diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -102,6 +102,9 @@ return false; for (const auto *Init : Ctor->inits()) { + // Scope needed for the initializers. + BlockScope Scope(this); + const Expr *InitExpr = Init->getInit(); if (const FieldDecl *Member = Init->getMember()) { const Record::Field *F = R->getField(Member); diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -250,6 +250,78 @@ constexpr S s; static_assert(s.m() == 1, ""); +namespace InitializerTemporaries { + class Bar { + private: + int a; + + public: + constexpr Bar() : a(10) {} + constexpr int getA() const { return a; } + }; + + class Foo { + public: + int a; + + constexpr Foo() : a(Bar().getA()) {} + }; + constexpr Foo F; + static_assert(F.a == 10, ""); + + + /// Needs constexpr destructors. +#if __cplusplus >= 202002L + /// Does + /// Arr[Pos] = Value; + /// ++Pos; + /// in its destructor. + class BitSetter { + private: + int *Arr; + int &Pos; + int Value; + + public: + constexpr BitSetter(int *Arr, int &Pos, int Value) : + Arr(Arr), Pos(Pos), Value(Value) {} + + constexpr int getValue() const { return 0; } + constexpr ~BitSetter() { + Arr[Pos] = Value; + ++Pos; + } + }; + + class Test { + int a, b, c; + public: + constexpr Test(int *Arr, int &Pos) : + a(BitSetter(Arr, Pos, 1).getValue()), + b(BitSetter(Arr, Pos, 2).getValue()), + c(BitSetter(Arr, Pos, 3).getValue()) + {} + }; + + + constexpr int T(int Index) { + int Arr[] = {0, 0, 0}; + int Pos = 0; + + { + auto T = Test(Arr, Pos); + // End of scope, should destroy Test. + } + + return Arr[Index]; + } + + static_assert(T(0) == 1); + static_assert(T(1) == 2); + static_assert(T(2) == 3); +#endif +} + #if __cplusplus >= 201703L namespace BaseInit { class _A {public: int a;};