[cfe-commits] r136876 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h include/clang/Sema/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp test/Parser/cxx0x-attributes.cpp test/Parser/cxx0x-lambda-expressions.cpp test/Parser/objc-messaging-neg-1.m test/Parser/objcxx-lambda-expressions-neg.mm test/Parser/objcxx0x-lambda-expressions.mm

Douglas Gregor dgregor at apple.com
Thu Aug 4 08:30:47 PDT 2011


Author: dgregor
Date: Thu Aug  4 10:30:47 2011
New Revision: 136876

URL: http://llvm.org/viewvc/llvm-project?rev=136876&view=rev
Log:
Parsing of C++0x lambda expressions, from John Freeman with help from
David Blaikie!

Added:
    cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp   (with props)
    cfe/trunk/test/Parser/objcxx-lambda-expressions-neg.mm
    cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/test/Parser/cxx0x-attributes.cpp
    cfe/trunk/test/Parser/objc-messaging-neg-1.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Aug  4 10:30:47 2011
@@ -487,6 +487,15 @@
 def err_sizeof_parameter_pack : Error<
   "expected parenthesized parameter pack name in 'sizeof...' expression">;
 
+// C++0x lambda expressions
+def err_expected_comma_or_rsquare : Error<
+  "expected ',' or ']' in lambda capture list">;
+def err_this_captured_by_reference : Error<
+  "'this' cannot be captured by reference">;
+def err_expected_capture : Error<
+  "expected variable name or 'this' in lambda capture list">;
+def err_expected_lambda_body : Error<"expected body of lambda expression">;
+
 // Availability attribute
 def err_expected_version : Error<
   "expected a version of the form 'major[.minor[.subminor]]'">;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Aug  4 10:30:47 2011
@@ -1186,6 +1186,17 @@
                                       bool IsTypename = false);
 
   //===--------------------------------------------------------------------===//
+  // C++0x 5.1.2: Lambda expressions
+
+  // [...] () -> type {...}
+  ExprResult ParseLambdaExpression();
+  ExprResult TryParseLambdaExpression();
+  llvm::Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro);
+  bool TryParseLambdaIntroducer(LambdaIntroducer &Intro);
+  ExprResult ParseLambdaExpressionAfterIntroducer(
+               LambdaIntroducer &Intro);
+
+  //===--------------------------------------------------------------------===//
   // C++ 5.2p1: C++ Casts
   ExprResult ParseCXXCasts();
 
@@ -1226,7 +1237,7 @@
 
   //===--------------------------------------------------------------------===//
   // C++0x 8: Function declaration trailing-return-type
-  TypeResult ParseTrailingReturnType();
+  TypeResult ParseTrailingReturnType(SourceRange &Range);
 
   //===--------------------------------------------------------------------===//
   // C++ 2.13.5: C++ Boolean Literals

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Aug  4 10:30:47 2011
@@ -1828,6 +1828,53 @@
   SourceLocation LastLocation;
 };
 
+/// LambdaCaptureDefault - The default, if any, capture method for a
+/// lambda expression.
+enum LambdaCaptureDefault {
+  LCD_None,
+  LCD_ByCopy,
+  LCD_ByRef
+};
+
+/// LambdaCaptureKind - The different capture forms in a lambda
+/// introducer: 'this' or a copied or referenced variable.
+enum LambdaCaptureKind {
+  LCK_This,
+  LCK_ByCopy,
+  LCK_ByRef
+};
+
+/// LambdaCapture - An individual capture in a lambda introducer.
+struct LambdaCapture {
+  LambdaCaptureKind Kind;
+  SourceLocation Loc;
+  IdentifierInfo* Id;
+
+  LambdaCapture(LambdaCaptureKind Kind,
+                     SourceLocation Loc,
+                     IdentifierInfo* Id = 0)
+    : Kind(Kind), Loc(Loc), Id(Id)
+  {}
+};
+
+/// LambdaIntroducer - Represents a complete lambda introducer.
+struct LambdaIntroducer {
+  SourceRange Range;
+  LambdaCaptureDefault Default;
+  llvm::SmallVector<LambdaCapture, 4> Captures;
+
+  LambdaIntroducer()
+    : Default(LCD_None) {}
+
+  /// addCapture - Append a capture in a lambda introducer.
+  void addCapture(LambdaCaptureKind Kind,
+                  SourceLocation Loc,
+                  IdentifierInfo* Id = 0) {
+    Captures.push_back(LambdaCapture(Kind, Loc, Id));
+  }
+
+};
+
 } // end namespace clang
 
 #endif

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Aug  4 10:30:47 2011
@@ -3745,7 +3745,10 @@
 
       // Parse trailing-return-type[opt].
       if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) {
-        TrailingReturnType = ParseTrailingReturnType().get();
+        SourceRange Range;
+        TrailingReturnType = ParseTrailingReturnType(Range).get();
+        if (Range.getEnd().isValid())
+          EndLoc = Range.getEnd();
       }
     }
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Aug  4 10:30:47 2011
@@ -2442,7 +2442,7 @@
 
 /// ParseTrailingReturnType - Parse a trailing return type on a new-style
 /// function declaration.
