summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2011-09-19 19:01:00 +0000
committerRichard Trieu <rtrieu@google.com>2011-09-19 19:01:00 +0000
commit01fc00106225e5d5e8a50637bcf8edbfa20a431d (patch)
treedcebed84a90f81be7733ef59fc1ea2ab935364dc
parent5a54065c4f1220ef6b1128c6fe59f9c962b32b21 (diff)
downloadbcm5719-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.h4
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp48
-rw-r--r--clang/lib/Parse/ParseStmt.cpp5
-rw-r--r--clang/test/Parser/cxx-casting.cpp16
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>();
+}
OpenPOWER on IntegriCloud