]> granicus.if.org Git - clang/commitdiff
C++1y n3648: parse and reject init-captures for now.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 9 May 2013 21:36:41 +0000 (21:36 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 9 May 2013 21:36:41 +0000 (21:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181553 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/DeclSpec.h
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaLambda.cpp
test/Parser/cxx0x-lambda-expressions.cpp
test/Parser/objcxx0x-lambda-expressions.mm

index 11fd91ab5bddad811435806e6adb3e587af0a129..18d5796ea14c4cb97912a2ae871fa0dc5e179842 100644 (file)
@@ -4887,6 +4887,8 @@ let CategoryName = "Lambda Issue" in {
   def note_lambda_to_block_conv : Note<
     "implicit capture of lambda object due to conversion to block pointer "
     "here">;
+  def err_lambda_init_capture_unsupported : Error<
+    "sorry, initialized lambda-captures are not supported yet">;
 }
 
 def err_return_in_captured_stmt : Error<
index 059919a35bb00e30eaf62d97a0e7a3df58802ab6..7ee2c6cc1e55d171d53909e7e9d3eb6705540e36 100644 (file)
@@ -2088,13 +2088,15 @@ private:
 struct LambdaCapture {
   LambdaCaptureKind Kind;
   SourceLocation Loc;
-  IdentifierInfoId;
+  IdentifierInfo *Id;
   SourceLocation EllipsisLoc;
-  
+  ExprResult Init;
+
   LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
                 IdentifierInfo* Id = 0,
-                SourceLocation EllipsisLoc = SourceLocation())
-    : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc)
+                SourceLocation EllipsisLoc = SourceLocation(),
+                ExprResult Init = ExprResult())
+    : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init)
   {}
 };
 
@@ -2111,11 +2113,11 @@ struct LambdaIntroducer {
   /// \brief Append a capture in a lambda introducer.
   void addCapture(LambdaCaptureKind Kind,
                   SourceLocation Loc,
-                  IdentifierInfo* Id = 0, 
-                  SourceLocation EllipsisLoc = SourceLocation()) {
-    Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc));
+                  IdentifierInfo* Id = 0,
+                  SourceLocation EllipsisLoc = SourceLocation(),
+                  ExprResult Init = ExprResult()) {
+    Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, Init));
   }
-
 };
 
 } // end namespace clang
index f259d5f59b4883b18586a1678047ee0e28aa8c3e..86e2e187d3e7c30743355dc1f6caeb46d64a0754 100644 (file)
@@ -583,7 +583,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
                                    Tok.is(tok::l_paren), isAddressOfOperand);
 }
 
-/// ParseLambdaExpression - Parse a C++0x lambda expression.
+/// ParseLambdaExpression - Parse a C++11 lambda expression.
 ///
 ///       lambda-expression:
 ///         lambda-introducer lambda-declarator[opt] compound-statement
@@ -605,10 +605,18 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
 ///         capture-list ',' capture
 ///
 ///       capture:
+///         simple-capture
+///         init-capture     [C++1y]
+///
+///       simple-capture:
 ///         identifier
 ///         '&' identifier
 ///         'this'
 ///
+///       init-capture:      [C++1y]
+///         identifier initializer
+///         '&' identifier initializer
+///
 ///       lambda-declarator:
 ///         '(' parameter-declaration-clause ')' attribute-specifier[opt]
 ///           'mutable'[opt] exception-specification[opt]