-TypeResult Parser::ParseTrailingReturnType() {
+TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) {
   assert(Tok.is(tok::arrow) && "expected arrow");
 
   ConsumeToken();
@@ -2454,8 +2454,6 @@
   //
   // struct X is parsed as class definition because of the trailing
   // brace.
-
-  SourceRange Range;
   return ParseTypeName(&Range);
 }
 

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Aug  4 10:30:47 2011
@@ -1115,6 +1115,16 @@
                                NotCastExpr, isTypeCast);
   }
   case tok::l_square:
+    if (getLang().CPlusPlus0x) {
+      if (getLang().ObjC1) {
+        Res = TryParseLambdaExpression();
+        if (Res.isInvalid())
+          Res = ParseObjCMessageExpression();
+        break;
+      }
+      Res = ParseLambdaExpression();
+      break;
+    }
     if (getLang().ObjC1) {
       Res = ParseObjCMessageExpression();
       break;

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Aug  4 10:30:47 2011
@@ -15,6 +15,7 @@
 #include "clang/Parse/Parser.h"
 #include "RAIIObjectsForParser.h"
 #include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -504,6 +505,266 @@
   
 }
 
+/// ParseLambdaExpression - Parse a C++0x lambda expression.
+///
+///       lambda-expression:
+///         lambda-introducer lambda-declarator[opt] compound-statement
+///
+///       lambda-introducer:
+///         '[' lambda-capture[opt] ']'
+///
+///       lambda-capture:
+///         capture-default
+///         capture-list
+///         capture-default ',' capture-list
+///
+///       capture-default:
+///         '&'
+///         '='
+///
+///       capture-list:
+///         capture
+///         capture-list ',' capture
+///
+///       capture:
+///         identifier
+///         '&' identifier
+///         'this'
+///
+///       lambda-declarator:
+///         '(' parameter-declaration-clause ')' attribute-specifier[opt]
+///           'mutable'[opt] exception-specification[opt]
+///           trailing-return-type[opt]
+///
+ExprResult Parser::ParseLambdaExpression() {
+  // Parse lambda-introducer.
+  LambdaIntroducer Intro;
+
+  llvm::Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro));
+  if (DiagID) {
+    Diag(Tok, DiagID.getValue());
+    SkipUntil(tok::r_square);
+  }
+
+  return ParseLambdaExpressionAfterIntroducer(Intro);
+}
+
+/// TryParseLambdaExpression - Use lookahead and potentially tentative
+/// parsing to determine if we are looking at a C++0x lambda expression, and parse
+/// it if we are.
+///
+/// If we are not looking at a lambda expression, returns ExprError().
+ExprResult Parser::TryParseLambdaExpression() {
+  assert(getLang().CPlusPlus0x
+         && Tok.is(tok::l_square)
+         && "Not at the start of a possible lambda expression.");
+
+  const Token Next = NextToken(), After = GetLookAheadToken(2);
+
+  // If lookahead indicates this is a lambda...
+  if (Next.is(tok::r_square) ||     // []
+      Next.is(tok::equal) ||        // [=
+      (Next.is(tok::amp) &&         // [&] or [&,
+       (After.is(tok::r_square) ||
+        After.is(tok::comma))) ||
+      (Next.is(tok::identifier) &&  // [identifier]
+       After.is(tok::r_square))) {
+    return ParseLambdaExpression();
+  }
+
+  // If lookahead indicates this is an Objective-C message...
+  if (Next.is(tok::identifier) && After.is(tok::identifier)) {
+    return ExprError();
+  }
+
+  LambdaIntroducer Intro;
+  if (TryParseLambdaIntroducer(Intro))
+    return ExprError();
+  return ParseLambdaExpressionAfterIntroducer(Intro);
+}
+
+/// ParseLambdaExpression - Parse a lambda introducer.
+///
+/// Returns a DiagnosticID if it hit something unexpected.
+llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) {
+  typedef llvm::Optional<unsigned> DiagResult;
+
+  assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['.");
+  Intro.Range.setBegin(ConsumeBracket());
+
+  bool first = true;
+
+  // Parse capture-default.
+  if (Tok.is(tok::amp) &&
+      (NextToken().is(tok::comma) || NextToken().is(tok::r_square))) {
+    Intro.Default = LCD_ByRef;
+    ConsumeToken();
+    first = false;
+  } else if (Tok.is(tok::equal)) {
+    Intro.Default = LCD_ByCopy;
+    ConsumeToken();
+    first = false;
+  }
+
+  while (Tok.isNot(tok::r_square)) {
+    if (!first) {
+      if (Tok.isNot(tok::comma))
+        return DiagResult(diag::err_expected_comma_or_rsquare);
+      ConsumeToken();
+    }
+
+    first = false;
+
+    // Parse capture.
+    LambdaCaptureKind Kind = LCK_ByCopy;
+    SourceLocation Loc;
+    IdentifierInfo* Id = 0;
+
+    if (Tok.is(tok::kw_this)) {
+      Kind = LCK_This;
+      Loc = ConsumeToken();
+    } else {
+      if (Tok.is(tok::amp)) {
+        Kind = LCK_ByRef;
+        ConsumeToken();
+      }
+
+      if (Tok.is(tok::identifier)) {
+        Id = Tok.getIdentifierInfo();
+        Loc = ConsumeToken();
+      } else if (Tok.is(tok::kw_this)) {
+        // FIXME: If we want to suggest a fixit here, will need to return more
+        // than just DiagnosticID. Perhaps full DiagnosticBuilder that can be
+        // Clear()ed to prevent emission in case of tentative parsing?
+        return DiagResult(diag::err_this_captured_by_reference);
+      } else {
+        return DiagResult(diag::err_expected_capture);
+      }
+    }
+
+    Intro.addCapture(Kind, Loc, Id);
+  }
+
+  Intro.Range.setEnd(MatchRHSPunctuation(tok::r_square,
+                                         Intro.Range.getBegin()));
+
+  return DiagResult();
+}
+
+/// TryParseLambdaExpression - Tentatively parse a lambda introducer.
+///
+/// Returns true if it hit something unexpected.
+bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) {
+  TentativeParsingAction PA(*this);
+
+  llvm::Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro));
+
+  if (DiagID) {
+    PA.Revert();
+    return true;
+  }
+
+  PA.Commit();
+  return false;
+}
+
+/// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda
+/// expression.
+ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
+                     LambdaIntroducer &Intro) {
+  // Parse lambda-declarator[opt].
+  DeclSpec DS(AttrFactory);
+  Declarator D(DS, Declarator::PrototypeContext);
+
+  if (Tok.is(tok::l_paren)) {
+    ParseScope PrototypeScope(this,
+                              Scope::FunctionPrototypeScope |
+                              Scope::DeclScope);
+
+    SourceLocation DeclLoc = ConsumeParen(), DeclEndLoc;
+
+    // Parse parameter-declaration-clause.
+    ParsedAttributes Attr(AttrFactory);
+    llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+    SourceLocation EllipsisLoc;
+
+    if (Tok.isNot(tok::r_paren))
+      ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
+
+    DeclEndLoc = MatchRHSPunctuation(tok::r_paren, DeclLoc);
+
+    // Parse 'mutable'[opt].
+    SourceLocation MutableLoc;
+    if (Tok.is(tok::kw_mutable)) {
+      MutableLoc = ConsumeToken();
+      DeclEndLoc = MutableLoc;
+    }
+
+    // Parse exception-specification[opt].
+    ExceptionSpecificationType ESpecType = EST_None;
+    SourceRange ESpecRange;
+    llvm::SmallVector<ParsedType, 2> DynamicExceptions;
+    llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges;
+    ExprResult NoexceptExpr;
+    ESpecType = MaybeParseExceptionSpecification(ESpecRange,
+                                                 DynamicExceptions,
+                                                 DynamicExceptionRanges,
+                                                 NoexceptExpr);
+
+    if (ESpecType != EST_None)
+      DeclEndLoc = ESpecRange.getEnd();
+
+    // Parse attribute-specifier[opt].
+    MaybeParseCXX0XAttributes(Attr, &DeclEndLoc);
+
+    // Parse trailing-return-type[opt].
+    ParsedType TrailingReturnType;
+    if (Tok.is(tok::arrow)) {
+      SourceRange Range;
+      TrailingReturnType = ParseTrailingReturnType(Range).get();
+      if (Range.getEnd().isValid())
+        DeclEndLoc = Range.getEnd();
+    }
+
+    PrototypeScope.Exit();
+
+    D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
+                                           /*isVariadic=*/EllipsisLoc.isValid(),
+                                           EllipsisLoc,
+                                           ParamInfo.data(), ParamInfo.size(),
+                                           DS.getTypeQualifiers(),
+                                           /*RefQualifierIsLValueRef=*/true,
+                                           /*RefQualifierLoc=*/SourceLocation(),
+                                           MutableLoc,
+                                           ESpecType, ESpecRange.getBegin(),
+                                           DynamicExceptions.data(),
+                                           DynamicExceptionRanges.data(),
+                                           DynamicExceptions.size(),
+                                           NoexceptExpr.isUsable() ?
+                                             NoexceptExpr.get() : 0,
+                                           DeclLoc, DeclEndLoc, D,
+                                           TrailingReturnType),
+                  Attr, DeclEndLoc);
+  }
+
+  // Parse compound-statement.
+  if (Tok.is(tok::l_brace)) {
+    // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
+    // it.
+    ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope |
+                               Scope::BreakScope | Scope::ContinueScope |
+                               Scope::DeclScope);
+
+    StmtResult Stmt(ParseCompoundStatementBody());
+
+    BodyScope.Exit();
+  } else {
+    Diag(Tok, diag::err_expected_lambda_body);
+  }
+
+  return ExprEmpty();
+}
+
 /// ParseCXXCasts - This handles the various ways to cast expressions to another
 /// type.
 ///

Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Thu Aug  4 10:30:47 2011
@@ -17,7 +17,7 @@
 int scope_attr [[foo::]]; // expected-error {{expected identifier}}
 int & [[]] ref_attr = after_attr; // expected-error {{an attribute list cannot appear here}}
 class foo {
-  void after_const_attr () const [[]]; // expected-error {{expected expression}}
+  void after_const_attr () const [[]]; // expected-error {{expected body of lambda expression}} expected-error {{array has incomplete element type 'void'}}
 };
 extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
 [[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}

Added: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp?rev=136876&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp (added)
+++ cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp Thu Aug  4 10:30:47 2011
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+class C {
+
+  int f() {
+    int foo, bar;
+
+    []; // expected-error {{expected body of lambda expression}}
+    [+] {}; // expected-error {{expected variable name or 'this' in lambda capture list}}
+    [foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
+    [foo,&this] {}; // expected-error {{'this' cannot be captured by reference}}
+    [&this] {}; // expected-error {{'this' cannot be captured by reference}}
+    [&,] {}; // expected-error {{ expected variable name or 'this' in lambda capture list}}
+    [=,] {}; // expected-error {{ expected variable name or 'this' in lambda capture list}}
+    [] {};
+    [=] (int i) {};
+    [&] (int) mutable -> void {};
+    [foo,bar] () { return 3; };
+    [=,&foo] () {};
+    [&,foo] () {};
+    [this] () {};
+
+    return 1;
+  }
+
+};
+

Propchange: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/Parser/objc-messaging-neg-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objc-messaging-neg-1.m?rev=136876&r1=136875&r2=136876&view=diff
==============================================================================
--- cfe/trunk/test/Parser/objc-messaging-neg-1.m (original)
+++ cfe/trunk/test/Parser/objc-messaging-neg-1.m Thu Aug  4 10:30:47 2011
@@ -9,4 +9,5 @@
   [a bla:0 6:7]; // expected-error {{expected ']'}}
   [A foo bar]; // expected-error {{expected ':'}}
   [A foo bar bar1]; // expected-error {{expected ':'}}
+  [] {}; // expected-error {{expected expression}}
 }

Added: cfe/trunk/test/Parser/objcxx-lambda-expressions-neg.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx-lambda-expressions-neg.mm?rev=136876&view=auto
==============================================================================
--- cfe/trunk/test/Parser/objcxx-lambda-expressions-neg.mm (added)
+++ cfe/trunk/test/Parser/objcxx-lambda-expressions-neg.mm Thu Aug  4 10:30:47 2011
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int main() {
+  []{}; // expected-error {{expected expression}}
+}

Added: cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm?rev=136876&view=auto
==============================================================================
--- cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm (added)
+++ cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm Thu Aug  4 10:30:47 2011
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+class C {
+
+  void f() {
+    int foo, bar;
+
+    // fail to parse as a lambda introducer, so we get objc message parsing errors instead
+    [foo,+] {}; // expected-error {{expected expression}}
+
+    []; // expected-error {{expected body of lambda expression}}
+    [=,foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
+    [&this] {}; // expected-error {{address expression must be an lvalue}}
+    [] {};
+    [=] (int i) {};
+    [&] (int) mutable -> void {};
+    // FIXME: this error occurs because we do not yet handle lambda scopes
+    // properly. I did not anticipate it because I thought it was a semantic (not
+    // syntactic) check.
+    [foo,bar] () { return 3; }; // expected-error {{void function 'f' should not return a value}}
+    [=,&foo] () {};
+    [this] () {};
+  }
+
+};
+





More information about the cfe-commits mailing list