forked from OSchip/llvm-project
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
This commit is contained in:
parent
5a54065c4f
commit
01fc001062
|
@ -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,
|
||||
|
|
|
@ -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 '<'
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue