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 | e02eb2bac2ef8db85fb7a5da119b8b1a2530e618 (patch) | |
tree | 75436476f9018532f989c31fb39593a2b0da224b | |
parent | 7aee5cf8fde9c78e5c8ec31b14644eb60e53aa67 (diff) | |
download | bcm5719-llvm-e02eb2bac2ef8db85fb7a5da119b8b1a2530e618.tar.gz bcm5719-llvm-e02eb2bac2ef8db85fb7a5da119b8b1a2530e618.zip |
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.
llvm-svn: 58944
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 109 |
2 files changed, 55 insertions, 59 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 99d9181b6c8..178ab13f166 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -314,8 +314,9 @@ public: AttributeList *Attr); DeclTy* ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK, - SourceLocation KWLoc, IdentifierInfo *Name, - SourceLocation NameLoc, AttributeList *Attr); + SourceLocation KWLoc, const CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr); virtual void ActOnDefs(Scope *S, SourceLocation DeclStart, IdentifierInfo *ClassName, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 66e43c2d4c3..d0cb986fb6a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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. |