Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -97,6 +97,7 @@ bool VisitTypeTraitExpr(const TypeTraitExpr *E); bool VisitLambdaExpr(const LambdaExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E); + bool VisitCXXThrowExpr(const CXXThrowExpr *E); protected: bool visitExpr(const Expr *E) override; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1102,6 +1102,14 @@ return this->visit(E->getFunctionName()); } +template +bool ByteCodeExprGen::VisitCXXThrowExpr(const CXXThrowExpr *E) { + if (!this->discard(E->getSubExpr())) + return false; + + return this->emitUnsupported(E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->containsErrors()) return false; Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1823,6 +1823,14 @@ return true; } +/// Just emit a diagnostic. The expression that caused emission of this +/// op is not valid in a constant context. +inline bool Unsupported(InterpState &S, CodePtr OpPC) { + const SourceLocation &Loc = S.Current->getLocation(OpPC); + S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); + return false; +} + //===----------------------------------------------------------------------===// // Read opcode arguments //===----------------------------------------------------------------------===// Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -627,3 +627,6 @@ let Types = [AllTypeClass]; let HasGroup = 1; } + +// [] -> [] +def Unsupported : Opcode {} Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -328,7 +328,8 @@ struct S { constexpr S() {} constexpr ~S() noexcept(false) { throw 12; } // expected-error {{cannot use 'throw'}} \ - // expected-note {{declared here}} \ + // expected-error {{never produces a constant expression}} \ + // expected-note 2{{subexpression not valid}} \ // ref-error {{cannot use 'throw'}} \ // ref-error {{never produces a constant expression}} \ // ref-note 2{{subexpression not valid}} @@ -336,7 +337,9 @@ constexpr int f() { S{}; // ref-note {{in call to '&S{}->~S()'}} - return 12; // expected-note {{undefined function '~S'}} + + /// FIXME: Wrong source location below. + return 12; // expected-note {{in call to '&S{}->~S()'}} } static_assert(f() == 12); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'f()'}} \ Index: clang/test/AST/Interp/unsupported.cpp =================================================================== --- /dev/null +++ clang/test/AST/Interp/unsupported.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -fcxx-exceptions -verify=ref %s + + + +namespace Throw { + + constexpr int ConditionalThrow(bool t) { + if (t) + throw 4; // expected-note {{subexpression not valid in a constant expression}} \ + // ref-note {{subexpression not valid in a constant expression}} + + return 0; + } + + static_assert(ConditionalThrow(false) == 0, ""); + static_assert(ConditionalThrow(true) == 0, ""); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to 'ConditionalThrow(true)'}} \ + // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to 'ConditionalThrow(true)'}} + + constexpr int Throw() { // expected-error {{never produces a constant expression}} \ + // ref-error {{never produces a constant expression}} + throw 5; // expected-note {{subexpression not valid in a constant expression}} \ + // ref-note {{subexpression not valid in a constant expression}} + return 0; + } +}