From c03c52ea017aa470a05e12fe2a7fda91a2e22e3a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 15 Jan 2012 18:08:05 +0000 Subject: When deserializing the definition of a C++ class/ObjC class/ObjC protocol, record the definition pointer in the canonical declaration for that entity, and then propagate that definition pointer from the canonical declaration to all other deserialized declarations. This approach works well even when deserializing declarations that didn't know about the original definition, which can occur with modules. A nice bonus from this definition-deserialization approach is that we no longer need update records when a definition is added, because the redeclaration chains ensure that the if any declaration is loaded, the definition will also get loaded. llvm-svn: 148223 --- clang/lib/AST/DeclObjC.cpp | 6 ---- clang/lib/Serialization/ASTCommon.h | 5 +-- clang/lib/Serialization/ASTReaderDecl.cpp | 60 +++++++++++++------------------ clang/lib/Serialization/ASTWriter.cpp | 58 ------------------------------ 4 files changed, 25 insertions(+), 104 deletions(-) (limited to 'clang/lib') diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index b0aeabf68f8..6a3bdfd4bb4 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -245,9 +245,6 @@ void ObjCInterfaceDecl::startDefinition() { if (*RD != this) RD->Data = Data; } - - if (ASTMutationListener *L = getASTContext().getASTMutationListener()) - L->CompletedObjCForwardRef(this); } /// getFirstClassExtension - Find first class extension of the given class. @@ -1058,9 +1055,6 @@ void ObjCProtocolDecl::startDefinition() { for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); RD != RDEnd; ++RD) RD->Data = this->Data; - - if (ASTMutationListener *L = getASTContext().getASTMutationListener()) - L->CompletedObjCForwardRef(this); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h index 2190844a837..16db8e36952 100644 --- a/clang/lib/Serialization/ASTCommon.h +++ b/clang/lib/Serialization/ASTCommon.h @@ -22,13 +22,10 @@ namespace clang { namespace serialization { enum DeclUpdateKind { - UPD_CXX_SET_DEFINITIONDATA, UPD_CXX_ADDED_IMPLICIT_MEMBER, UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, - UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, - UPD_OBJC_SET_CLASS_DEFINITIONDATA, - UPD_OBJC_SET_PROTOCOL_DEFINITIONDATA + UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 6788d9ee5c6..863aabb1734 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -677,6 +677,10 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { // Read the definition. ID->allocateDefinitionData(); + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + ID->getCanonicalDecl()->Data = ID->Data; + ObjCInterfaceDecl::DefinitionData &Data = ID->data(); // Read the superclass. @@ -722,8 +726,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(ID); - } else if (Def && Def->Data) { - ID->Data = Def->Data; + } else { + ID->Data = ID->getCanonicalDecl()->Data; } } @@ -746,6 +750,10 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { // Read the definition. PD->allocateDefinitionData(); + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + PD->getCanonicalDecl()->Data = PD->Data; + unsigned NumProtoRefs = Record[Idx++]; SmallVector ProtoRefs; ProtoRefs.reserve(NumProtoRefs); @@ -760,8 +768,8 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(PD); - } else if (Def && Def->Data) { - PD->Data = Def->Data; + } else { + PD->Data = PD->getCanonicalDecl()->Data; } } @@ -1104,12 +1112,21 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D, if (D == DefinitionDecl) { D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); + + // Propagate the DefinitionData pointer to the canonical declaration, so + // that all other deserialized declarations will see it. + // FIXME: Complain if there already is a DefinitionData! + D->getCanonicalDecl()->DefinitionData = D->DefinitionData; + ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); - // Note that we have deserialized a definition. + // Note that we have deserialized a definition. Any declarations + // deserialized before this one will be be given the DefinitionData pointer + // at the end. Reader.PendingDefinitions.insert(D); - } else if (DefinitionDecl && DefinitionDecl->DefinitionData) { - D->DefinitionData = DefinitionDecl->DefinitionData; + } else { + // Propagate DefinitionData pointer from the canonical declaration. + D->DefinitionData = D->getCanonicalDecl()->DefinitionData; } } @@ -1514,8 +1531,6 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable *D, static_cast(static_cast(ExistingCanon))); } - // FIXME: Update common pointer for RedeclarableTemplateDecls? - // Don't introduce DCanon into the set of pending declaration chains. Redecl.suppress(); @@ -2372,15 +2387,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, unsigned Idx = 0; while (Idx < Record.size()) { switch ((DeclUpdateKind)Record[Idx++]) { - case UPD_CXX_SET_DEFINITIONDATA: { - CXXRecordDecl *RD = cast(D); - CXXRecordDecl *DefinitionDecl - = Reader.ReadDeclAs(ModuleFile, Record, Idx); - assert(!RD->DefinitionData && "DefinitionData is already set!"); - InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx); - break; - } - case UPD_CXX_ADDED_IMPLICIT_MEMBER: cast(D)->addedMember(Reader.ReadDecl(ModuleFile, Record, Idx)); break; @@ -2410,24 +2416,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, cast(D)->getMemberSpecializationInfo()->setPointOfInstantiation( Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; - - case UPD_OBJC_SET_CLASS_DEFINITIONDATA: { - ObjCInterfaceDecl *ID = cast(D); - ObjCInterfaceDecl *Def - = Reader.ReadDeclAs(ModuleFile, Record, Idx); - if (Def->Data) - ID->Data = Def->Data; - break; - } - - case UPD_OBJC_SET_PROTOCOL_DEFINITIONDATA: { - ObjCProtocolDecl *ID = cast(D); - ObjCProtocolDecl *Def - = Reader.ReadDeclAs(ModuleFile, Record, Idx); - if (Def->Data) - ID->Data = Def->Data; - break; - } } } } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index d49e7110c39..20420d6ddcc 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3519,12 +3519,9 @@ void ASTWriter::ResolveDeclUpdatesBlocks() { unsigned Idx = 0, N = URec.size(); while (Idx < N) { switch ((DeclUpdateKind)URec[Idx++]) { - case UPD_CXX_SET_DEFINITIONDATA: case UPD_CXX_ADDED_IMPLICIT_MEMBER: 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(URec[Idx])); ++Idx; break; @@ -4365,22 +4362,6 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { // have created a new definition decl instead ? RewriteDecl(RD); } - - for (CXXRecordDecl::redecl_iterator - I = RD->redecls_begin(), E = RD->redecls_end(); I != E; ++I) { - CXXRecordDecl *Redecl = cast(*I); - if (Redecl == RD) - continue; - - // We are interested when a PCH decl is modified. - if (Redecl->isFromASTFile()) { - UpdateRecord &Record = DeclUpdates[Redecl]; - Record.push_back(UPD_CXX_SET_DEFINITIONDATA); - assert(Redecl->DefinitionData); - assert(Redecl->DefinitionData->Definition == D); - Record.push_back(reinterpret_cast(D)); // the DefinitionDecl - } - } } } void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { @@ -4474,45 +4455,6 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, LocalChainedObjCCategories.push_back(Data); } -void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) { - assert(!WritingAST && "Already writing the AST!"); - - if (const ObjCInterfaceDecl *ID = dyn_cast(D)) { - for (ObjCInterfaceDecl::redecl_iterator I = ID->redecls_begin(), - E = ID->redecls_end(); - I != E; ++I) { - if (*I == ID) - continue; - - // We are interested when a PCH decl is modified. - if (I->isFromASTFile()) { - UpdateRecord &Record = DeclUpdates[*I]; - Record.push_back(UPD_OBJC_SET_CLASS_DEFINITIONDATA); - assert((*I)->hasDefinition()); - assert((*I)->getDefinition() == D); - Record.push_back(reinterpret_cast(D)); // the DefinitionDecl - } - } - } - - if (const ObjCProtocolDecl *PD = dyn_cast(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(D)); // the DefinitionDecl - } - } - } -} void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, const ObjCPropertyDecl *OrigProp, -- cgit v1.2.3