Author: Timm Bäder Date: 2024-02-08T15:36:07+01:00 New Revision: 06774d6bbf32aff45b67d8c3753524ec36bf8869
URL: https://github.com/llvm/llvm-project/commit/06774d6bbf32aff45b67d8c3753524ec36bf8869 DIFF: https://github.com/llvm/llvm-project/commit/06774d6bbf32aff45b67d8c3753524ec36bf8869.diff LOG: [clang][Interp] Handle CXXInheritedCtorInitExprs We need to forward all arguments of the current function and call the ctor function. 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 59fddfc2da1957..21bc29ff8ee2e5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2020,6 +2020,37 @@ bool ByteCodeExprGen<Emitter>::VisitObjCBoolLiteralExpr( return this->emitConst(E->getValue(), E); } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitCXXInheritedCtorInitExpr( + const CXXInheritedCtorInitExpr *E) { + const CXXConstructorDecl *Ctor = E->getConstructor(); + assert(!Ctor->isTrivial() && + "Trivial CXXInheritedCtorInitExpr, implement. (possible?)"); + const Function *F = this->getFunction(Ctor); + assert(F); + assert(!F->hasRVO()); + assert(F->hasThisPointer()); + + if (!this->emitDupPtr(SourceInfo{})) + return false; + + // Forward all arguments of the current function (which should be a + // constructor itself) to the inherited ctor. + // This is necessary because the calling code has pushed the pointer + // of the correct base for us already, but the arguments need + // to come after. + unsigned Offset = align(primSize(PT_Ptr)); // instance pointer. + for (const ParmVarDecl *PD : Ctor->parameters()) { + PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr); + + if (!this->emitGetParam(PT, Offset, E)) + return false; + Offset += align(primSize(PT)); + } + + return this->emitCall(F, E); +} + template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { if (E->containsErrors()) return false; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 2c9cca5082b121..c908a9bf1ef834 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -111,6 +111,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, bool VisitGenericSelectionExpr(const GenericSelectionExpr *E); bool VisitChooseExpr(const ChooseExpr *E); bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E); + bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 5ce1e6e09a0b74..1ef13f558b753c 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1223,3 +1223,63 @@ namespace IndirectFieldInit { #endif } + +namespace InheritedConstructor { + namespace PR47555 { + struct A { + int c; + int d; + constexpr A(int c, int d) : c(c), d(d){} + }; + struct B : A { using A::A; }; + + constexpr B b = {13, 1}; + static_assert(b.c == 13, ""); + static_assert(b.d == 1, ""); + } + + namespace PR47555_2 { + struct A { + int c; + int d; + double e; + constexpr A(int c, int &d, double e) : c(c), d(++d), e(e){} + }; + struct B : A { using A::A; }; + + constexpr int f() { + int a = 10; + B b = {10, a, 40.0}; + return a; + } + static_assert(f() == 11, ""); + } + + namespace AaronsTest { + struct T { + constexpr T(float) {} + }; + + struct Base { + constexpr Base(T t = 1.0f) {} + constexpr Base(float) {} + }; + + struct FirstMiddle : Base { + using Base::Base; + constexpr FirstMiddle() : Base(2.0f) {} + }; + + struct SecondMiddle : Base { + constexpr SecondMiddle() : Base(3.0f) {} + constexpr SecondMiddle(T t) : Base(t) {} + }; + + struct S : FirstMiddle, SecondMiddle { + using FirstMiddle::FirstMiddle; + constexpr S(int i) : S(4.0f) {} + }; + + constexpr S s(1); + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits