tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

  We need to run the functions we compiled immediately after to check if
  they can ever be a constant expression.

I removed this before, thinking it was unneeded. Turns out it is needed to get 
the "constexpr function never produces a constant expression" diagnostics.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140724

Files:
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/test/AST/Interp/arrays.cpp
  clang/test/AST/Interp/literals.cpp
  clang/test/AST/Interp/records.cpp
  clang/test/AST/Interp/shifts.cpp

Index: clang/test/AST/Interp/shifts.cpp
===================================================================
--- clang/test/AST/Interp/shifts.cpp
+++ 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}} \
Index: clang/test/AST/Interp/records.cpp
===================================================================
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -166,10 +166,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}} \
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ 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}} \
Index: clang/test/AST/Interp/arrays.cpp
===================================================================
--- clang/test/AST/Interp/arrays.cpp
+++ 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
   }
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -1298,6 +1298,8 @@
 
 inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
   assert(S.Current->getFunction()->hasRVO());
+  if (S.checkingPotentialConstantExpression())
+    return false;
   S.Stk.push<Pointer>(S.Current->getRVOPtr());
   return true;
 }
@@ -1375,9 +1377,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))
Index: clang/lib/AST/Interp/Interp.cpp
===================================================================
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -350,6 +350,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();
Index: clang/lib/AST/Interp/Context.cpp
===================================================================
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -42,6 +42,11 @@
     }
   }
 
+  APValue DummyResult;
+  if (!Run(Parent, Func, DummyResult)) {
+    return false;
+  }
+
   return Func->isConstexpr();
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to