diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-01-01 21:47:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-01-01 21:47:52 +0000 |
commit | dba9361891ab147b6ea658c1834bc1d660f5226b (patch) | |
tree | 5cad032d8abe46d14a32ecbad689e59d4bc292f3 /lib | |
parent | 49310ba7dca1df625f89baaa7c70bc4d6a36e80e (diff) |
Implement declaration merging for Objective-C protocols across
multiple, disjoint modules. There is far too much duplicating with the
ObjCInterfaceDecl case here, which I'll eliminate shortly.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147417 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 1df67f22ab..12436c5c4f 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -759,12 +759,54 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { - VisitRedeclarable(PD); + // Record the declaration -> global ID mapping. + Reader.DeclToID[PD] = ThisDeclID; + + RedeclarableResult Redecl = VisitRedeclarable(PD); VisitObjCContainerDecl(PD); PD->InitiallyForwardDecl = Record[Idx++]; PD->isForwardProtoDecl = Record[Idx++]; PD->setLocEnd(ReadSourceLocation(Record, Idx)); + // Determine whether we need to merge this declaration with another @protocol + // with the same name. + // FIXME: Not needed unless the module file graph is a DAG. + if (FindExistingResult ExistingRes = findExisting(PD)) { + if (ObjCProtocolDecl *Existing = ExistingRes) { + ObjCProtocolDecl *ExistingCanon = Existing->getCanonicalDecl(); + ObjCProtocolDecl *PDCanon = PD->getCanonicalDecl(); + if (ExistingCanon != PDCanon) { + // Have our redeclaration link point back at the canonical declaration + // of the existing declaration, so that this declaration has the + // appropriate canonical declaration. + PD->RedeclLink = ObjCProtocolDecl::PreviousDeclLink(ExistingCanon); + + // Don't introduce IDCanon into the set of pending declaration chains. + Redecl.suppress(); + + // Introduce ExistingCanon into the set of pending declaration chains, + // if in fact it came from a module file. + if (ExistingCanon->isFromASTFile()) { + GlobalDeclID ExistingCanonID = Reader.DeclToID[ExistingCanon]; + assert(ExistingCanonID && "Unrecorded canonical declaration ID?"); + if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID)) + Reader.PendingDeclChains.push_back(ExistingCanonID); + } + + // If this declaration was the canonical declaration, make a note of + // that. We accept the linear algorithm here because the number of + // unique canonical declarations of an entity should always be tiny. + if (PDCanon == PD) { + SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; + if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) + == Merged.end()) + Merged.push_back(Redecl.getFirstID()); + } + } + } + } + + ObjCProtocolDecl *Def = ReadDeclAs<ObjCProtocolDecl>(Record, Idx); if (PD == Def) { // Read the definition. @@ -1645,8 +1687,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { Y->getDeclContext()->getRedeclContext())) return false; - // Objective-C classes with the same name always match. - if (isa<ObjCInterfaceDecl>(X)) + // Objective-C classes and protocols with the same name always match. + if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) return true; // FIXME: Many other cases to implement. |