aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2024-11-25 12:15:31 +0100
committerGitHub <noreply@github.com>2024-11-25 12:15:31 +0100
commitceaf6e912a846b88f19df682c6bdbe9516be04e9 (patch)
tree44b88a7b4d3a0ceb3f81407c4b24cdd049081e32 /clang/lib
parente477989a055f92f6ca63fc8f76929cde81d33e44 (diff)
downloadllvm-ceaf6e912a846b88f19df682c6bdbe9516be04e9.zip
llvm-ceaf6e912a846b88f19df682c6bdbe9516be04e9.tar.gz
llvm-ceaf6e912a846b88f19df682c6bdbe9516be04e9.tar.bz2
[clang][bytecode] Support ImplicitValueInitExpr for multi-dim arrays (#117312)
The attached test case from https://github.com/llvm/llvm-project/issues/117294 used to cause an assertion because we called classifPrim() on an array type. The new result doesn't crash but isn't exactly perfect either. Since the problem arises when evaluating an ImplicitValueInitExpr, we have no proper source location to point to. Point to the caller instead.
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp79
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h1
-rw-r--r--clang/lib/AST/ByteCode/InterpFrame.cpp7
3 files changed, 58 insertions, 29 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 3d8215f..6add18e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1642,22 +1642,8 @@ bool Compiler<Emitter>::VisitImplicitValueInitExpr(
if (QT->isIncompleteArrayType())
return true;
- if (QT->isArrayType()) {
- const ArrayType *AT = QT->getAsArrayTypeUnsafe();
- assert(AT);
- const auto *CAT = cast<ConstantArrayType>(AT);
- size_t NumElems = CAT->getZExtSize();
- PrimType ElemT = classifyPrim(CAT->getElementType());
-
- for (size_t I = 0; I != NumElems; ++I) {
- if (!this->visitZeroInitializer(ElemT, CAT->getElementType(), E))
- return false;
- if (!this->emitInitElem(ElemT, I, E))
- return false;
- }
-
- return true;
- }
+ if (QT->isArrayType())
+ return this->visitZeroArrayInitializer(QT, E);
if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
assert(Initializing);
@@ -3916,18 +3902,9 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
return false;
}
} else if (D->isCompositeArray()) {
- const Record *ElemRecord = D->ElemDesc->ElemRecord;
- assert(D->ElemDesc->ElemRecord);
- for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {
- if (!this->emitConstUint32(I, E))
- return false;
- if (!this->emitArrayElemPtr(PT_Uint32, E))
- return false;
- if (!this->visitZeroRecordInitializer(ElemRecord, E))
- return false;
- if (!this->emitPopPtr(E))
- return false;
- }
+ // Can't be a vector or complex field.
+ if (!this->visitZeroArrayInitializer(D->getType(), E))
+ return false;
} else if (D->isRecord()) {
if (!this->visitZeroRecordInitializer(D->ElemRecord, E))
return false;
@@ -3959,6 +3936,52 @@ bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
}
template <class Emitter>
+bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
+ assert(T->isArrayType() || T->isAnyComplexType() || T->isVectorType());
+ const ArrayType *AT = T->getAsArrayTypeUnsafe();
+ QualType ElemType = AT->getElementType();
+ size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();
+
+ if (std::optional<PrimType> ElemT = classify(ElemType)) {
+ for (size_t I = 0; I != NumElems; ++I) {
+ if (!this->visitZeroInitializer(*ElemT, ElemType, E))
+ return false;
+ if (!this->emitInitElem(*ElemT, I, E))
+ return false;
+ }
+ return true;
+ } else if (ElemType->isRecordType()) {
+ const Record *R = getRecord(ElemType);
+
+ for (size_t I = 0; I != NumElems; ++I) {
+ if (!this->emitConstUint32(I, E))
+ return false;
+ if (!this->emitArrayElemPtr(PT_Uint32, E))
+ return false;
+ if (!this->visitZeroRecordInitializer(R, E))
+ return false;
+ if (!this->emitPopPtr(E))
+ return false;
+ }
+ return true;
+ } else if (ElemType->isArrayType()) {
+ for (size_t I = 0; I != NumElems; ++I) {
+ if (!this->emitConstUint32(I, E))
+ return false;
+ if (!this->emitArrayElemPtr(PT_Uint32, E))
+ return false;
+ if (!this->visitZeroArrayInitializer(ElemType, E))
+ return false;
+ if (!this->emitPopPtr(E))
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+template <class Emitter>
template <typename T>
bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
switch (Ty) {
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index d1b624d..2a94f5e 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -325,6 +325,7 @@ private:
/// Emits a zero initializer.
bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
bool visitZeroRecordInitializer(const Record *R, const Expr *E);
+ bool visitZeroArrayInitializer(QualType T, const Expr *E);
/// Emits an APSInt constant.
bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E);
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp
index 7f02464..20f67d9 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -234,7 +234,12 @@ SourceInfo InterpFrame::getSource(CodePtr PC) const {
if (Func && !funcHasUsableBody(Func) && Caller)
return Caller->getSource(RetPC);
- return S.getSource(Func, PC);
+ // Similarly, if the resulting source location is invalid anyway,
+ // point to the caller instead.
+ SourceInfo Result = S.getSource(Func, PC);
+ if (Result.getLoc().isInvalid() && Caller)
+ return Caller->getSource(RetPC);
+ return Result;
}
const Expr *InterpFrame::getExpr(CodePtr PC) const {