diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -42,6 +42,11 @@ } } + APValue DummyResult; + if (!Run(Parent, Func, DummyResult)) { + return false; + } + return Func->isConstexpr(); } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1311,6 +1311,8 @@ inline bool RVOPtr(InterpState &S, CodePtr OpPC) { assert(S.Current->getFunction()->hasRVO()); + if (S.checkingPotentialConstantExpression()) + return false; S.Stk.push(S.Current->getRVOPtr()); return true; } @@ -1383,9 +1385,11 @@ Pointer ThisPtr; if (Func->hasThisPointer()) { ThisPtr = NewFrame->getThis(); - if (!CheckInvoke(S, PC, ThisPtr)) { + if (!CheckInvoke(S, PC, ThisPtr)) + return false; + + if (S.checkingPotentialConstantExpression()) return false; - } } if (!CheckCallable(S, PC, Func)) diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -342,6 +342,11 @@ } if (!F->isConstexpr()) { + // Don't emit anything if we're checking for a potential constant + // expression. That will happen later when actually executing. + if (S.checkingPotentialConstantExpression()) + return false; + const SourceLocation &Loc = S.Current->getLocation(OpPC); if (S.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = F->getDecl(); diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -209,7 +209,8 @@ public: int a; constexpr AU() : a(5 / 0) {} // expected-warning {{division by zero is undefined}} \ - // expected-note {{division by zero}} \ + // expected-note 2{{division by zero}} \ + // expected-error {{never produces a constant expression}} \ // ref-error {{never produces a constant expression}} \ // ref-note 2{{division by zero}} \ // ref-warning {{division by zero is undefined}} @@ -296,10 +297,11 @@ } static_assert(getSecondToLast2() == 3, ""); - constexpr int bad1() { // ref-error {{never produces a constant expression}} + constexpr int bad1() { // ref-error {{never produces a constant expression}} \ + // expected-error {{never produces a constant expression}} const int *e = E + 3; e++; // This is fine because it's a one-past-the-end pointer - return *e; // expected-note {{read of dereferenced one-past-the-end pointer}} \ + return *e; // expected-note 2{{read of dereferenced one-past-the-end pointer}} \ // ref-note 2{{read of dereferenced one-past-the-end pointer}} } static_assert(bad1() == 0, ""); // expected-error {{not an integral constant expression}} \ @@ -307,9 +309,10 @@ // ref-error {{not an integral constant expression}} \ // ref-note {{in call to}} - constexpr int bad2() { // ref-error {{never produces a constant expression}} + constexpr int bad2() { // ref-error {{never produces a constant expression}} \ + // expected-error {{never produces a constant expression}} const int *e = E + 4; - e++; // expected-note {{cannot refer to element 5 of array of 4 elements}} \ + e++; // expected-note 2{{cannot refer to element 5 of array of 4 elements}} \ // ref-note 2{{cannot refer to element 5 of array of 4 elements}} return *e; // This is UB as well } @@ -319,9 +322,10 @@ // ref-note {{in call to}} - constexpr int bad3() { // ref-error {{never produces a constant expression}} + constexpr int bad3() { // ref-error {{never produces a constant expression}} \ + // expected-error {{never produces a constant expression}} const int *e = E; - e--; // expected-note {{cannot refer to element -1 of array of 4 elements}} \ + e--; // expected-note 2{{cannot refer to element -1 of array of 4 elements}} \ // ref-note 2{{cannot refer to element -1 of array of 4 elements}} return *e; // This is UB as well } diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -452,10 +452,11 @@ static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit()'}} - constexpr int OverFlow() { // ref-error {{never produces a constant expression}} + constexpr int OverFlow() { // ref-error {{never produces a constant expression}} \ + // expected-error {{never produces a constant expression}} int a = INT_MAX; ++a; // ref-note 2{{is outside the range}} \ - // expected-note {{is outside the range}} + // expected-note 2{{is outside the range}} return -1; } static_assert(OverFlow() == -1, ""); // expected-error {{not an integral constant expression}} \ @@ -464,10 +465,11 @@ // ref-note {{in call to 'OverFlow()'}} - constexpr int UnderFlow() { // ref-error {{never produces a constant expression}} + constexpr int UnderFlow() { // ref-error {{never produces a constant expression}} \ + // expected-error {{never produces a constant expression}} int a = INT_MIN; --a; // ref-note 2{{is outside the range}} \ - // expected-note {{is outside the range}} + // expected-note 2{{is outside the range}} return -1; } static_assert(UnderFlow() == -1, ""); // expected-error {{not an integral constant expression}} \ 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 @@ -174,10 +174,11 @@ constexpr int get12() { return 12; } }; - constexpr int foo() { // ref-error {{never produces a constant expression}} + constexpr int foo() { // ref-error {{never produces a constant expression}} \ + // expected-error {{never produces a constant expression}} S *s = nullptr; return s->get12(); // ref-note 2{{member call on dereferenced null pointer}} \ - // expected-note {{member call on dereferenced null pointer}} + // expected-note 2{{member call on dereferenced null pointer}} } static_assert(foo() == 12, ""); // ref-error {{not an integral constant expression}} \ diff --git a/clang/test/AST/Interp/shifts.cpp b/clang/test/AST/Interp/shifts.cpp --- a/clang/test/AST/Interp/shifts.cpp +++ b/clang/test/AST/Interp/shifts.cpp @@ -8,7 +8,9 @@ namespace shifts { constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \ - // ref-cxx17-error {{constexpr function never produces a constant expression}} + // ref-cxx17-error {{constexpr function never produces a constant expression}} \ + // expected-error {{constexpr function never produces a constant expression}} \ + // cxx17-error {{constexpr function never produces a constant expression}} \ char c; // cxx17-warning {{uninitialized variable}} \ // ref-cxx17-warning {{uninitialized variable}} @@ -19,6 +21,8 @@ c = 1 << -0; c = 1 >> -0; c = 1 << -1; // expected-warning {{shift count is negative}} \ + // expected-note {{negative shift count -1}} \ + // cxx17-note {{negative shift count -1}} \ // cxx17-warning {{shift count is negative}} \ // ref-warning {{shift count is negative}} \ // ref-note {{negative shift count -1}} \