diff options
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 70 |
1 files changed, 33 insertions, 37 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cfd33f6123..7346526265 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2813,9 +2813,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, /// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. -/// TagType indicates what kind of tag this is. TK indicates whether this is a +/// TagSpec indicates what kind of tag this is. TK indicates whether this is a /// reference/declaration/definition of a tag. -Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, +Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, @@ -2825,7 +2825,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, "Nameless record must be a definition!"); TagDecl::TagKind Kind; - switch (TagType) { + switch (TagSpec) { default: assert(0 && "Unknown tag type!"); case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break; case DeclSpec::TST_union: Kind = TagDecl::TK_union; break; @@ -2838,6 +2838,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, DeclContext *LexicalContext = CurContext; ScopedDecl *PrevDecl = 0; + bool Invalid = false; + if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -2898,6 +2900,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, // Recover by making this an anonymous redefinition. Name = 0; PrevDecl = 0; + Invalid = true; } else { // If this is a use, just return the declaration we found. @@ -2913,15 +2916,29 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) { Diag(NameLoc, diag::err_redefinition) << Name; Diag(Def->getLocation(), diag::note_previous_definition); - // If this is a redefinition, recover by making this struct be - // anonymous, which will make any later references get the 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; PrevDecl = 0; + Invalid = true; + } else { + // If the type is currently being defined, complain + // about a nested redefinition. + TagType *Tag = cast<TagType>(Context.getTagDeclType(PrevTagDecl)); + if (Tag->isBeingDefined()) { + Diag(NameLoc, diag::err_nested_redefinition) << Name; + Diag(PrevTagDecl->getLocation(), + diag::note_previous_definition); + Name = 0; + PrevDecl = 0; + Invalid = true; + } } + // Okay, this is definition of a previously declared or referenced // tag PrevDecl. We're going to create a new Decl for it. - } + } } // If we get here we have (another) forward declaration or we // have a definition. Just create a new decl. @@ -2944,6 +2961,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, Diag(PrevDecl->getLocation(), diag::note_previous_definition); Name = 0; PrevDecl = 0; + Invalid = true; } else { // The existing declaration isn't relevant to us; we're in a // new scope, so clear out the previous declaration. @@ -3034,16 +3052,23 @@ CreateNewDecl: New->addAttr(new PackedAttr(Alignment * 8)); } + if (Invalid) + New->setInvalidDecl(); + if (Attr) ProcessDeclAttributeList(New, Attr); - // If we're declaring or defining + // If we're declaring or defining a tag in function prototype scope + // in C, note that this type can only be used within the function. if (Name && S->isFunctionPrototypeScope() && !getLangOptions().CPlusPlus) Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); // Set the lexical context. If the tag has a C++ scope specifier, the // lexical context will be different from the semantic context. New->setLexicalDeclContext(LexicalContext); + + if (TK == TK_Definition) + New->startDefinition(); // If this has an identifier, add it to the scope stack. if (Name) { @@ -3332,22 +3357,6 @@ void Sema::ActOnFields(Scope* S, assert(EnclosingDecl && "missing record or interface decl"); RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); - if (Record) { - QualType RecordType = Context.getTypeDeclType(Record); - if (RecordType->getAsRecordType()->getDecl()->isDefinition()) { - RecordDecl *Def = RecordType->getAsRecordType()->getDecl(); - // Diagnose code like: - // struct S { struct S {} X; }; - // We discover this when we complete the outer S. Reject and ignore the - // outer S. - Diag(Def->getLocation(), diag::err_nested_redefinition) - << Def->getDeclName(); - Diag(RecLoc, diag::note_previous_definition); - Record->setInvalidDecl(); - return; - } - } - // Verify that all the fields are okay. unsigned NumNamedMembers = 0; llvm::SmallVector<FieldDecl*, 32> RecFields; @@ -3564,19 +3573,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX)); QualType EnumType = Context.getTypeDeclType(Enum); - if (EnumType->getAsEnumType()->getDecl()->isDefinition()) { - EnumDecl *Def = EnumType->getAsEnumType()->getDecl(); - // Diagnose code like: - // enum e0 { - // E0 = sizeof(enum e0 { E1 }) - // }; - Diag(Def->getLocation(), diag::err_nested_redefinition) - << Enum->getDeclName(); - Diag(Enum->getLocation(), diag::note_previous_definition); - Enum->setInvalidDecl(); - return; - } - // TODO: If the result value doesn't fit in an int, it must be a long or long // long value. ISO C does not support this, but GCC does as an extension, // emit a warning. |