diff options
author | Manman Ren <manman.ren@gmail.com> | 2016-09-09 23:48:27 +0000 |
---|---|---|
committer | Manman Ren <manman.ren@gmail.com> | 2016-09-09 23:48:27 +0000 |
commit | ec315f10021cc9ca48b375fe86cd08a74d5e71d5 (patch) | |
tree | 71614795337b1c76a426f59e9c0eb7bfdd061175 /clang/lib/Serialization/ASTReaderDecl.cpp | |
parent | a3ad6dcfaf1ba5af42f19700c329dd27e3a62c40 (diff) | |
download | bcm5719-llvm-ec315f10021cc9ca48b375fe86cd08a74d5e71d5.tar.gz bcm5719-llvm-ec315f10021cc9ca48b375fe86cd08a74d5e71d5.zip |
Modules: for ObjectiveC try to keep the definition invariant.
When deserializing ObjCInterfaceDecl with definition data, if we already have
a definition, try to keep the definition invariant; also pull in the
categories even if it is not what getDefinition returns (this effectively
combines categories).
rdar://27926200
rdar://26708823
llvm-svn: 281119
Diffstat (limited to 'clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 95 |
1 files changed, 59 insertions, 36 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 3cc54048188..70c7b7808c4 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -133,6 +133,10 @@ namespace clang { const RecordData &R, unsigned &I); void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&NewDD); + void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data, + const RecordData &R, unsigned &I); + void MergeDefinitionData(ObjCInterfaceDecl *D, + struct ObjCInterfaceDecl::DefinitionData &&NewDD); static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, @@ -981,6 +985,43 @@ ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() { typeParams, rAngleLoc); } +void ASTDeclReader::ReadObjCDefinitionData( + struct ObjCInterfaceDecl::DefinitionData &Data, + const RecordData &R, unsigned &I) { + // Read the superclass. + Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx); + + Data.EndLoc = ReadSourceLocation(Record, Idx); + Data.HasDesignatedInitializers = Record[Idx++]; + + // Read the directly referenced protocols and their SourceLocations. + unsigned NumProtocols = Record[Idx++]; + SmallVector<ObjCProtocolDecl *, 16> Protocols; + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; + ProtoLocs.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); + Data.ReferencedProtocols.set(Protocols.data(), NumProtocols, ProtoLocs.data(), + Reader.getContext()); + + // Read the transitive closure of protocols referenced by this class. + NumProtocols = Record[Idx++]; + Protocols.clear(); + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + Data.AllReferencedProtocols.set(Protocols.data(), NumProtocols, + Reader.getContext()); +} + +void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, + struct ObjCInterfaceDecl::DefinitionData &&NewDD) { + // FIXME: odr checking? +} + void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); @@ -991,43 +1032,22 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { if (Record[Idx++]) { // 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. - Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx); - Data.EndLoc = ReadSourceLocation(Record, Idx); - Data.HasDesignatedInitializers = Record[Idx++]; + ReadObjCDefinitionData(ID->data(), Record, Idx); + ObjCInterfaceDecl *Canon = ID->getCanonicalDecl(); + if (Canon->Data.getPointer()) { + // If we already have a definition, keep the definition invariant and + // merge the data. + MergeDefinitionData(Canon, std::move(ID->data())); + ID->Data = Canon->Data; + } else { + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + ID->getCanonicalDecl()->Data = ID->Data; - // Read the directly referenced protocols and their SourceLocations. - unsigned NumProtocols = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - Reader.getContext()); - - // Read the transitive closure of protocols referenced by this class. - NumProtocols = Record[Idx++]; - Protocols.clear(); - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols, - Reader.getContext()); - - // We will rebuild this list lazily. - ID->setIvarList(nullptr); + // We will rebuild this list lazily. + ID->setIvarList(nullptr); + } // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(ID); @@ -3502,7 +3522,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // Load the categories after recursive loading is finished. if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) - if (Class->isThisDeclarationADefinition()) + // If we already have a definition when deserializing the ObjCInterfaceDecl, + // we put the Decl in PendingDefinitions so we can pull the categories here. + if (Class->isThisDeclarationADefinition() || + PendingDefinitions.count(Class)) loadObjCCategories(ID, Class); // If we have deserialized a declaration that has a definition the |