[clang] e34b41c - [clang][Interp] Support CXXParenListInitExprs for non-record types
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 29 07:34:03 PDT 2024
Author: Timm Bäder
Date: 2024-04-29T16:30:13+02:00
New Revision: e34b41c707a8cc589725d5f996e1a40e9631a495
URL: https://github.com/llvm/llvm-project/commit/e34b41c707a8cc589725d5f996e1a40e9631a495
DIFF: https://github.com/llvm/llvm-project/commit/e34b41c707a8cc589725d5f996e1a40e9631a495.diff
LOG: [clang][Interp] Support CXXParenListInitExprs for non-record types
Merge the non-record code paths into visitInitList().
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/test/AST/Interp/records.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 0a93a6a198a9de..accaea0a84424c 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1023,125 +1023,98 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
template <class Emitter>
bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
+ const Expr *ArrayFiller,
const Expr *E) {
- assert(E->getType()->isRecordType());
- const Record *R = getRecord(E->getType());
+ if (E->getType()->isVoidType())
+ return this->emitInvalid(E);
- if (Inits.size() == 1 && E->getType() == Inits[0]->getType()) {
- return this->visitInitializer(Inits[0]);
+ // Handle discarding first.
+ if (DiscardResult) {
+ for (const Expr *Init : Inits) {
+ if (!this->discard(Init))
+ return false;
+ }
+ return true;
}
- unsigned InitIndex = 0;
- for (const Expr *Init : Inits) {
- // Skip unnamed bitfields.
- while (InitIndex < R->getNumFields() &&
- R->getField(InitIndex)->Decl->isUnnamedBitField())
- ++InitIndex;
+ // Primitive values.
+ if (std::optional<PrimType> T = classify(E->getType())) {
+ assert(!DiscardResult);
+ if (Inits.size() == 0)
+ return this->visitZeroInitializer(*T, E->getType(), E);
+ assert(Inits.size() == 1);
+ return this->delegate(Inits[0]);
+ }
- if (!this->emitDupPtr(E))
- return false;
+ QualType T = E->getType();
+ if (T->isRecordType()) {
+ const Record *R = getRecord(E->getType());
- if (std::optional<PrimType> T = classify(Init)) {
- const Record::Field *FieldToInit = R->getField(InitIndex);
- if (!this->visit(Init))
- return false;
+ if (Inits.size() == 1 && E->getType() == Inits[0]->getType()) {
+ return this->visitInitializer(Inits[0]);
+ }
- if (FieldToInit->isBitField()) {
- if (!this->emitInitBitField(*T, FieldToInit, E))
- return false;
- } else {
- if (!this->emitInitField(*T, FieldToInit->Offset, E))
- return false;
- }
+ unsigned InitIndex = 0;
+ for (const Expr *Init : Inits) {
+ // Skip unnamed bitfields.
+ while (InitIndex < R->getNumFields() &&
+ R->getField(InitIndex)->Decl->isUnnamedBitField())
+ ++InitIndex;
- if (!this->emitPopPtr(E))
+ if (!this->emitDupPtr(E))
return false;
- ++InitIndex;
- } else {
- // Initializer for a direct base class.
- if (const Record::Base *B = R->getBase(Init->getType())) {
- if (!this->emitGetPtrBasePop(B->Offset, Init))
- return false;
-
- if (!this->visitInitializer(Init))
- return false;
- if (!this->emitFinishInitPop(E))
- return false;
- // Base initializers don't increase InitIndex, since they don't count
- // into the Record's fields.
- } else {
+ if (std::optional<PrimType> T = classify(Init)) {
const Record::Field *FieldToInit = R->getField(InitIndex);
- // Non-primitive case. Get a pointer to the field-to-initialize
- // on the stack and recurse into visitInitializer().
- if (!this->emitGetPtrField(FieldToInit->Offset, Init))
+ if (!this->visit(Init))
return false;
- if (!this->visitInitializer(Init))
- return false;
+ if (FieldToInit->isBitField()) {
+ if (!this->emitInitBitField(*T, FieldToInit, E))
+ return false;
+ } else {
+ if (!this->emitInitField(*T, FieldToInit->Offset, E))
+ return false;
+ }
if (!this->emitPopPtr(E))
return false;
++InitIndex;
- }
- }
- }
- return true;
-}
+ } else {
+ // Initializer for a direct base class.
+ if (const Record::Base *B = R->getBase(Init->getType())) {
+ if (!this->emitGetPtrBasePop(B->Offset, Init))
+ return false;
-/// Pointer to the array(not the element!) must be on the stack when calling
-/// this.
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
- const Expr *Init) {
- if (std::optional<PrimType> T = classify(Init->getType())) {
- // Visit the primitive element like normal.
- if (!this->visit(Init))
- return false;
- return this->emitInitElem(*T, ElemIndex, Init);
- }
+ if (!this->visitInitializer(Init))
+ return false;
- // Advance the pointer currently on the stack to the given
- // dimension.
- if (!this->emitConstUint32(ElemIndex, Init))
- return false;
- if (!this->emitArrayElemPtrUint32(Init))
- return false;
- if (!this->visitInitializer(Init))
- return false;
- return this->emitFinishInitPop(Init);
-}
+ if (!this->emitFinishInitPop(E))
+ return false;
+ // Base initializers don't increase InitIndex, since they don't count
+ // into the Record's fields.
+ } else {
+ const Record::Field *FieldToInit = R->getField(InitIndex);
+ // Non-primitive case. Get a pointer to the field-to-initialize
+ // on the stack and recurse into visitInitializer().
+ if (!this->emitGetPtrField(FieldToInit->Offset, Init))
+ return false;
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
- if (E->getType()->isVoidType())
- return this->emitInvalid(E);
+ if (!this->visitInitializer(Init))
+ return false;
- // Handle discarding first.
- if (DiscardResult) {
- for (const Expr *Init : E->inits()) {
- if (!this->discard(Init))
- return false;
+ if (!this->emitPopPtr(E))
+ return false;
+ ++InitIndex;
+ }
+ }
}
return true;
}
- // Primitive values.
- if (std::optional<PrimType> T = classify(E->getType())) {
- assert(!DiscardResult);
- if (E->getNumInits() == 0)
- return this->visitZeroInitializer(*T, E->getType(), E);
- assert(E->getNumInits() == 1);
- return this->delegate(E->inits()[0]);
- }
-
- QualType T = E->getType();
- if (T->isRecordType())
- return this->visitInitList(E->inits(), E);
-
if (T->isArrayType()) {
unsigned ElementIndex = 0;
- for (const Expr *Init : E->inits()) {
+ for (const Expr *Init : Inits) {
if (!this->visitArrayElemInit(ElementIndex, Init))
return false;
++ElementIndex;
@@ -1149,13 +1122,13 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
// Expand the filler expression.
// FIXME: This should go away.
- if (const Expr *Filler = E->getArrayFiller()) {
+ if (ArrayFiller) {
const ConstantArrayType *CAT =
Ctx.getASTContext().getAsConstantArrayType(E->getType());
uint64_t NumElems = CAT->getZExtSize();
for (; ElementIndex != NumElems; ++ElementIndex) {
- if (!this->visitArrayElemInit(ElementIndex, Filler))
+ if (!this->visitArrayElemInit(ElementIndex, ArrayFiller))
return false;
}
}
@@ -1164,10 +1137,10 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
}
if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
- unsigned NumInits = E->getNumInits();
+ unsigned NumInits = Inits.size();
if (NumInits == 1)
- return this->delegate(E->inits()[0]);
+ return this->delegate(Inits[0]);
QualType ElemQT = ComplexTy->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
@@ -1181,7 +1154,7 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
}
} else if (NumInits == 2) {
unsigned InitIndex = 0;
- for (const Expr *Init : E->inits()) {
+ for (const Expr *Init : Inits) {
if (!this->visit(Init))
return false;
@@ -1195,14 +1168,14 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
if (const auto *VecT = E->getType()->getAs<VectorType>()) {
unsigned NumVecElements = VecT->getNumElements();
- assert(NumVecElements >= E->getNumInits());
+ assert(NumVecElements >= Inits.size());
QualType ElemQT = VecT->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
// All initializer elements.
unsigned InitIndex = 0;
- for (const Expr *Init : E->inits()) {
+ for (const Expr *Init : Inits) {
if (!this->visit(Init))
return false;
@@ -1224,19 +1197,38 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
return false;
}
+/// Pointer to the array(not the element!) must be on the stack when calling
+/// this.
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
+ const Expr *Init) {
+ if (std::optional<PrimType> T = classify(Init->getType())) {
+ // Visit the primitive element like normal.
+ if (!this->visit(Init))
+ return false;
+ return this->emitInitElem(*T, ElemIndex, Init);
+ }
+
+ // Advance the pointer currently on the stack to the given
+ // dimension.
+ if (!this->emitConstUint32(ElemIndex, Init))
+ return false;
+ if (!this->emitArrayElemPtrUint32(Init))
+ return false;
+ if (!this->visitInitializer(Init))
+ return false;
+ return this->emitFinishInitPop(Init);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
+ return this->visitInitList(E->inits(), E->getArrayFiller(), E);
+}
+
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitCXXParenListInitExpr(
const CXXParenListInitExpr *E) {
- if (DiscardResult) {
- for (const Expr *Init : E->getInitExprs()) {
- if (!this->discard(Init))
- return false;
- }
- return true;
- }
-
- assert(E->getType()->isRecordType());
- return this->visitInitList(E->getInitExprs(), E);
+ return this->visitInitList(E->getInitExprs(), E->getArrayFiller(), E);
}
template <class Emitter>
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 2c3127968a1c77..a89e37c67aa67c 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -225,7 +225,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
return this->emitFinishInitPop(I);
}
- bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E);
+ bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
+ const Expr *E);
bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init);
/// Creates a local primitive value.
diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp
index 866fa7240d2fae..771e5adfca34a4 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1030,6 +1030,12 @@ namespace ParenInit {
// both-note {{required by 'constinit' specifier}} \
// both-note {{reference to temporary is not a constant expression}} \
// both-note {{temporary created here}}
+
+
+ /// Initializing an array.
+ constexpr void bar(int i, int j) {
+ int arr[4](i, j);
+ }
}
#endif
More information about the cfe-commits
mailing list