diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-12-16 03:12:41 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-12-16 03:12:41 +0000 |
commit | 0af550115df1f57f17a4f125ff0e8b34820c65d1 (patch) | |
tree | ef5aba0397d507447128ebb837e6c77b782dfb62 | |
parent | bd79119a50172db92ad3ce77ec3ac3c51e42a126 (diff) |
Fix chaining of ObjCInterfaceDecl redeclarations
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146722 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 3 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 5 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 10 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 3 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 36 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 24 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 23 | ||||
-rw-r--r-- | test/Modules/Inputs/decl2.h | 1 | ||||
-rw-r--r-- | test/Modules/Inputs/module.map | 1 | ||||
-rw-r--r-- | test/SemaObjC/forward-class-1.m | 2 |
11 files changed, 64 insertions, 45 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 9f207823f2..c272580650 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -853,7 +853,8 @@ public: QualType getPackExpansionType(QualType Pattern, llvm::Optional<unsigned> NumExpansions); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const; + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + ObjCInterfaceDecl *PrevDecl = 0) const; QualType getObjCObjectType(QualType Base, ObjCProtocolDecl * const *Protocols, diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index d3335220e1..c13e1baa56 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -614,9 +614,12 @@ public: static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, + ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc = SourceLocation(), bool isInternal = false); + static ObjCInterfaceDecl *CreateEmpty(ASTContext &C); + virtual SourceRange getSourceRange() const { if (isThisDeclarationADefinition()) return ObjCContainerDecl::getSourceRange(); @@ -916,8 +919,6 @@ public: return getFirstDeclaration(); } - void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl); - // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f65888fad8..de0250ced4 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2808,11 +2808,17 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const { /// getObjCInterfaceType - Return the unique reference to the type for the /// specified ObjC interface decl. The list of protocols is optional. -QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const { +QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + ObjCInterfaceDecl *PrevDecl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - // FIXME: redeclarations? + if (PrevDecl) { + assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); + Decl->TypeForDecl = PrevDecl->TypeForDecl; + return QualType(PrevDecl->TypeForDecl, 0); + } + void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment); ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl); Decl->TypeForDecl = T; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index ac3b536ace..963643e542 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3182,7 +3182,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { if (!ToIface) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), - Name.getAsIdentifierInfo(), Loc, + Name.getAsIdentifierInfo(), + /*PrevDecl=*/0,Loc, D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index d420b2be49..317dc95f54 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -225,18 +225,19 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( void ObjCInterfaceDecl::allocateDefinitionData() { assert(!hasDefinition() && "ObjC class already has a definition"); Data = new (getASTContext()) DefinitionData(); - Data->Definition = this; - + Data->Definition = this; +} + +void ObjCInterfaceDecl::startDefinition() { + allocateDefinitionData(); + // Update all of the declarations with a pointer to the definition. for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); RD != RDEnd; ++RD) { if (*RD != this) RD->Data = Data; } -} -void ObjCInterfaceDecl::startDefinition() { - allocateDefinitionData(); if (ASTMutationListener *L = getASTContext().getASTMutationListener()) L->CompletedObjCForwardRef(this); } @@ -674,9 +675,24 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, + ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc, bool isInternal){ - return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, isInternal); + ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, + isInternal); + C.getObjCInterfaceType(Result, PrevDecl); + + if (PrevDecl) { + Result->Data = PrevDecl->Data; + Result->setPreviousDeclaration(PrevDecl); + } + + return Result; +} + +ObjCInterfaceDecl *ObjCInterfaceDecl::CreateEmpty(ASTContext &C) { + return new (C) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(), + false); } ObjCInterfaceDecl:: @@ -851,14 +867,6 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, return false; } -void ObjCInterfaceDecl::setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl) { - redeclarable_base::setPreviousDeclaration(PrevDecl); - - // Inherit the 'Data' pointer from the previous declaration. - if (PrevDecl) - Data = PrevDecl->Data; -} - //===----------------------------------------------------------------------===// // ObjCIvarDecl //===----------------------------------------------------------------------===// diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 2b7be7eaca..c95cf224cd 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -82,6 +82,7 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { ObjCInterfaceDecl *ProtocolDecl = ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("Protocol"), + /*PrevDecl=*/0, SourceLocation(), true); Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); PushOnScopeChains(ProtocolDecl, TUScope, false); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 02a83e5327..4f87db426d 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -366,11 +366,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } // Create a declaration to describe this @interface. + ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, - ClassLoc); + PrevIDecl, ClassLoc); - ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); if (PrevIDecl) { // Class already seen. Was it a definition? if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { @@ -379,9 +379,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, Diag(Def->getLocation(), diag::note_previous_definition); IDecl->setInvalidDecl(); } - - // Link to the previous declaration. - IDecl->setPreviousDeclaration(PrevIDecl); } if (AttrList) @@ -870,9 +867,8 @@ Decl *Sema::ActOnStartClassImplementation( Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { - if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), - diag::warn_undef_interface)) - IDecl = 0; + RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), + diag::warn_undef_interface); } else { // We did not find anything with the name ClassName; try to correct for // typos in the class name. @@ -928,7 +924,8 @@ Decl *Sema::ActOnStartClassImplementation( // FIXME: Do we support attributes on the @implementation? If so we should // copy them over. IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, - ClassName, ClassLoc, true); + ClassName, /*PrevDecl=*/0, ClassLoc, + true); IDecl->startDefinition(); if (SDecl) { IDecl->setSuperClass(SDecl); @@ -1774,16 +1771,13 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, } // Create a declaration to describe this forward declaration. + ObjCInterfaceDecl *PrevIDecl + = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], IdentLocs[i], true); + IdentList[i], PrevIDecl, IdentLocs[i], true); IDecl->setAtEndRange(IdentLocs[i]); - // If there was a previous declaration, link to it. - if (ObjCInterfaceDecl *PrevIDecl - = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl)) - IDecl->setPreviousDeclaration(PrevIDecl); - // Create the forward declaration. Note that we intentionally do this // before we add the ObjCInterfaceDecl we just created, so that the // rewriter sees the ObjCClassDecl first. diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index cacacd2394..5e5f1cb6fe 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -223,6 +223,9 @@ void ASTDeclReader::Visit(Decl *D) { if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { // if we have a fully initialized TypeDecl, we can safely read its type now. TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull()); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + // if we have a fully initialized TypeDecl, we can safely read its type now. + ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull(); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // FunctionDecl's body was written last after all other Stmts/Exprs. if (Record[Idx++]) @@ -556,7 +559,7 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { VisitRedeclarable(ID); VisitObjCContainerDecl(ID); - ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull()); + TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); ObjCInterfaceDecl *Def = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); if (ID == Def) { @@ -621,13 +624,13 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { // pending references were linked. Reader.PendingForwardRefs.erase(ID); #endif - } else if (Def) { - if (Def->Data) { - ID->Data = Def->Data; - } else { - // The definition is still initializing. - Reader.PendingForwardRefs[Def].push_back(ID); - } + } + } else if (Def) { + if (Def->Data) { + ID->Data = Def->Data; + } else { + // The definition is still initializing. + Reader.PendingForwardRefs[Def].push_back(ID); } } } @@ -1561,6 +1564,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { FD->RedeclLink.setPointer(cast<FunctionDecl>(previous)); } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { VD->RedeclLink.setPointer(cast<VarDecl>(previous)); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(previous)) { + ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous)); } else { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous); @@ -1736,7 +1741,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { Selector(), QualType(), 0, 0); break; case DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::Create(Context, 0, SourceLocation(), 0); + D = ObjCInterfaceDecl::CreateEmpty(Context); break; case DECL_OBJC_IVAR: D = ObjCIvarDecl::Create(Context, 0, SourceLocation(), SourceLocation(), diff --git a/test/Modules/Inputs/decl2.h b/test/Modules/Inputs/decl2.h new file mode 100644 index 0000000000..decf6e033a --- /dev/null +++ b/test/Modules/Inputs/decl2.h @@ -0,0 +1 @@ +@class A; diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 6b93a6acef..f7cc7d4b51 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -39,5 +39,6 @@ module load_failure { header "load_failure.h" } module decldef { explicit module Decl { header "decl.h" } + explicit module Decl2 { header "decl2.h" } explicit module Def { header "def.h" } }
\ No newline at end of file diff --git a/test/SemaObjC/forward-class-1.m b/test/SemaObjC/forward-class-1.m index f5ce8892d3..e8c36957a3 100644 --- a/test/SemaObjC/forward-class-1.m +++ b/test/SemaObjC/forward-class-1.m @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -@class FOO, BAR; @class FOO, BAR; // expected-note {{forward declaration of class here}} +@class FOO, BAR; @interface INTF : FOO // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}} @end |