[clang] 06774d6 - [clang][Interp] Handle CXXInheritedCtorInitExprs
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 8 06:36:24 PST 2024
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);
+ }
+}
More information about the cfe-commits
mailing list