]> granicus.if.org Git - clang/commitdiff
Improve recovery for lambda expressions that have 'mutable' or a
authorDouglas Gregor <dgregor@apple.com>
Thu, 16 Feb 2012 21:53:36 +0000 (21:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 16 Feb 2012 21:53:36 +0000 (21:53 +0000)
trailing return type but not a '()'. Recover by inserting the
parentheses. Thanks to Xeo on IRC for the example.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150727 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
lib/Parse/ParseExprCXX.cpp
test/Parser/cxx0x-lambda-expressions.cpp

index dcc6f697f8a38bd4bf8ccf72c09ea26b9805b493..3960d029828a50df1e431620c8ddf8a877fdf5cd 100644 (file)
@@ -602,6 +602,8 @@ def err_expected_lambda_body : Error<"expected body of lambda expression">;
 def warn_cxx98_compat_lambda : Warning<
   "lambda expressions are incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
+def err_lambda_missing_parens : Error<
+  "lambda requires '()' before %select{'mutable'|return type}0">;
 
 // Availability attribute
 def err_expected_version : Error<
index 7185e93a11d35617e95a650cb296d5afd4744365..d09dba258568f240fe4bebb61047513f5f7245bd 100644 (file)
@@ -820,7 +820,53 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
                                            DeclLoc, DeclEndLoc, D,
                                            TrailingReturnType),
                   Attr, DeclEndLoc);
+  } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow)) {
+    // It's common to forget that one needs '()' before 'mutable' or the 
+    // result type. Deal with this.
+    Diag(Tok, diag::err_lambda_missing_parens)
+      << Tok.is(tok::arrow)
+      << FixItHint::CreateInsertion(Tok.getLocation(), "() ");
+    SourceLocation DeclLoc = Tok.getLocation();
+    SourceLocation DeclEndLoc = DeclLoc;
+    
+    // Parse 'mutable', if it's there.
+    SourceLocation MutableLoc;
+    if (Tok.is(tok::kw_mutable)) {
+      MutableLoc = ConsumeToken();
+      DeclEndLoc = MutableLoc;
+    }
+    
+    // Parse the return type, if there is one.
+    ParsedType TrailingReturnType;
+    if (Tok.is(tok::arrow)) {
+      SourceRange Range;
+      TrailingReturnType = ParseTrailingReturnType(Range).get();
+      if (Range.getEnd().isValid())
+        DeclEndLoc = Range.getEnd();      
+    }
+
+    ParsedAttributes Attr(AttrFactory);
+    D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
+                     /*isVariadic=*/false,
+                     /*EllipsisLoc=*/SourceLocation(),
+                     /*Params=*/0, /*NumParams=*/0,
+                     /*TypeQuals=*/0,
+                     /*RefQualifierIsLValueRef=*/true,
+                     /*RefQualifierLoc=*/SourceLocation(),
+                     /*ConstQualifierLoc=*/SourceLocation(),
+                     /*VolatileQualifierLoc=*/SourceLocation(),
+                     MutableLoc,
+                     EST_None, 
+                     /*ESpecLoc=*/SourceLocation(),
+                     /*Exceptions=*/0,
+                     /*ExceptionRanges=*/0,
+                     /*NumExceptions=*/0,
+                     /*NoexceptExpr=*/0,
+                     DeclLoc, DeclEndLoc, D,
+                     TrailingReturnType),
+                  Attr, DeclEndLoc);
   }
+  
 
   // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
   // it.
index aa2a9cf7fd2ee46d20b388266a72864fad4c2270..a25116b460aa5f7eed2d5ea963a28ed278b10280 100644 (file)
@@ -20,6 +20,8 @@ class C {
     [&,foo] () {}; 
     [this] () {}; 
 
+    [] -> int { return 0; }; // expected-error{{lambda requires '()' before return type}}
+    [] mutable -> int { return 0; }; // expected-error{{lambda requires '()' before 'mutable'}}
     return 1;
   }