diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-20 18:01:54 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-20 18:01:54 +0000 |
commit | e9585060398960d78cce6dd59b79e31e736b8f51 (patch) | |
tree | 8aec90e80180321de91daaf2765a0b616d9fcb4b /clang/lib/Parse/ParseTentative.cpp | |
parent | d91f1dd4706d2bc591fc64d7f315c020f521678e (diff) | |
download | bcm5719-llvm-e9585060398960d78cce6dd59b79e31e736b8f51.tar.gz bcm5719-llvm-e9585060398960d78cce6dd59b79e31e736b8f51.zip |
Rearrange and clean up how we disambiguate lambda-introducers from ObjC
message sends, designators, and attributes.
Instead of having the tentative parsing phase sometimes return an
indicator to say what diagnostic to produce if parsing fails and
sometimes ask the caller to run it again, consistently ask the caller to
try parsing again if tentative parsing would fail or is otherwise unable
to completely parse the lambda-introducer without producing an
irreversible semantic effect.
Mostly NFC, but we should recover marginally better in some error cases
(avoiding duplicate diagnostics).
llvm-svn: 361182
Diffstat (limited to 'clang/lib/Parse/ParseTentative.cpp')
-rw-r--r-- | clang/lib/Parse/ParseTentative.cpp | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 4393326f6c7..e97a8e5b544 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -653,12 +653,15 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, if (!Disambiguate && !getLangOpts().ObjC) return CAK_AttributeSpecifier; + // '[[using ns: ...]]' is an attribute. + if (GetLookAheadToken(2).is(tok::kw_using)) + return CAK_AttributeSpecifier; + RevertingTentativeParsingAction PA(*this); // Opening brackets were checked for above. ConsumeBracket(); - // Outside Obj-C++11, treat anything with a matching ']]' as an attribute. if (!getLangOpts().ObjC) { ConsumeBracket(); @@ -677,24 +680,45 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, // 4) [[obj]{ return self; }() doStuff]; Lambda in message send. // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted. - // If we have a lambda-introducer, then this is definitely not a message send. + // Check to see if this is a lambda-expression. // FIXME: If this disambiguation is too slow, fold the tentative lambda parse // into the tentative attribute parse below. - LambdaIntroducer Intro; - if (!TryParseLambdaIntroducer(Intro)) { - // A lambda cannot end with ']]', and an attribute must. - bool IsAttribute = Tok.is(tok::r_square); - - if (IsAttribute) - // Case 1: C++11 attribute. - return CAK_AttributeSpecifier; + { + RevertingTentativeParsingAction LambdaTPA(*this); + LambdaIntroducer Intro; + LambdaIntroducerTentativeParse Tentative; + if (ParseLambdaIntroducer(Intro, &Tentative)) { + // We hit a hard error after deciding this was not an attribute. + // FIXME: Don't parse and annotate expressions when disambiguating + // against an attribute. + return CAK_NotAttributeSpecifier; + } - if (OuterMightBeMessageSend) - // Case 4: Lambda in message send. + switch (Tentative) { + case LambdaIntroducerTentativeParse::MessageSend: + // Case 3: The inner construct is definitely a message send, so the + // outer construct is definitely not an attribute. return CAK_NotAttributeSpecifier; - // Case 2: Lambda in array size / index. - return CAK_InvalidAttributeSpecifier; + case LambdaIntroducerTentativeParse::Success: + case LambdaIntroducerTentativeParse::Incomplete: + // This is a lambda-introducer or attribute-specifier. + if (Tok.is(tok::r_square)) + // Case 1: C++11 attribute. + return CAK_AttributeSpecifier; + + if (OuterMightBeMessageSend) + // Case 4: Lambda in message send. + return CAK_NotAttributeSpecifier; + + // Case 2: Lambda in array size / index. + return CAK_InvalidAttributeSpecifier; + + case LambdaIntroducerTentativeParse::Invalid: + // No idea what this is; we couldn't parse it as a lambda-introducer. + // Might still be an attribute-specifier or a message send. + break; + } } ConsumeBracket(); |