r193397 - Sema: Do not allow lambda expressions to appear inside of constant expressions

Richard Smith richard at metafoo.co.uk
Sun Nov 3 21:30:49 PST 2013


On Fri, Oct 25, 2013 at 2:12 AM, David Majnemer <david.majnemer at gmail.com>wrote:

> Author: majnemer
> Date: Fri Oct 25 04:12:52 2013
> New Revision: 193397
>
> URL: http://llvm.org/viewvc/llvm-project?rev=193397&view=rev
> Log:
> Sema: Do not allow lambda expressions to appear inside of constant
> expressions
>
> We would previously not diagnose this which would lead to crashes (on
> very strange code).
>
> This fixes PR17675.
>
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaLambda.cpp
>     cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
>     cfe/trunk/test/SemaCXX/new-delete-0x.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=193397&r1=193396&r2=193397&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 25
> 04:12:52 2013
> @@ -5067,6 +5067,8 @@ let CategoryName = "Lambda Issue" in {
>    def note_lambda_decl : Note<"lambda expression begins here">;
>    def err_lambda_unevaluated_operand : Error<
>      "lambda expression in an unevaluated operand">;
> +  def err_lambda_in_constant_expression : Error<
> +    "a lambda expression may not appear inside of a constant expression">;
>    def err_lambda_return_init_list : Error<
>      "cannot deduce lambda return type from initializer list">;
>    def err_lambda_capture_default_arg : Error<
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=193397&r1=193396&r2=193397&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Oct 25 04:12:52 2013
> @@ -10962,13 +10962,22 @@ void Sema::PopExpressionEvaluationContex
>    ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
>
>    if (!Rec.Lambdas.empty()) {
> -    if (Rec.isUnevaluated()) {
> -      // C++11 [expr.prim.lambda]p2:
> -      //   A lambda-expression shall not appear in an unevaluated operand
> -      //   (Clause 5).
> +    if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) {
> +      unsigned D;
> +      if (Rec.isUnevaluated()) {
> +        // C++11 [expr.prim.lambda]p2:
> +        //   A lambda-expression shall not appear in an unevaluated
> operand
> +        //   (Clause 5).
> +        D = diag::err_lambda_unevaluated_operand;
> +      } else {
> +        // C++1y [expr.const]p2:
> +        //   A conditional-expression e is a core constant expression
> unless the
> +        //   evaluation of e, following the rules of the abstract
> machine, would
> +        //   evaluate [...] a lambda-expression.
>

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


> +        D = diag::err_lambda_in_constant_expression;
> +      }
>        for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)
> -        Diag(Rec.Lambdas[I]->getLocStart(),
> -             diag::err_lambda_unevaluated_operand);
> +        Diag(Rec.Lambdas[I]->getLocStart(), D);
>      } else {
>        // Mark the capture expressions odr-used. This was deferred
>        // during lambda expression creation.
>
> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=193397&r1=193396&r2=193397&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Oct 25 04:12:52 2013
> @@ -1229,20 +1229,25 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
>                                            CaptureInits, ArrayIndexVars,
>                                            ArrayIndexStarts,
> Body->getLocEnd(),
>
>  ContainsUnexpandedParameterPack);
> -  // C++11 [expr.prim.lambda]p2:
> -  //   A lambda-expression shall not appear in an unevaluated operand
> -  //   (Clause 5).
> +
>    if (!CurContext->isDependentContext()) {
>      switch (ExprEvalContexts.back().Context) {
> +    // C++11 [expr.prim.lambda]p2:
> +    //   A lambda-expression shall not appear in an unevaluated operand
> +    //   (Clause 5).
>      case Unevaluated:
>      case UnevaluatedAbstract:
> +    // C++1y [expr.const]p2:
> +    //   A conditional-expression e is a core constant expression unless
> the
> +    //   evaluation of e, following the rules of the abstract machine,
> would
> +    //   evaluate [...] a lambda-expression.
> +    case ConstantEvaluated:
>        // We don't actually diagnose this case immediately, because we
>        // could be within a context where we might find out later that
>        // the expression is potentially evaluated (e.g., for typeid).
>        ExprEvalContexts.back().Lambdas.push_back(Lambda);
>        break;
>
> -    case ConstantEvaluated:
>      case PotentiallyEvaluated:
>      case PotentiallyEvaluatedIfUsed:
>        break;
>
> Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=193397&r1=193396&r2=193397&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Fri Oct 25 04:12:52 2013
> @@ -275,9 +275,7 @@ namespace UndefinedBehavior {
>
>  // - a lambda-expression (5.1.2);
>  struct Lambda {
> -  // FIXME: clang crashes when trying to parse this! Revisit this check
> once
> -  // lambdas are fully implemented.
> -  //int n : []{ return 1; }();
> +  int n : []{ return 1; }(); // expected-error {{constant expression}}
> expected-error {{integral constant expression}}
>  };
>
>  // - an lvalue-to-rvalue conversion (4.1) unless it is applied to
>
> Modified: cfe/trunk/test/SemaCXX/new-delete-0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete-0x.cpp?rev=193397&r1=193396&r2=193397&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/new-delete-0x.cpp (original)
> +++ cfe/trunk/test/SemaCXX/new-delete-0x.cpp Fri Oct 25 04:12:52 2013
> @@ -21,7 +21,9 @@ void bad_news(int *ip)
>    auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected
> ']'}}
>    // ... but not here:
>    auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot
> appear here}}
> -  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}}
> +  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}} \
> +                                                expected-error {{a lambda
> expression may not appear inside of a constant expression}}
>  }
>
>  void good_deletes()
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131103/4c2a944c/attachment.html>


More information about the cfe-commits mailing list