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:
Richard Trieu 2011-09-19 19:01:00 +00:00
parent 5a54065c4f
commit 01fc001062
4 changed files with 51 additions and 22 deletions

View File

@ -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,

View File

@ -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 '<'

View File

@ -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()) {

View File

@ -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>();
}