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.  | 

