aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/Parser.h4
-rw-r--r--lib/Parse/ParseExprCXX.cpp48
-rw-r--r--lib/Parse/ParseStmt.cpp5
-rw-r--r--test/Parser/cxx-casting.cpp16
4 files changed, 51 insertions, 22 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index d32c36efbd..ee2dbd5519 100644
--- a/include/clang/Parse/Parser.h
+++ b/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/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 4086da84ab..88abce9c5e 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/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/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index c1ead6bdef..58514b0467 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/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/test/Parser/cxx-casting.cpp b/test/Parser/cxx-casting.cpp
index 4a0bb4d1e4..cb82c8efda 100644
--- a/test/Parser/cxx-casting.cpp
+++ b/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>();
+}