r206128 - PR19339: Disambiguate lambdas with init-captures from designated initializers

Richard Smith richard-llvm at metafoo.co.uk
Sat Apr 12 21:31:48 PDT 2014


Author: rsmith
Date: Sat Apr 12 23:31:48 2014
New Revision: 206128

URL: http://llvm.org/viewvc/llvm-project?rev=206128&view=rev
Log:
PR19339: Disambiguate lambdas with init-captures from designated initializers
properly.

Modified:
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseInit.cpp
    cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=206128&r1=206127&r2=206128&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Apr 12 23:31:48 2014
@@ -837,8 +837,8 @@ Optional<unsigned> Parser::ParseLambdaIn
           //   [..., x = expr
           //
           // We need to find the end of the following expression in order to
-          // determine whether this is an Obj-C message send's receiver, or a
-          // lambda init-capture.
+          // determine whether this is an Obj-C message send's receiver, a
+          // C99 designator, or a lambda init-capture.
           //
           // Parse the expression to find where it ends, and annotate it back
           // onto the tokens. We would have parsed this expression the same way

Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=206128&r1=206127&r2=206128&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Sat Apr 12 23:31:48 2014
@@ -66,45 +66,29 @@ bool Parser::MayBeDesignationStart() {
   }
   
   // Parse up to (at most) the token after the closing ']' to determine 
-  // whether this is a C99 designator or a lambda.
+  // whether this is a C99 designator or a lambda.
   TentativeParsingAction Tentative(*this);
-  ConsumeBracket();
-  while (true) {
-    switch (Tok.getKind()) {
-    case tok::equal:
-    case tok::amp:
-    case tok::identifier:
-    case tok::kw_this:
-      // These tokens can occur in a capture list or a constant-expression.
-      // Keep looking.
-      ConsumeToken();
-      continue;
-      
-    case tok::comma:
-      // Since a comma cannot occur in a constant-expression, this must
-      // be a lambda.
-      Tentative.Revert();
-      return false;
-      
-    case tok::r_square: {
-      // Once we hit the closing square bracket, we look at the next
-      // token. If it's an '=', this is a designator. Otherwise, it's a
-      // lambda expression. This decision favors lambdas over the older
-      // GNU designator syntax, which allows one to omit the '=', but is
-      // consistent with GCC.
-      ConsumeBracket();
-      tok::TokenKind Kind = Tok.getKind();
-      Tentative.Revert();
-      return Kind == tok::equal;
-    }
-      
-    default:
-      // Anything else cannot occur in a lambda capture list, so it
-      // must be a designator.
-      Tentative.Revert();
-      return true;
-    }
+
+  LambdaIntroducer Intro;
+  bool SkippedInits = false;
+  Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits));
+
+  if (DiagID) {
+    // If this can't be a lambda capture list, it's a designator.
+    Tentative.Revert();
+    return true;
   }
+
+  // Once we hit the closing square bracket, we look at the next
+  // token. If it's an '=', this is a designator. Otherwise, it's a
+  // lambda expression. This decision favors lambdas over the older
+  // GNU designator syntax, which allows one to omit the '=', but is
+  // consistent with GCC.
+  tok::TokenKind Kind = Tok.getKind();
+  // FIXME: If we didn't skip any inits, parse the lambda from here
+  // rather than throwing away then reparsing the LambdaIntroducer.
+  Tentative.Revert();
+  return Kind == tok::equal;
 }
 
 static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,

Modified: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp?rev=206128&r1=206127&r2=206128&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp Sat Apr 12 23:31:48 2014
@@ -2,6 +2,8 @@
 
 enum E { e };
 
+constexpr int id(int n) { return n; }
+
 class C {
 
   int f() {
@@ -34,12 +36,18 @@ class C {
     typedef int T; 
     const int b = 0; 
     const int c = 1;
+    int d;
     int a1[1] = {[b] (T()) {}}; // expected-error{{no viable conversion from '(lambda}}
     int a2[1] = {[b] = 1 };
-    int a3[1] = {[b,c] = 1 }; // expected-error{{expected body of lambda expression}}
+    int a3[1] = {[b,c] = 1 }; // expected-error{{expected ']'}} expected-note {{to match}}
     int a4[1] = {[&b] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'const int *'}}
     int a5[3] = { []{return 0;}() };
     int a6[1] = {[this] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'C *'}}
+    int a7[1] = {[d(0)] { return d; } ()}; // expected-warning{{extension}}
+    int a8[1] = {[d = 0] { return d; } ()}; // expected-warning{{extension}}
+    int a9[1] = {[d = 0] = 1}; // expected-error{{is not an integral constant expression}}
+    int a10[1] = {[id(0)] { return id; } ()}; // expected-warning{{extension}}
+    int a11[1] = {[id(0)] = 1};
   }
 
   void delete_lambda(int *p) {





More information about the cfe-commits mailing list