Fix PR2020 by recovering by defining an anonymous enum, instead of recovering

by filling in the body of a union with enum constants.

llvm-svn: 53069
This commit is contained in:
Chris Lattner 2008-07-03 03:30:58 +00:00
parent b261292917
commit 9ff58d7caf
2 changed files with 29 additions and 21 deletions

View File

@ -1688,35 +1688,38 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
"unexpected Decl type");
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
if (TK == TK_Reference ||
IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
// Make sure that this wasn't declared as an enum and now used as a struct
// or something similar.
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
if (PrevTagDecl->getTagKind() != Kind) {
Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
Diag(PrevDecl->getLocation(), diag::err_previous_use);
}
// If this is a use or a forward declaration, we're good.
if (TK != TK_Definition)
return PrevDecl;
// Diagnose attempts to redefine a tag.
if (PrevTagDecl->isDefinition()) {
Diag(NameLoc, diag::err_redefinition, Name->getName());
Diag(PrevDecl->getLocation(), diag::err_previous_definition);
// If this is a redefinition, recover by making this struct be
// anonymous, which will make any later references get the previous
// definition.
// Recover by making this an anonymous redefinition.
Name = 0;
PrevDecl = 0;
} else {
// Okay, this is definition of a previously declared or referenced tag.
// Move the location of the decl to be the definition site.
PrevDecl->setLocation(NameLoc);
return PrevDecl;
// If this is a use or a forward declaration, we're good.
if (TK != TK_Definition)
return PrevDecl;
// Diagnose attempts to redefine a tag.
if (PrevTagDecl->isDefinition()) {
Diag(NameLoc, diag::err_redefinition, Name->getName());
Diag(PrevDecl->getLocation(), diag::err_previous_definition);
// If this is a redefinition, recover by making this struct be
// anonymous, which will make any later references get the previous
// definition.
Name = 0;
} else {
// Okay, this is definition of a previously declared or referenced
// tag. Move the location of the decl to be the definition site.
PrevDecl->setLocation(NameLoc);
return PrevDecl;
}
}
}
// If we get here, this is a definition of a new struct type in a nested

View File

@ -28,3 +28,8 @@ int test2(int i)
{
ve + i;
}
// PR2020
union u0; // expected-error {{previous use is here}}
enum u0 { U0A }; // expected-error {{error: use of 'u0' with tag type that does not match previous declaration}}