r286748 - Fix PR28366: Handle variables from enclosing local scopes more gracefully during constant expression evaluation.

Faisal Vali via cfe-commits cfe-commits at lists.llvm.org
Sat Nov 12 22:09:16 PST 2016


Author: faisalv
Date: Sun Nov 13 00:09:16 2016
New Revision: 286748

URL: http://llvm.org/viewvc/llvm-project?rev=286748&view=rev
Log:
Fix PR28366: Handle variables from enclosing local scopes more gracefully during constant expression evaluation.

Only look for a variable's value in the constant expression evaluation activation frame, if the variable was indeed declared in that frame, otherwise it might be a constant expression and be usable within a nested local scope or emit an error.


void f(char c) { 
  struct X {
    static constexpr char f() { 
      return c; // error gracefully here as opposed to crashing.
    }
  };
  int I = X::f();
}


Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
    cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=286748&r1=286747&r2=286748&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Nov 13 00:09:16 2016
@@ -4803,10 +4803,21 @@ bool LValueExprEvaluator::VisitDeclRefEx
   return Error(E);
 }
 
+
 bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
   CallStackFrame *Frame = nullptr;
-  if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1)
-    Frame = Info.CurrentCall;
+  if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) {
+    // Only if a local variable was declared in the function currently being
+    // evaluated, do we expect to be able to find its value in the current
+    // frame. (Otherwise it was likely declared in an enclosing context and
+    // could either have a valid evaluatable value (for e.g. a constexpr
+    // variable) or be ill-formed (and trigger an appropriate evaluation
+    // diagnostic)).
+    if (Info.CurrentCall->Callee &&
+        Info.CurrentCall->Callee->Equals(VD->getDeclContext())) {
+      Frame = Info.CurrentCall;
+    }
+  }
 
   if (!VD->getType()->isReferenceType()) {
     if (Frame) {

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=286748&r1=286747&r2=286748&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Nov 13 00:09:16 2016
@@ -188,7 +188,7 @@ static void instantiateDependentEnableIf
 
   SmallVector<PartialDiagnosticAt, 8> Diags;
   if (A->getCond()->isValueDependent() && !Cond->isValueDependent() &&
-      !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(Tmpl),
+      !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(New),
                                                 Diags)) {
     S.Diag(A->getLocation(), diag::err_enable_if_never_constant_expr);
     for (int I = 0, N = Diags.size(); I != N; ++I)

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=286748&r1=286747&r2=286748&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Sun Nov 13 00:09:16 2016
@@ -2066,3 +2066,33 @@ namespace InheritedCtor {
   constexpr Z z(1);
   static_assert(z.w == 1 && z.x == 2 && z.y == 3 && z.z == 4, "");
 }
+
+
+namespace PR28366 {
+namespace ns1 {
+
+void f(char c) { //expected-note2{{declared here}}
+  struct X {
+    static constexpr char f() { //expected-error{{never produces a constant expression}}
+      return c; //expected-error{{reference to local}} expected-note{{non-const variable}}
+    }
+  };
+  int I = X::f();
+}
+
+void g() {
+  const int c = 'c';
+  static const int d = 'd';
+  struct X {
+    static constexpr int f() {
+      return c + d;
+    }
+  };
+  static_assert(X::f() == 'c' + 'd',"");
+}
+
+
+} // end ns1
+
+} //end ns PR28366
+

Modified: cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp?rev=286748&r1=286747&r2=286748&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1z-constexpr-lambdas.cpp Sun Nov 13 00:09:16 2016
@@ -46,5 +46,17 @@ namespace ns3 {
 
 } // end ns test_constexpr_call
 
-#endif // ndef CPP14_AND_EARLIER
+namespace test_captureless_lambda {
+void f() {
+  const char c = 'c';
+  auto L = [] { return c; };
+  constexpr char C = L();
+}
+  
+void f(char c) { //expected-note{{declared here}}
+  auto L = [] { return c; }; //expected-error{{cannot be implicitly captured}} expected-note{{lambda expression begins here}}
+  int I = L();
+}
 
+}
+#endif // ndef CPP14_AND_EARLIER




More information about the cfe-commits mailing list