aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Serialization/ASTBitCodes.h5
-rw-r--r--include/clang/Serialization/ASTReader.h20
-rw-r--r--include/clang/Serialization/ASTWriter.h3
-rw-r--r--lib/Serialization/ASTReader.cpp10
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp38
-rw-r--r--lib/Serialization/ASTWriter.cpp22
-rw-r--r--test/Modules/Inputs/redecl-merge-bottom.h2
-rw-r--r--test/Modules/Inputs/redecl-merge-left.h2
-rw-r--r--test/Modules/redecl-merge.m7
9 files changed, 100 insertions, 9 deletions
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index a4b6b8f45e..073ad80d74 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -452,7 +452,10 @@ namespace clang {
/// \brief Record code for an array of all of the (sub)modules that were
/// imported by the AST file.
- IMPORTED_MODULES = 51
+ IMPORTED_MODULES = 51,
+
+ /// \brief Record code for the set of merged declarations in an AST file.
+ MERGED_DECLARATIONS = 52
};
/// \brief Record types used within a source manager block.
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 166ac66821..1595a0ef61 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -690,6 +690,26 @@ private:
/// that canonical declaration.
MergedDeclsMap MergedDecls;
+ typedef llvm::DenseMap<serialization::GlobalDeclID,
+ llvm::SmallVector<serialization::DeclID, 2> >
+ StoredMergedDeclsMap;
+
+ /// \brief A mapping from canonical declaration IDs to the set of additional
+ /// declaration IDs that have been merged with that canonical declaration.
+ ///
+ /// This is the deserialized representation of the entries in MergedDecls.
+ /// When we query entries in MergedDecls, they will be augmented with entries
+ /// from StoredMergedDecls.
+ StoredMergedDeclsMap StoredMergedDecls;
+
+ /// \brief Combine the stored merged declarations for the given canonical
+ /// declaration into the set of merged declarations.
+ ///
+ /// \returns An iterator into MergedDecls that corresponds to the position of
+ /// the given canonical declaration.
+ MergedDeclsMap::iterator
+ combineStoredMergedDecls(Decl *Canon, serialization::GlobalDeclID CanonID);
+
/// \brief We delay loading the chain of objc categories after recursive
/// loading of declarations is finished.
std::vector<std::pair<ObjCInterfaceDecl *, serialization::DeclID> >
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 8791d83d93..ef2f1ada6f 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -415,7 +415,8 @@ private:
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptions &Opts);
void WriteOpenCLExtensions(Sema &SemaRef);
-
+ void WriteMergedDecls();
+
unsigned DeclParmVarAbbrev;
unsigned DeclContextLexicalAbbrev;
unsigned DeclContextVisibleLookupAbbrev;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 2ac1908ee2..440474b587 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2407,6 +2407,16 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
F.RedeclarationsInfo = (const LocalRedeclarationsInfo *)BlobStart;
break;
}
+
+ case MERGED_DECLARATIONS: {
+ for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
+ GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
+ SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
+ for (unsigned N = Record[Idx++]; N > 0; --N)
+ Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
+ }
+ break;
+ }
}
}
Error("premature end of bitstream in AST file");
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 2c8e6ea466..cb816632bd 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -676,9 +676,14 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
}
// If this declaration was the canonical declaration, make a note of
- // that.
- if (IDCanon == ID)
- Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID());
+ // that. We accept the linear algorithm here because the number of
+ // unique canonical declarations of an entity should always be tiny.
+ if (IDCanon == ID) {
+ SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
+ if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
+ == Merged.end())
+ Merged.push_back(Redecl.getFirstID());
+ }
}
}
}
@@ -1725,6 +1730,29 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
}
}
+ASTReader::MergedDeclsMap::iterator
+ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) {
+ // If we don't have any stored merged declarations, just look in the
+ // merged declarations set.
+ StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID);
+ if (StoredPos == StoredMergedDecls.end())
+ return MergedDecls.find(Canon);
+
+ // Append the stored merged declarations to the merged declarations set.
+ MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
+ if (Pos == MergedDecls.end())
+ Pos = MergedDecls.insert(std::make_pair(Canon,
+ SmallVector<DeclID, 2>())).first;
+ Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
+ StoredMergedDecls.erase(StoredPos);
+
+ // Sort and uniquify the set of merged declarations.
+ llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
+ Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
+ Pos->second.end());
+ return Pos;
+}
+
void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) {
Decl *previous = GetDecl(ID);
ASTDeclReader::attachPreviousDecl(D, previous);
@@ -2186,7 +2214,7 @@ static Decl *getMostRecentDecl(Decl *D) {
void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
Decl *D = GetDecl(ID);
Decl *CanonDecl = D->getCanonicalDecl();
-
+
// Determine the set of declaration IDs we'll be searching for.
llvm::SmallVector<DeclID, 1> SearchDecls;
GlobalDeclID CanonID = 0;
@@ -2194,7 +2222,7 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
SearchDecls.push_back(ID); // Always first.
CanonID = ID;
}
- MergedDeclsMap::iterator MergedPos = MergedDecls.find(CanonDecl);
+ MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID);
if (MergedPos != MergedDecls.end())
SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 97c31b07a3..feeb27f338 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -2903,6 +2903,25 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
+void ASTWriter::WriteMergedDecls() {
+ if (!Chain || Chain->MergedDecls.empty())
+ return;
+
+ RecordData Record;
+ for (ASTReader::MergedDeclsMap::iterator I = Chain->MergedDecls.begin(),
+ IEnd = Chain->MergedDecls.end();
+ I != IEnd; ++I) {
+ DeclID CanonID = I->first->isFromASTFile()? Chain->DeclToID[I->first]
+ : getDeclID(I->first);
+ assert(CanonID && "Merged declaration not known?");
+
+ Record.push_back(CanonID);
+ Record.push_back(I->second.size());
+ Record.append(I->second.begin(), I->second.end());
+ }
+ Stream.EmitRecord(MERGED_DECLARATIONS, Record);
+}
+
//===----------------------------------------------------------------------===//
// General Serialization Routines
//===----------------------------------------------------------------------===//
@@ -3401,7 +3420,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteDeclUpdatesBlocks();
WriteDeclReplacementsBlock();
WriteChainedObjCCategories();
-
+ WriteMergedDecls();
+
if (!LocalRedeclarations.empty()) {
// Sort the local redeclarations info by the first declaration ID,
// since the reader will be perforing binary searches on this information.
diff --git a/test/Modules/Inputs/redecl-merge-bottom.h b/test/Modules/Inputs/redecl-merge-bottom.h
index ce4368d08a..50c191c8b6 100644
--- a/test/Modules/Inputs/redecl-merge-bottom.h
+++ b/test/Modules/Inputs/redecl-merge-bottom.h
@@ -8,6 +8,8 @@ __import_module__ redecl_merge_right;
@class A;
+void refers_to_C4(C4*);
+
#ifdef __cplusplus
template<typename T> class Vector;
diff --git a/test/Modules/Inputs/redecl-merge-left.h b/test/Modules/Inputs/redecl-merge-left.h
index 7f355e8f9d..c4789ad0c0 100644
--- a/test/Modules/Inputs/redecl-merge-left.h
+++ b/test/Modules/Inputs/redecl-merge-left.h
@@ -22,6 +22,8 @@ void accept_a_C2(C2*);
void accept_a_C3(C3*);
@class C3;
+@class C4;
+
@class Explicit;
int *explicit_func(void);
diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m
index 930e8df6b8..ea04037707 100644
--- a/test/Modules/redecl-merge.m
+++ b/test/Modules/redecl-merge.m
@@ -58,13 +58,18 @@ void test_C3(C3 *c3) {
C4 *global_C4;
__import_module__ redecl_merge_left_left;
-void test_C4(C4 *c4) {
+void test_C4a(C4 *c4) {
global_C4 = c4 = get_a_C4();
accept_a_C4(c4);
}
__import_module__ redecl_merge_bottom;
+void test_C4b() {
+ if (&refers_to_C4) {
+ }
+}
+
@implementation B
+ (B*)create_a_B { return 0; }
@end