From: Douglas Gregor Date: Thu, 22 Dec 2011 19:44:59 +0000 (+0000) Subject: If we end up merging an Objective-C class with an existing Objective-C X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cce54aa6a40e4c39b25532336e17ce40f0a7e087;p=clang If we end up merging an Objective-C class with an existing Objective-C class that comes from a different module file, make sure that we load all of the pending declarations for the original declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147168 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 9d661c8c19..166ac66821 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -675,6 +675,13 @@ private: /// \brief Keeps track of the elements added to PendingDeclChains. llvm::SmallSet PendingDeclChainsKnown; + /// \brief Reverse mapping from declarations to their global declaration IDs. + /// + /// FIXME: This data structure is currently only used for ObjCInterfaceDecls, + /// support declaration merging. If we must have this for other declarations, + /// allocate it along with the Decl itself. + llvm::DenseMap DeclToID; + typedef llvm::DenseMap > MergedDeclsMap; diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 93ba34bec6..2c8e6ea466 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -643,10 +643,13 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { } void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { + // Record the declaration -> global ID mapping. + Reader.DeclToID[ID] = ThisDeclID; + RedeclarableResult Redecl = VisitRedeclarable(ID); VisitObjCContainerDecl(ID); TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]); - + // Determine whether we need to merge this declaration with another @interface // with the same name. // FIXME: Not needed unless the module file graph is a DAG. @@ -660,6 +663,18 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { // appropriate canonical declaration. ID->RedeclLink = ObjCInterfaceDecl::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. if (IDCanon == ID) @@ -2192,7 +2207,6 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { if (Chains.empty()) return; - // Capture all of the parsed declarations and put them at the end. Decl *MostRecent = getMostRecentDecl(CanonDecl); Decl *FirstParsed = MostRecent; diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 13a44eb6a7..640aa3c1f6 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -51,6 +51,10 @@ module redecl_merge_left { header "redecl-merge-left.h" export * } +module redecl_merge_left_left { + header "redecl-merge-left-left.h" + export * +} module redecl_merge_right { header "redecl-merge-right.h" export * diff --git a/test/Modules/Inputs/redecl-merge-bottom.h b/test/Modules/Inputs/redecl-merge-bottom.h index 1c59c1f223..ce4368d08a 100644 --- a/test/Modules/Inputs/redecl-merge-bottom.h +++ b/test/Modules/Inputs/redecl-merge-bottom.h @@ -1,4 +1,7 @@ __import_module__ redecl_merge_left; + +@class C4; +@class C4; __import_module__ redecl_merge_right; @class B; diff --git a/test/Modules/Inputs/redecl-merge-left-left.h b/test/Modules/Inputs/redecl-merge-left-left.h new file mode 100644 index 0000000000..0d7fd6a514 --- /dev/null +++ b/test/Modules/Inputs/redecl-merge-left-left.h @@ -0,0 +1,5 @@ +__import_module__ redecl_merge_left; + +@class C4; +void accept_a_C4(C4*); + diff --git a/test/Modules/Inputs/redecl-merge-right.h b/test/Modules/Inputs/redecl-merge-right.h index f5e4eb8ee4..f86f1103ee 100644 --- a/test/Modules/Inputs/redecl-merge-right.h +++ b/test/Modules/Inputs/redecl-merge-right.h @@ -18,6 +18,12 @@ C2 *get_a_C2(void); @class C3; C3 *get_a_C3(void); +@class C4; +@class C4; +@class C4; +@class C4; +C4 *get_a_C4(void); + @class Explicit; int *explicit_func(void); diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m index 7b06adcce4..930e8df6b8 100644 --- a/test/Modules/redecl-merge.m +++ b/test/Modules/redecl-merge.m @@ -55,6 +55,14 @@ void test_C3(C3 *c3) { accept_a_C3(c3); } +C4 *global_C4; +__import_module__ redecl_merge_left_left; + +void test_C4(C4 *c4) { + global_C4 = c4 = get_a_C4(); + accept_a_C4(c4); +} + __import_module__ redecl_merge_bottom; @implementation B