summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-04-13 04:31:48 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-04-13 04:31:48 +0000
commit0446558506ede662c42d7ff2e3db5b21a5db2c02 (patch)
treee7d1fa545126065db77adda3ed966c5b72e70e9f
parentd25ab09876a595a6bad5bdd6b13c005e3517a139 (diff)
downloadclang-0446558506ede662c42d7ff2e3db5b21a5db2c02.tar.gz
clang-0446558506ede662c42d7ff2e3db5b21a5db2c02.tar.bz2
clang-0446558506ede662c42d7ff2e3db5b21a5db2c02.tar.xz
PR19339: Disambiguate lambdas with init-captures from designated initializers
properly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206128 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Parse/ParseExprCXX.cpp4
-rw-r--r--lib/Parse/ParseInit.cpp58
-rw-r--r--test/Parser/cxx0x-lambda-expressions.cpp10
3 files changed, 32 insertions, 40 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index f10ca6ab78..6495d193f7 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -837,8 +837,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// [..., x = expr
//
// We need to find the end of the following expression in order to
- // determine whether this is an Obj-C message send's receiver, or a
- // lambda init-capture.
+ // determine whether this is an Obj-C message send's receiver, a
+ // C99 designator, or a lambda init-capture.
//
// Parse the expression to find where it ends, and annotate it back
// onto the tokens. We would have parsed this expression the same way
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 44053f193b..bdd4513167 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -66,45 +66,29 @@ bool Parser::MayBeDesignationStart() {
}
// Parse up to (at most) the token after the closing ']' to determine
- // whether this is a C99 designator or a lambda.
+ // whether this is a C99 designator or a lambda.
TentativeParsingAction Tentative(*this);
- ConsumeBracket();
- while (true) {
- switch (Tok.getKind()) {
- case tok::equal:
- case tok::amp:
- case tok::identifier:
- case tok::kw_this:
- // These tokens can occur in a capture list or a constant-expression.
- // Keep looking.
- ConsumeToken();
- continue;
-
- case tok::comma:
- // Since a comma cannot occur in a constant-expression, this must
- // be a lambda.
- Tentative.Revert();
- return false;
-
- case tok::r_square: {
- // Once we hit the closing square bracket, we look at the next
- // token. If it's an '=', this is a designator. Otherwise, it's a
- // lambda expression. This decision favors lambdas over the older
- // GNU designator syntax, which allows one to omit the '=', but is
- // consistent with GCC.
- ConsumeBracket();
- tok::TokenKind Kind = Tok.getKind();
- Tentative.Revert();
- return Kind == tok::equal;
- }
-
- default:
- // Anything else cannot occur in a lambda capture list, so it
- // must be a designator.
- Tentative.Revert();
- return true;
- }
+
+ LambdaIntroducer Intro;
+ bool SkippedInits = false;
+ Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits));
+
+ if (DiagID) {
+ // If this can't be a lambda capture list, it's a designator.
+ Tentative.Revert();
+ return true;
}
+
+ // Once we hit the closing square bracket, we look at the next
+ // token. If it's an '=', this is a designator. Otherwise, it's a
+ // lambda expression. This decision favors lambdas over the older
+ // GNU designator syntax, which allows one to omit the '=', but is
+ // consistent with GCC.
+ tok::TokenKind Kind = Tok.getKind();
+ // FIXME: If we didn't skip any inits, parse the lambda from here
+ // rather than throwing away then reparsing the LambdaIntroducer.
+ Tentative.Revert();
+ return Kind == tok::equal;
}
static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
diff --git a/test/Parser/cxx0x-lambda-expressions.cpp b/test/Parser/cxx0x-lambda-expressions.cpp
index 53ea05ea86..8cfe7f3b02 100644
--- a/test/Parser/cxx0x-lambda-expressions.cpp
+++ b/test/Parser/cxx0x-lambda-expressions.cpp
@@ -2,6 +2,8 @@
enum E { e };
+constexpr int id(int n) { return n; }
+
class C {
int f() {
@@ -34,12 +36,18 @@ class C {
typedef int T;
const int b = 0;
const int c = 1;
+ int d;
int a1[1] = {[b] (T()) {}}; // expected-error{{no viable conversion from '(lambda}}
int a2[1] = {[b] = 1 };
- int a3[1] = {[b,c] = 1 }; // expected-error{{expected body of lambda expression}}
+ int a3[1] = {[b,c] = 1 }; // expected-error{{expected ']'}} expected-note {{to match}}
int a4[1] = {[&b] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'const int *'}}
int a5[3] = { []{return 0;}() };
int a6[1] = {[this] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'C *'}}
+ int a7[1] = {[d(0)] { return d; } ()}; // expected-warning{{extension}}
+ int a8[1] = {[d = 0] { return d; } ()}; // expected-warning{{extension}}
+ int a9[1] = {[d = 0] = 1}; // expected-error{{is not an integral constant expression}}
+ int a10[1] = {[id(0)] { return id; } ()}; // expected-warning{{extension}}
+ int a11[1] = {[id(0)] = 1};
}
void delete_lambda(int *p) {