<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Oct 25, 2013 at 2:12 AM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: majnemer<br>
Date: Fri Oct 25 04:12:52 2013<br>
New Revision: 193397<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=193397&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=193397&view=rev</a><br>
Log:<br>
Sema: Do not allow lambda expressions to appear inside of constant expressions<br>
<br>
We would previously not diagnose this which would lead to crashes (on<br>
very strange code).<br>
<br>
This fixes PR17675.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaLambda.cpp<br>
    cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp<br>
    cfe/trunk/test/SemaCXX/new-delete-0x.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=193397&r1=193396&r2=193397&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=193397&r1=193396&r2=193397&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 25 04:12:52 2013<br>
@@ -5067,6 +5067,8 @@ let CategoryName = "Lambda Issue" in {<br>
   def note_lambda_decl : Note<"lambda expression begins here">;<br>
   def err_lambda_unevaluated_operand : Error<<br>
     "lambda expression in an unevaluated operand">;<br>
+  def err_lambda_in_constant_expression : Error<<br>
+    "a lambda expression may not appear inside of a constant expression">;<br>
   def err_lambda_return_init_list : Error<<br>
     "cannot deduce lambda return type from initializer list">;<br>
   def err_lambda_capture_default_arg : Error<<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=193397&r1=193396&r2=193397&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=193397&r1=193396&r2=193397&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Oct 25 04:12:52 2013<br>
@@ -10962,13 +10962,22 @@ void Sema::PopExpressionEvaluationContex<br>
   ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();<br>
<br>
   if (!Rec.Lambdas.empty()) {<br>
-    if (Rec.isUnevaluated()) {<br>
-      // C++11 [expr.prim.lambda]p2:<br>
-      //   A lambda-expression shall not appear in an unevaluated operand<br>
-      //   (Clause 5).<br>
+    if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) {<br>
+      unsigned D;<br>
+      if (Rec.isUnevaluated()) {<br>
+        // C++11 [expr.prim.lambda]p2:<br>
+        //   A lambda-expression shall not appear in an unevaluated operand<br>
+        //   (Clause 5).<br>
+        D = diag::err_lambda_unevaluated_operand;<br>
+      } else {<br>
+        // C++1y [expr.const]p2:<br>
+        //   A conditional-expression e is a core constant expression unless the<br>
+        //   evaluation of e, following the rules of the abstract machine, would<br>
+        //   evaluate [...] a lambda-expression.<br></blockquote><div><br></div><div>Can we get a better comment here? This is not what the language rule says: a lambda is allowed as a subexpression of a constant expression if it happens to not be evaluated during the evaluation of the core constant expression. For instance: 0 && []{return false;}() is currently allowed. Instead, say this is subject to a DR (and if you can dig out the number, that'd be great).</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        D = diag::err_lambda_in_constant_expression;<br>
+      }<br>
       for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)<br>
-        Diag(Rec.Lambdas[I]->getLocStart(),<br>
-             diag::err_lambda_unevaluated_operand);<br>
+        Diag(Rec.Lambdas[I]->getLocStart(), D);<br>
     } else {<br>
       // Mark the capture expressions odr-used. This was deferred<br>
       // during lambda expression creation.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=193397&r1=193396&r2=193397&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=193397&r1=193396&r2=193397&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Oct 25 04:12:52 2013<br>
@@ -1229,20 +1229,25 @@ ExprResult Sema::ActOnLambdaExpr(SourceL<br>
                                           CaptureInits, ArrayIndexVars,<br>
                                           ArrayIndexStarts, Body->getLocEnd(),<br>
                                           ContainsUnexpandedParameterPack);<br>
-  // C++11 [expr.prim.lambda]p2:<br>
-  //   A lambda-expression shall not appear in an unevaluated operand<br>
-  //   (Clause 5).<br>
+<br>
   if (!CurContext->isDependentContext()) {<br>
     switch (ExprEvalContexts.back().Context) {<br>
+    // C++11 [expr.prim.lambda]p2:<br>
+    //   A lambda-expression shall not appear in an unevaluated operand<br>
+    //   (Clause 5).<br>
     case Unevaluated:<br>
     case UnevaluatedAbstract:<br>
+    // C++1y [expr.const]p2:<br>
+    //   A conditional-expression e is a core constant expression unless the<br>
+    //   evaluation of e, following the rules of the abstract machine, would<br>
+    //   evaluate [...] a lambda-expression.<br>
+    case ConstantEvaluated:<br>
       // We don't actually diagnose this case immediately, because we<br>
       // could be within a context where we might find out later that<br>
       // the expression is potentially evaluated (e.g., for typeid).<br>
       ExprEvalContexts.back().Lambdas.push_back(Lambda);<br>
       break;<br>
<br>
-    case ConstantEvaluated:<br>
     case PotentiallyEvaluated:<br>
     case PotentiallyEvaluatedIfUsed:<br>
       break;<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=193397&r1=193396&r2=193397&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=193397&r1=193396&r2=193397&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Fri Oct 25 04:12:52 2013<br>
@@ -275,9 +275,7 @@ namespace UndefinedBehavior {<br>
<br>
 // - a lambda-expression (5.1.2);<br>
 struct Lambda {<br>
-  // FIXME: clang crashes when trying to parse this! Revisit this check once<br>
-  // lambdas are fully implemented.<br>
-  //int n : []{ return 1; }();<br>
+  int n : []{ return 1; }(); // expected-error {{constant expression}} expected-error {{integral constant expression}}<br>
 };<br>
<br>
 // - an lvalue-to-rvalue conversion (4.1) unless it is applied to<br>
<br>
Modified: cfe/trunk/test/SemaCXX/new-delete-0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete-0x.cpp?rev=193397&r1=193396&r2=193397&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete-0x.cpp?rev=193397&r1=193396&r2=193397&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/new-delete-0x.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/new-delete-0x.cpp Fri Oct 25 04:12:52 2013<br>
@@ -21,7 +21,9 @@ void bad_news(int *ip)<br>
   auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected ']'}}<br>
   // ... but not here:<br>
   auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot appear here}}<br>
-  auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} expected-error {{variably modified type}}<br>
+  auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} \<br>
+                                                expected-error {{variably modified type}} \<br>
+                                                expected-error {{a lambda expression may not appear inside of a constant expression}}<br>
 }<br>
<br>
 void good_deletes()<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>