<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>