diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-03-11 13:03:15 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-03-11 13:03:15 +0000 |
commit | 85f82dcfa0da0a7e1b78c7a2c1b5b1949f679e8e (patch) | |
tree | 8eb807785643842f8d3a4b64c98c3e29b5db1878 | |
parent | 7533ae94377aed5aa7866ebd67cbcf616efabb3c (diff) | |
download | clang-85f82dcfa0da0a7e1b78c7a2c1b5b1949f679e8e.tar.gz clang-85f82dcfa0da0a7e1b78c7a2c1b5b1949f679e8e.tar.bz2 clang-85f82dcfa0da0a7e1b78c7a2c1b5b1949f679e8e.tar.xz |
Gracefully handle an attribute specifier following a lambda introducer when the parameter list wasn't present.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203565 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 3 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 24 | ||||
-rw-r--r-- | test/Parser/cxx0x-lambda-expressions.cpp | 1 |
3 files changed, 21 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 5be34dc188..573748f37b 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -725,7 +725,8 @@ 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">; + "lambda requires '()' before %select{'mutable'|return type|" + "attribute specifier}0">; // Availability attribute def err_expected_version : Error< diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 6fd920e7e8..439fb077da 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1066,11 +1066,20 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( LParenLoc, FunLocalRangeEnd, 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. + } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) || + (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { + // It's common to forget that one needs '()' before 'mutable', an attribute + // specifier, or the result type. Deal with this. + unsigned TokKind = 0; + switch (Tok.getKind()) { + case tok::kw_mutable: TokKind = 0; break; + case tok::arrow: TokKind = 1; break; + case tok::l_square: TokKind = 2; break; + default: llvm_unreachable("Unknown token kind"); + } + Diag(Tok, diag::err_lambda_missing_parens) - << Tok.is(tok::arrow) + << TokKind << FixItHint::CreateInsertion(Tok.getLocation(), "() "); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation DeclEndLoc = DeclLoc; @@ -1081,7 +1090,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( MutableLoc = ConsumeToken(); DeclEndLoc = MutableLoc; } - + + // Parse attribute-specifier[opt]. + ParsedAttributes Attr(AttrFactory); + MaybeParseCXX11Attributes(Attr, &DeclEndLoc); + // Parse the return type, if there is one. TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { @@ -1091,7 +1104,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DeclEndLoc = Range.getEnd(); } - ParsedAttributes Attr(AttrFactory); SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, /*isAmbiguous=*/false, diff --git a/test/Parser/cxx0x-lambda-expressions.cpp b/test/Parser/cxx0x-lambda-expressions.cpp index 289d03c223..189a6448e1 100644 --- a/test/Parser/cxx0x-lambda-expressions.cpp +++ b/test/Parser/cxx0x-lambda-expressions.cpp @@ -24,6 +24,7 @@ class C { [] () -> class C { return C(); }; [] () -> enum E { return e; }; + [] [[noreturn]] { while (1) ; }; // expected-error {{lambda requires '()' before attribute specifier}} [] -> int { return 0; }; // expected-error{{lambda requires '()' before return type}} [] mutable -> int { return 0; }; // expected-error{{lambda requires '()' before 'mutable'}} [](int) -> {}; // PR13652 expected-error {{expected a type}} |