diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-11-09 22:09:58 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-11-09 22:09:58 +0000 |
commit | 630c81b78a6a469707e2940a421da874f3b12643 (patch) | |
tree | 871abdc474563f13143fd530be85e26a13a66529 /lib/Sema/SemaDecl.cpp | |
parent | ce179ab4358c152164899c032302d8b0e81982b6 (diff) |
Simplify handling of nested-names in tags ('struct foo::bar').
-Use more of the non nested-name code path.
-Also use the ActOnTagStruct code path.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58944 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 109 |
1 files changed, 52 insertions, 57 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 66e43c2d4c..d0cb986fb6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2138,68 +2138,41 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, case DeclSpec::TST_class: Kind = TagDecl::TK_class; break; case DeclSpec::TST_enum: Kind = TagDecl::TK_enum; break; } + + // Two code paths: a new one for structs/unions/classes where we create + // separate decls for forward declarations, and an old (eventually to + // be removed) code path for enums. + if (Kind != TagDecl::TK_enum) + return ActOnTagStruct(S, Kind, TK, KWLoc, SS, Name, NameLoc, Attr); + + ScopedDecl *PrevDecl; if (Name && SS.isNotEmpty()) { + // We have a nested-name tag ('struct foo::bar'). + + // Check for invalid 'foo::'. DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep()); if (DC == 0) { - // Invalid C++ scope specifier. Name = 0; goto CreateNewDecl; } - TagDecl *PrevDecl = - dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag, S, DC)); + PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC)); + + // A tag 'foo::bar' must already exist. if (PrevDecl == 0) { - // No tag member found. Diag(NameLoc, diag::err_not_tag_in_scope, Name->getName(), SS.getRange()); Name = 0; goto CreateNewDecl; } - - if (PrevDecl->getTagKind() != Kind) { - Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName()); - Diag(PrevDecl->getLocation(), diag::err_previous_use); - // Recover by making this an anonymous redefinition. - Name = 0; - goto CreateNewDecl; - } - - // 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 (PrevDecl->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; - goto CreateNewDecl; - } - - // 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; + } else { + // If this is a named struct, check to see if there was a previous forward + // declaration or definition. + // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up. + PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S)); } - - // Two code paths: a new one for structs/unions/classes where we create - // separate decls for forward declarations, and an old (eventually to - // be removed) code path for enums. - if (Kind != TagDecl::TK_enum) - return ActOnTagStruct(S, Kind, TK, KWLoc, Name, NameLoc, Attr); - - { - // If this is a named struct, check to see if there was a previous forward - // declaration or definition. - // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up. - ScopedDecl *PrevDecl = - dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag, S)); - if (PrevDecl) { assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) && "unexpected Decl type"); @@ -2252,8 +2225,6 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, } } - } // subscope in which an already declared tag is handled. - CreateNewDecl: // If there is an identifier, use the location of the identifier as the @@ -2301,14 +2272,36 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, /// the logic for enums, we create separate decls for forward declarations. /// This is called by ActOnTag, but eventually will replace its logic. Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK, - SourceLocation KWLoc, IdentifierInfo *Name, - SourceLocation NameLoc, AttributeList *Attr) { - - // If this is a named struct, check to see if there was a previous forward - // declaration or definition. - // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up. - ScopedDecl *PrevDecl = - dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag, S)); + SourceLocation KWLoc, const CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr) { + ScopedDecl *PrevDecl; + + if (Name && SS.isNotEmpty()) { + // We have a nested-name tag ('struct foo::bar'). + + // Check for invalid 'foo::'. + DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep()); + if (DC == 0) { + Name = 0; + goto CreateNewDecl; + } + + PrevDecl = dyn_cast_or_null<TagDecl>(LookupDecl(Name, Decl::IDNS_Tag,S,DC)); + + // A tag 'foo::bar' must already exist. + if (PrevDecl == 0) { + Diag(NameLoc, diag::err_not_tag_in_scope, Name->getName(), + SS.getRange()); + Name = 0; + goto CreateNewDecl; + } + } else { + // If this is a named struct, check to see if there was a previous forward + // declaration or definition. + // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up. + PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S)); + } if (PrevDecl) { assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) && @@ -2375,7 +2368,9 @@ Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK, } } } - + + CreateNewDecl: + // If there is an identifier, use the location of the identifier as the // location of the decl, otherwise use the location of the struct/union // keyword. |