diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-16 21:53:36 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-16 21:53:36 +0000 |
commit | c9ecec404fe28d53aa49b3c830d8353e97bea5f2 (patch) | |
tree | 4aaf2e993d195dc55121a5c5825f12aef51caf73 | |
parent | 3f77c7b56d515a6756dba63a3dfa0a332711a779 (diff) |
Improve recovery for lambda expressions that have 'mutable' or a
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
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 2 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 46 | ||||
-rw-r--r-- | test/Parser/cxx0x-lambda-expressions.cpp | 2 |
3 files changed, 50 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index dcc6f697f8..3960d02982 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -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< diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 7185e93a11..d09dba2585 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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. diff --git a/test/Parser/cxx0x-lambda-expressions.cpp b/test/Parser/cxx0x-lambda-expressions.cpp index aa2a9cf7fd..a25116b460 100644 --- a/test/Parser/cxx0x-lambda-expressions.cpp +++ b/test/Parser/cxx0x-lambda-expressions.cpp @@ -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; } |