aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Serialization/ASTReader.h7
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp18
-rw-r--r--test/Modules/Inputs/module.map4
-rw-r--r--test/Modules/Inputs/redecl-merge-bottom.h3
-rw-r--r--test/Modules/Inputs/redecl-merge-left-left.h5
-rw-r--r--test/Modules/Inputs/redecl-merge-right.h6
-rw-r--r--test/Modules/redecl-merge.m8
7 files changed, 49 insertions, 2 deletions
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<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;
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