@@ -737,6 +745,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) {
     SourceLocation Loc;
     IdentifierInfo* Id = 0;
     SourceLocation EllipsisLoc;
+    ExprResult Init;
     
     if (Tok.is(tok::kw_this)) {
       Kind = LCK_This;
@@ -768,9 +777,31 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) {
       } else {
         return DiagResult(diag::err_expected_capture);
       }
+
+      if (Tok.is(tok::l_paren)) {
+        BalancedDelimiterTracker Parens(*this, tok::l_paren);
+        Parens.consumeOpen();
+
+        ExprVector Exprs;
+        CommaLocsTy Commas;
+        if (ParseExpressionList(Exprs, Commas)) {
+          Parens.skipToEnd();
+          Init = ExprError();
+        } else {
+          Parens.consumeClose();
+          Init = Actions.ActOnParenListExpr(Parens.getOpenLocation(),
+                                            Parens.getCloseLocation(),
+                                            Exprs);
+        }
+      } else if (Tok.is(tok::l_brace) || Tok.is(tok::equal)) {
+        if (Tok.is(tok::equal))
+          ConsumeToken();
+
+        Init = ParseInitializer();
+      }
     }
 
-    Intro.addCapture(Kind, Loc, Id, EllipsisLoc);
+    Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init);
   }
 
   T.consumeClose();
@@ -806,6 +837,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
                                 "lambda expression parsing");
 
+  // FIXME: Call into Actions to add any init-capture declarations to the
+  // scope while parsing the lambda-declarator and compound-statement.
+
   // Parse lambda-declarator[opt].
   DeclSpec DS(AttrFactory);
   Declarator D(DS, Declarator::LambdaExprContext);
index 24388dd0f52b94615416c1cb1133527d351d0a2c..4e11bb4c0557fbd87e8d05e9a9431e5d725b5fde 100644 (file)
@@ -559,6 +559,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
       continue;
     }
 
+    // FIXME: C++1y [expr.prim.lambda]p11
+    if (C->Init.isInvalid())
+      continue;
+    if (C->Init.isUsable()) {
+      Diag(C->Loc, diag::err_lambda_init_capture_unsupported);
+      continue;
+    }
+
     assert(C->Id && "missing identifier for capture");
 
     // C++11 [expr.prim.lambda]p8:
index 642c69a532eec4aa5c6659bcd8a72459b5de5ad0..d7dc7d3a4730ba28250e3597640d516ff42130cf 100644 (file)
@@ -48,4 +48,22 @@ class C {
     delete [] { return new int; } (); // expected-error{{expected expression}}
     delete [&] { return new int; } (); // ok, lambda
   }
+
+  // We support init-captures in C++11 as an extension.
+  int z;
+  void init_capture() {
+    // FIXME: These diagnostics should all disappear once semantic analysis
+    // for init-captures is complete.
+    [n(0)] () -> int { return ++n; }; // expected-error {{not supported}} expected-error {{undeclared}}
+    [n{0}] { return; }; // expected-error {{not supported}}
+    [n = 0] { return ++n; }; // expected-error {{not supported}} expected-error {{undeclared}}
+    [n = {0}] { return; }; // expected-error {{not supported}}
+    [a([&b = z]{})](){}; // expected-error 2{{not supported}}
+
+    int x = 4; // expected-note {{here}}
+    auto y = [&r = x, x = x + 1]() -> int { // expected-error 2{{not supported}} expected-note {{here}}
+      r += 2; // expected-error {{undeclared}}
+      return x + 2; // expected-error {{implicitly captured}}
+    } ();
+  }
 };
index fb90b16a971f15cc7048b7a730c1ba0c4b15efe5..94e47ccd3e0a2b0f7c2948b2dbed1405561aee87 100644 (file)
@@ -17,6 +17,16 @@ class C {
     [foo,bar] () { return 3; }; 
     [=,&foo] () {}; 
     [this] () {}; 
+
+    [foo(bar)] () {}; // expected-error {{not supported}}
+    [foo = bar] () {}; // expected-error {{not supported}}
+    [foo{bar}] () {}; // expected-error {{not supported}}
+    [foo = {bar}] () {}; // expected-error {{not supported}}
+
+    [foo(bar) baz] () {}; // expected-error {{called object type 'int' is not a function}}
+
+    // FIXME: These are some appalling diagnostics.
+    [foo = bar baz]; // expected-error {{missing '['}} expected-warning 2{{receiver type 'int'}} expected-warning 2{{instance method '-baz'}}
   }
 
 };