diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -91,6 +91,8 @@ bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E); bool VisitExprWithCleanups(const ExprWithCleanups *E); bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); + bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E); + bool VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *E); bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); bool VisitTypeTraitExpr(const TypeTraitExpr *E); bool VisitLambdaExpr(const LambdaExpr *E); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -886,6 +886,24 @@ return false; } +template +bool ByteCodeExprGen::VisitCXXBindTemporaryExpr( + const CXXBindTemporaryExpr *E) { + + return this->visit(E->getSubExpr()); +} + +template +bool ByteCodeExprGen::VisitCXXTemporaryObjectExpr( + const CXXTemporaryObjectExpr *E) { + + if (std::optional LocalIndex = + allocateLocal(E, /*IsExtended=*/false)) { + return this->visitLocalInitializer(E, *LocalIndex); + } + return false; +} + template bool ByteCodeExprGen::VisitCompoundLiteralExpr( const CompoundLiteralExpr *E) { 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 @@ -311,16 +311,36 @@ int Pos = 0; { - auto T = Test(Arr, Pos); + 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); + + // Invalid destructor. + struct S { + constexpr S() {} + constexpr ~S() noexcept(false) { throw 12; } // expected-error {{cannot use 'throw'}} \ + // expected-note {{declared here}} \ + // ref-error {{cannot use 'throw'}} \ + // ref-error {{never produces a constant expression}} \ + // ref-note 2{{subexpression not valid}} + }; + + constexpr int f() { + S{}; // ref-note {{in call to 'S{}.~S()'}} + return 12; // expected-note {{undefined function '~S'}} + } + static_assert(f() == 12); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'f()'}} \ + // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'f()'}} + + #endif } @@ -572,17 +592,18 @@ constexpr ~S() { // expected-error {{never produces a constant expression}} \ // ref-error {{never produces a constant expression}} int i = 1 / 0; // expected-warning {{division by zero}} \ - // expected-note {{division by zero}} \ + // expected-note 2{{division by zero}} \ // ref-warning {{division by zero}} \ // ref-note 2{{division by zero}} } }; constexpr int testS() { S{}; // ref-note {{in call to 'S{}.~S()'}} - return 1; + return 1; // expected-note {{in call to '&S{}->~S()'}} // FIXME: ^ Wrong line } static_assert(testS() == 1); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'testS()'}} \ // ref-error {{not an integral constant expression}} \ // ref-note {{in call to 'testS()'}} }