diff options
| author | Richard Trieu <rtrieu@google.com> | 2011-09-19 19:01:00 +0000 |
|---|---|---|
| committer | Richard Trieu <rtrieu@google.com> | 2011-09-19 19:01:00 +0000 |
| commit | 01fc00106225e5d5e8a50637bcf8edbfa20a431d (patch) | |
| tree | dcebed84a90f81be7733ef59fc1ea2ab935364dc | |
| parent | 5a54065c4f1220ef6b1128c6fe59f9c962b32b21 (diff) | |
| download | bcm5719-llvm-01fc00106225e5d5e8a50637bcf8edbfa20a431d.tar.gz bcm5719-llvm-01fc00106225e5d5e8a50637bcf8edbfa20a431d.zip | |
Changes to the name lookup have caused a regression in the digraph fix-it hint.
For instance:
template <class T> void E() {};
class F {};
void test() {
::E<::F>();
E<::F>();
}
Gives the following error messages:
error: found '<::' after a template name which forms the
digraph '<:' (aka '[') and a ':', did you mean '< ::'?
::E<::F>();
^~~
< ::
error: expected expression
E<::F>();
^
error: expected ']'
note: to match this '['
E<::F>();
This patch adds the digraph fix-it check right before the name lookup,
moves the shared checking code to a new function, and adds new
tests to catch future regressions.
llvm-svn: 140039
| -rw-r--r-- | clang/include/clang/Parse/Parser.h | 4 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 48 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 5 | ||||
| -rw-r--r-- | clang/test/Parser/cxx-casting.cpp | 16 |
4 files changed, 51 insertions, 22 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d32c36efbdf..ee2dbd55198 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1237,6 +1237,10 @@ private: // C++ Expressions ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); + void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr, + bool EnteringContext, IdentifierInfo &II, + CXXScopeSpec &SS); + bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 4086da84ab2..88abce9c5e2 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -70,6 +70,31 @@ static void FixDigraph(Parser &P, Preprocessor &PP, Token &DigraphToken, PP.EnterToken(DigraphToken); } +// Check for '<::' which should be '< ::' instead of '[:' when following +// a template name. +void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, + bool EnteringContext, + IdentifierInfo &II, CXXScopeSpec &SS) { + if (!Next.is(tok::l_square) || !Next.getLength() == 2) + return; + + Token SecondToken = GetLookAheadToken(2); + if (!SecondToken.is(tok::colon) || !AreTokensAdjacent(PP, Next, SecondToken)) + return; + + TemplateTy Template; + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&II, Tok.getLocation()); + bool MemberOfUnknownSpecialization; + if (!Actions.isTemplateName(getCurScope(), SS, /*hasTemplateKeyword=*/false, + TemplateName, ObjectType, EnteringContext, + Template, MemberOfUnknownSpecialization)) + return; + + FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, + /*AtDigraph*/false); +} + /// \brief Parse global scope or nested-name-specifier if present. /// /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which @@ -341,28 +366,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } - // Check for '<::' which should be '< ::' instead of '[:' when following - // a template name. - if (Next.is(tok::l_square) && Next.getLength() == 2) { - Token SecondToken = GetLookAheadToken(2); - if (SecondToken.is(tok::colon) && - AreTokensAdjacent(PP, Next, SecondToken)) { - TemplateTy Template; - UnqualifiedId TemplateName; - TemplateName.setIdentifier(&II, Tok.getLocation()); - bool MemberOfUnknownSpecialization; - if (Actions.isTemplateName(getCurScope(), SS, - /*hasTemplateKeyword=*/false, - TemplateName, - ObjectType, - EnteringContext, - Template, - MemberOfUnknownSpecialization)) { - FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, - /*AtDigraph*/false); - } - } - } + CheckForTemplateAndDigraph(Next, ObjectType, EnteringContext, II, SS); // nested-name-specifier: // type-name '<' diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index c1ead6bdef8..58514b04676 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -114,6 +114,11 @@ Retry: CXXScopeSpec SS; IdentifierInfo *Name = Tok.getIdentifierInfo(); SourceLocation NameLoc = Tok.getLocation(); + + if (getLang().CPlusPlus) + CheckForTemplateAndDigraph(Next, ParsedType(), + /*EnteringContext=*/false, *Name, SS); + Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next); switch (Classification.getKind()) { diff --git a/clang/test/Parser/cxx-casting.cpp b/clang/test/Parser/cxx-casting.cpp index 4a0bb4d1e4e..cb82c8efdad 100644 --- a/clang/test/Parser/cxx-casting.cpp +++ b/clang/test/Parser/cxx-casting.cpp @@ -67,3 +67,19 @@ void test2(char x, struct B * b) { test1::A LCC B> e; // expected-error{{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} (void)static_cast LCC c>(&x); // expected-error{{found '<::' after a static_cast which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} } + +template <class T> class D {}; +template <class T> void E() {}; +class F {}; + +void test3() { + ::D<::F> A1; // expected-error{{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} + D<::F> A2; // expected-error{{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} + ::E<::F>(); // expected-error{{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} + E<::F>(); // expected-error{{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}} + + ::D< ::F> A3; + D< ::F> A4; + ::E< ::F>(); + E< ::F>(); +} |

