forked from OSchip/llvm-project
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:
parent
b261292917
commit
9ff58d7caf
|
@ -1688,35 +1688,38 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
|
||||||
assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
|
assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
|
||||||
"unexpected Decl type");
|
"unexpected Decl type");
|
||||||
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
|
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
|
||||||
// If this is a use of a previous tag, or if the tag is already declared in
|
// If this is a use of a previous tag, or if the tag is already declared
|
||||||
// the same scope (so that the definition/declaration completes or
|
// in the same scope (so that the definition/declaration completes or
|
||||||
// rementions the tag), reuse the decl.
|
// rementions the tag), reuse the decl.
|
||||||
if (TK == TK_Reference ||
|
if (TK == TK_Reference ||
|
||||||
IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
|
IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
|
||||||
// Make sure that this wasn't declared as an enum and now used as a struct
|
// Make sure that this wasn't declared as an enum and now used as a
|
||||||
// or something similar.
|
// struct or something similar.
|
||||||
if (PrevTagDecl->getTagKind() != Kind) {
|
if (PrevTagDecl->getTagKind() != Kind) {
|
||||||
Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
|
Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
|
||||||
Diag(PrevDecl->getLocation(), diag::err_previous_use);
|
Diag(PrevDecl->getLocation(), diag::err_previous_use);
|
||||||
}
|
// Recover by making this an anonymous redefinition.
|
||||||
|
|
||||||
// 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;
|
Name = 0;
|
||||||
|
PrevDecl = 0;
|
||||||
} else {
|
} else {
|
||||||
// Okay, this is definition of a previously declared or referenced tag.
|
// If this is a use or a forward declaration, we're good.
|
||||||
// Move the location of the decl to be the definition site.
|
if (TK != TK_Definition)
|
||||||
PrevDecl->setLocation(NameLoc);
|
return PrevDecl;
|
||||||
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
|
// If we get here, this is a definition of a new struct type in a nested
|
||||||
|
|
|
@ -28,3 +28,8 @@ int test2(int i)
|
||||||
{
|
{
|
||||||
ve + 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}}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue