diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-01-01 19:51:50 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-01-01 19:51:50 +0000 |
commit | 1d784b277cdfd4eba03680715d2a082b3f28d295 (patch) | |
tree | 5070a82eb117524e15f1f15ef324c52f4ea61687 | |
parent | 5e2a1ff9f28d2eab256d2553e76a9c9d54693875 (diff) |
Introduce the core infrastructure needed to model redeclaration chains
for Objective-C protocols, including:
- Using the first declaration as the canonical declaration
- Using the definition as the primary DeclContext
- Making sure that all declarations have a pointer to the definition
data, and that we know which declaration is the definition
- Serialization support for redeclaration chains and for adding
definitions to already-serialized declarations.
However, note that we're not taking advantage of much of this code
yet, because we're still re-using ObjCProtocolDecls.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147410 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclObjC.h | 29 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 6 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTCommon.h | 3 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 24 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 24 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 19 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 1 |
11 files changed, 110 insertions, 19 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 9a594a68db..e5c89b8948 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1063,10 +1063,14 @@ public: /// /// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; /// -class ObjCProtocolDecl : public ObjCContainerDecl { +class ObjCProtocolDecl : public ObjCContainerDecl, + public Redeclarable<ObjCProtocolDecl> { virtual void anchor(); struct DefinitionData { + // \brief The declaration that defines this protocol. + ObjCProtocolDecl *Definition; + /// Referenced protocols ObjCProtocolList ReferencedProtocols; }; @@ -1093,7 +1097,12 @@ class ObjCProtocolDecl : public ObjCContainerDecl { } void allocateDefinitionData(); - + + typedef Redeclarable<ObjCProtocolDecl> redeclarable_base; + virtual ObjCProtocolDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + public: static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, @@ -1163,12 +1172,12 @@ public: /// \brief Retrieve the definition of this protocol, if any. ObjCProtocolDecl *getDefinition() { - return hasDefinition()? this : 0; + return Data? Data->Definition : 0; } /// \brief Retrieve the definition of this protocol, if any. const ObjCProtocolDecl *getDefinition() const { - return hasDefinition()? this : 0; + return Data? Data->Definition : 0; } /// \brief Determine whether this particular declaration is also the @@ -1192,12 +1201,20 @@ public: SourceLocation getLocEnd() const { return EndLoc; } void setLocEnd(SourceLocation LE) { EndLoc = LE; } + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } + /// Retrieves the canonical declaration of this Objective-C protocol. ObjCProtocolDecl *getCanonicalDecl() { - return this; + return getFirstDeclaration(); } const ObjCProtocolDecl *getCanonicalDecl() const { - return this; + return getFirstDeclaration(); } static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 983673fec8..a71275a2c1 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -784,8 +784,10 @@ DeclContext *DeclContext::getPrimaryContext() { return this; case Decl::ObjCProtocol: - // FIXME: Update when protocols properly model forward declarations. - // For now, it's fine to fall through + if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(this)->getDefinition()) + return Def; + + return this; case Decl::ObjCCategory: return this; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index f5828fcb4c..341f0f5e93 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -1005,11 +1005,17 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, void ObjCProtocolDecl::allocateDefinitionData() { assert(!Data && "Protocol already has a definition!"); - Data = new (getASTContext()) DefinitionData; + Data = new (getASTContext()) DefinitionData; + Data->Definition = this; } void ObjCProtocolDecl::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) + RD->Data = this->Data; } void ObjCProtocolDecl::completedForwardDecl() { diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 0a207ab76d..3a591e88dd 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -1529,6 +1529,11 @@ llvm::Constant *CGObjCGNU::GenerateEmptyProtocol( void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { ASTContext &Context = CGM.getContext(); std::string ProtocolName = PD->getNameAsString(); + + // Use the protocol definition, if there is one. + if (const ObjCProtocolDecl *Def = PD->getDefinition()) + PD = Def; + SmallVector<std::string, 16> Protocols; for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), E = PD->protocol_end(); PI != E; ++PI) diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 121395676f..a782db76f6 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1787,6 +1787,10 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { if (Entry && Entry->hasInitializer()) return Entry; + // Use the protocol definition, if there is one. + if (const ObjCProtocolDecl *Def = PD->getDefinition()) + PD = Def; + // FIXME: I don't understand why gcc generates this, or where it is // resolved. Investigate. Its also wasteful to look this up over and over. LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); @@ -5413,6 +5417,10 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( if (Entry && Entry->hasInitializer()) return Entry; + // Use the protocol definition, if there is one. + if (const ObjCProtocolDecl *Def = PD->getDefinition()) + PD = Def; + // Construct method lists. std::vector<llvm::Constant*> InstanceMethods, ClassMethods; std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 389abd5ec7..f7dd69a78a 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1067,6 +1067,8 @@ static NamedDecl *getPreviousDeclaration(NamedDecl *D) { return TD->getPreviousDeclaration(); if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) return ID->getPreviousDeclaration(); + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + return PD->getPreviousDeclaration(); return 0; } diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index 2e3d70b853..2190844a83 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -27,7 +27,8 @@ enum DeclUpdateKind { UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, - UPD_OBJC_SET_CLASS_DEFINITIONDATA + UPD_OBJC_SET_CLASS_DEFINITIONDATA, + UPD_OBJC_SET_PROTOCOL_DEFINITIONDATA }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index dd48b2dc56..9c9e8b3ca9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6121,9 +6121,10 @@ void ASTReader::finishPendingActions() { PendingChainedObjCCategories.clear(); } - // If we deserialized any C++ or Objective-C class definitions, make sure - // that all redeclarations point to the definitions. Note that this can only - // happen now, after the redeclaration chains have been fully wired. + // If we deserialized any C++ or Objective-C class definitions or any + // Objective-C protocol definitions, make sure that all redeclarations point + // to the definitions. Note that this can only happen now, after the + // redeclaration chains have been fully wired. for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(), DEnd = PendingDefinitions.end(); D != DEnd; ++D) { @@ -6136,11 +6137,20 @@ void ASTReader::finishPendingActions() { continue; } - ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(*D); - for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), - REnd = ID->redecls_end(); + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) { + for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(), + REnd = ID->redecls_end(); + R != REnd; ++R) + R->Data = ID->Data; + + continue; + } + + ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(*D); + for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(), + REnd = PD->redecls_end(); R != REnd; ++R) - R->Data = ID->Data; + R->Data = PD->Data; } PendingDefinitions.clear(); } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index f88a394e90..38b69413ac 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -760,6 +760,7 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { + VisitRedeclarable(PD); VisitObjCContainerDecl(PD); PD->InitiallyForwardDecl = Record[Idx++]; PD->isForwardProtoDecl = Record[Idx++]; @@ -782,8 +783,8 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), Reader.getContext()); - // FIXME: Note that we have deserialized a definition. - // Reader.PendingDefinitions.insert(PD); + // Note that we have deserialized a definition. + Reader.PendingDefinitions.insert(PD); } else if (Def && Def->Data) { PD->Data = Def->Data; } @@ -1712,6 +1713,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { TD->RedeclLink.setPointer(cast<TypedefNameDecl>(previous)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous)); + } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + PD->RedeclLink.setPointer(cast<ObjCProtocolDecl>(previous)); } else { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous); @@ -1737,6 +1740,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { ID->RedeclLink = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink( cast<ObjCInterfaceDecl>(Latest)); + } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + PD->RedeclLink + = Redeclarable<ObjCProtocolDecl>::LatestDeclLink( + cast<ObjCProtocolDecl>(Latest)); } else { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->getCommonPtr()->Latest = cast<RedeclarableTemplateDecl>(Latest); @@ -2201,6 +2208,8 @@ static Decl *getPreviousDecl(Decl *D) { return TD->getPreviousDeclaration(); if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) return ID->getPreviousDeclaration(); + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + return PD->getPreviousDeclaration(); return cast<RedeclarableTemplateDecl>(D)->getPreviousDeclaration(); } @@ -2217,6 +2226,8 @@ static Decl *getMostRecentDecl(Decl *D) { return TD->getMostRecentDeclaration(); if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) return ID->getMostRecentDeclaration(); + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + return PD->getMostRecentDeclaration(); return cast<RedeclarableTemplateDecl>(D)->getMostRecentDeclaration(); } @@ -2454,6 +2465,15 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, ID->Data = Def->Data; break; } + + case UPD_OBJC_SET_PROTOCOL_DEFINITIONDATA: { + ObjCProtocolDecl *ID = cast<ObjCProtocolDecl>(D); + ObjCProtocolDecl *Def + = Reader.ReadDeclAs<ObjCProtocolDecl>(ModuleFile, Record, Idx); + if (Def->Data) + ID->Data = Def->Data; + break; + } } } } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index cfc83f7bc0..e59a3d39d1 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3483,6 +3483,7 @@ void ASTWriter::ResolveDeclUpdatesBlocks() { case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: case UPD_OBJC_SET_CLASS_DEFINITIONDATA: + case UPD_OBJC_SET_PROTOCOL_DEFINITIONDATA: URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx])); ++Idx; break; @@ -4447,6 +4448,24 @@ void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) { } } } + + if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + for (ObjCProtocolDecl::redecl_iterator I = PD->redecls_begin(), + E = PD->redecls_end(); + I != E; ++I) { + if (*I == PD) + continue; + + // We are interested when a PCH decl is modified. + if (I->isFromASTFile()) { + UpdateRecord &Record = DeclUpdates[*I]; + Record.push_back(UPD_OBJC_SET_PROTOCOL_DEFINITIONDATA); + assert((*I)->hasDefinition()); + assert((*I)->getDefinition() == D); + Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl + } + } + } } void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index f1394850ed..f6fc4304e7 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -517,6 +517,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { } void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + VisitRedeclarable(D); VisitObjCContainerDecl(D); Record.push_back(D->isInitiallyForwardDecl()); Record.push_back(D->isForwardProtoDecl); |