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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits