Try harder to recognize hidden tag type names in potential declarations instead

of giving unhelpful errors about undeclared identifers and missing semicolons.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155965 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kaelyn Uhrain 2012-05-02 00:11:40 +00:00
Родитель 2a6e30d9ec
Коммит 12f3297fbe
2 изменённых файлов: 90 добавлений и 44 удалений

Просмотреть файл

@ -470,6 +470,55 @@ static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) {
return false;
}
static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
Scope *S, CXXScopeSpec &SS,
IdentifierInfo *&Name,
SourceLocation NameLoc) {
Result.clear(Sema::LookupTagName);
SemaRef.LookupParsedName(Result, S, &SS);
if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) {
const char *TagName = 0;
const char *FixItTagName = 0;
switch (Tag->getTagKind()) {
case TTK_Class:
TagName = "class";
FixItTagName = "class ";
break;
case TTK_Enum:
TagName = "enum";
FixItTagName = "enum ";
break;
case TTK_Struct:
TagName = "struct";
FixItTagName = "struct ";
break;
case TTK_Union:
TagName = "union";
FixItTagName = "union ";
break;
}
SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
<< Name << TagName << SemaRef.getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(NameLoc, FixItTagName);
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupOrdinaryName);
if (SemaRef.LookupParsedName(R, S, &SS)) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end();
I != IEnd; ++I)
SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
<< Name << TagName;
}
return true;
}
Result.clear(Sema::LookupOrdinaryName);
return false;
}
Sema::NameClassification Sema::ClassifyName(Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *&Name,
@ -533,49 +582,9 @@ Corrected:
// In C, we first see whether there is a tag type by the same name, in
// which case it's likely that the user just forget to write "enum",
// "struct", or "union".
if (!getLangOpts().CPlusPlus && !SecondTry) {
Result.clear(LookupTagName);
LookupParsedName(Result, S, &SS);
if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) {
const char *TagName = 0;
const char *FixItTagName = 0;
switch (Tag->getTagKind()) {
case TTK_Class:
TagName = "class";
FixItTagName = "class ";
break;
case TTK_Enum:
TagName = "enum";
FixItTagName = "enum ";
break;
case TTK_Struct:
TagName = "struct";
FixItTagName = "struct ";
break;
case TTK_Union:
TagName = "union";
FixItTagName = "union ";
break;
}
Diag(NameLoc, diag::err_use_of_tag_name_without_tag)
<< Name << TagName << getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(NameLoc, FixItTagName);
LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
if (LookupParsedName(R, S, &SS)) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end();
I != IEnd; ++I)
Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
<< Name << TagName;
}
break;
}
Result.clear(LookupOrdinaryName);
if (!getLangOpts().CPlusPlus && !SecondTry &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
break;
}
// Perform typo correction to determine if there is another name that is
@ -773,6 +782,23 @@ Corrected:
return ParsedType::make(T);
}
// Check for a tag type hidden by a non-type decl in a few cases where it
// seems likely a type is wanted instead of the non-type that was found.
if (!getLangOpts().ObjC1 && FirstDecl && !isa<ClassTemplateDecl>(FirstDecl) &&
!isa<TypeAliasTemplateDecl>(FirstDecl)) {
bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
if ((NextToken.is(tok::identifier) ||
(NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
FirstDecl = (*Result.begin())->getUnderlyingDecl();
if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
DiagnoseUseOfDecl(Type, NameLoc);
QualType T = Context.getTypeDeclType(Type);
return ParsedType::make(T);
}
}
}
if (!Result.empty() && (*Result.begin())->isCXXClassMember())
return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0);

Просмотреть файл

@ -70,3 +70,23 @@ void foo() {
fn(1); // expected-error {{no matching function}}
fn(g); // OK
}
namespace PR11874 {
void foo(); // expected-note 3 {{class 'foo' is hidden by a non-type declaration of 'foo' here}}
class foo {};
class bar {
bar() {
const foo* f1 = 0; // expected-error {{must use 'class' tag to refer to type 'foo' in this scope}}
foo* f2 = 0; // expected-error {{must use 'class' tag to refer to type 'foo' in this scope}}
foo f3; // expected-error {{must use 'class' tag to refer to type 'foo' in this scope}}
}
};
int baz; // expected-note 2 {{class 'baz' is hidden by a non-type declaration of 'baz' here}}
class baz {};
void fizbin() {
const baz* b1 = 0; // expected-error {{must use 'class' tag to refer to type 'baz' in this scope}}
baz* b2; // expected-error {{use of undeclared identifier 'b2'}}
baz b3; // expected-error {{must use 'class' tag to refer to type 'baz' in this scope}}
}
}