]> granicus.if.org Git - clang/commitdiff
If we end up merging an Objective-C class with an existing Objective-C
authorDouglas Gregor <dgregor@apple.com>
Thu, 22 Dec 2011 19:44:59 +0000 (19:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 22 Dec 2011 19:44:59 +0000 (19:44 +0000)
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

include/clang/Serialization/ASTReader.h
lib/Serialization/ASTReaderDecl.cpp
test/Modules/Inputs/module.map
test/Modules/Inputs/redecl-merge-bottom.h
test/Modules/Inputs/redecl-merge-left-left.h [new file with mode: 0644]
test/Modules/Inputs/redecl-merge-right.h
test/Modules/redecl-merge.m

index 9d661c8c194ea1602d26d96f2f747db123679e7e..166ac668210463d7e074b81c116e5672b92b8d6b 100644 (file)
@@ -675,6 +675,13 @@ private:
   /// \brief Keeps track of the elements added to PendingDeclChains.
   llvm::SmallSet<serialization::DeclID, 16> 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<Decl *, serialization::GlobalDeclID> DeclToID;
+  
   typedef llvm::DenseMap<Decl *, llvm::SmallVector<serialization::DeclID, 2> >
     MergedDeclsMap;
     
index 93ba34bec6a957470656c767ba18c8c6ae91e0e0..2c8e6ea46634fc8db5f4e08c7e835525f2186f52 100644 (file)
@@ -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;
index 13a44eb6a76df7ed4b8b37d1e7accc90bacd9b72..640aa3c1f6381d3eea98e5e2bb02e3d1ca130f38 100644 (file)
@@ -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 *
index 1c59c1f22342d09a3dc7c12123571b10af09272a..ce4368d08a01d76965973c890a6ef09a823bc814 100644 (file)
@@ -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 (file)
index 0000000..0d7fd6a
--- /dev/null
@@ -0,0 +1,5 @@
+__import_module__ redecl_merge_left;
+
+@class C4;
+void accept_a_C4(C4*);
+
index f5e4eb8ee4457e9a1526a5b3e960baed73a8f1ae..f86f1103eeaf10fec46db8c4301ceedfb4aebf31 100644 (file)
@@ -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);
index 7b06adcce43cf5a970971cdfd2843eba9bb9a5c2..930e8df6b87fe13078a413b159293c775d4fb8df 100644 (file)
@@ -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