summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-03-11 13:03:15 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-03-11 13:03:15 +0000
commit85f82dcfa0da0a7e1b78c7a2c1b5b1949f679e8e (patch)
tree8eb807785643842f8d3a4b64c98c3e29b5db1878
parent7533ae94377aed5aa7866ebd67cbcf616efabb3c (diff)
downloadclang-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.td3
-rw-r--r--lib/Parse/ParseExprCXX.cpp24
-rw-r--r--test/Parser/cxx0x-lambda-expressions.cpp1
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}}