summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclObjC.h1
-rw-r--r--clang/include/clang/Serialization/ASTReader.h5
-rw-r--r--clang/lib/Serialization/ASTReader.cpp23
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp38
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp8
-rw-r--r--clang/test/Modules/redecl-merge.m4
6 files changed, 61 insertions, 18 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 7a5a715eab6..6a0b6acc87d 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -928,6 +928,7 @@ public:
static bool classof(const ObjCInterfaceDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCInterface; }
+ friend class ASTReader;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 10ed5dceea5..507b75f33ce 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -338,7 +338,10 @@ private:
/// the DefinitionData pointer of all pending references.
PendingForwardRefsMap PendingForwardRefs;
-
+ /// \brief The set of C++ or Objective-C classes that have forward
+ /// declarations that have not yet been linked to their definitions.
+ llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
+
typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
FirstLatestDeclIDMap;
/// \brief Map of first declarations from a chained PCH that point to the
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index fc49e88a50a..2b417522bcc 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6095,6 +6095,29 @@ void ASTReader::finishPendingActions() {
}
PendingChainedObjCCategories.clear();
}
+
+ // If we deserialized any C++ or Objective-C class definitions, make sure
+ // that all redeclarations point to the definitions. Note that this can only
+ // happen now, after the redeclaration chains have been fully wired.
+ for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
+ DEnd = PendingDefinitions.end();
+ D != DEnd; ++D) {
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
+ for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
+ REnd = RD->redecls_end();
+ R != REnd; ++R)
+ cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+
+ continue;
+ }
+
+ ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(*D);
+ for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
+ REnd = ID->redecls_end();
+ R != REnd; ++R)
+ R->Data = ID->Data;
+ }
+ PendingDefinitions.clear();
}
void ASTReader::FinishedDeserializing() {
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 35cd8478d5b..bd6a5a5e06d 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -630,6 +630,9 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
// pending references were linked.
Reader.PendingForwardRefs.erase(ID);
#endif
+
+ // Note that we have deserialized a definition.
+ Reader.PendingDefinitions.insert(ID);
}
} else if (Def) {
if (Def->Data) {
@@ -1030,6 +1033,9 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D,
Reader.PendingForwardRefs.erase(D);
#endif
}
+
+ // Note that we have deserialized a definition.
+ Reader.PendingDefinitions.insert(D);
} else if (DefinitionDecl) {
if (DefinitionDecl->DefinitionData) {
D->DefinitionData = DefinitionDecl->DefinitionData;
@@ -1162,7 +1168,7 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
// can be used while this is still initializing.
- enum RedeclKind { FirstDeclaration, PointsToPrevious };
+ enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
// Determine the first declaration ID.
@@ -1190,7 +1196,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
}
break;
}
-
+
+ case FirstInFile:
case PointsToPrevious: {
FirstDeclID = ReadDeclID(Record, Idx);
DeclID PrevDeclID = ReadDeclID(Record, Idx);
@@ -1204,9 +1211,13 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// loaded and attached later on.
D->CommonOrPrev = FirstDecl;
- // Make a note that we need to wire up this declaration to its
- // previous declaration, later.
- Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
+ if (Kind == PointsToPrevious) {
+ // Make a note that we need to wire up this declaration to its
+ // previous declaration, later. We don't need to do this for the first
+ // declaration in any given module file, because those will be wired
+ // together later.
+ Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
+ }
break;
}
}
@@ -1412,7 +1423,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
template <typename T>
void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
- enum RedeclKind { FirstDeclaration = 0, PointsToPrevious };
+ enum RedeclKind { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
DeclID FirstDeclID;
@@ -1420,7 +1431,8 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
case FirstDeclaration:
FirstDeclID = ThisDeclID;
break;
-
+
+ case FirstInFile:
case PointsToPrevious: {
FirstDeclID = ReadDeclID(Record, Idx);
DeclID PrevDeclID = ReadDeclID(Record, Idx);
@@ -1433,10 +1445,14 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// loaded & attached later on.
D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
- // Make a note that we need to wire up this declaration to its
- // previous declaration, later.
- Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
- PrevDeclID));
+ if (Kind == PointsToPrevious) {
+ // Make a note that we need to wire up this declaration to its
+ // previous declaration, later. We don't need to do this for the first
+ // declaration in any given module file, because those will be wired
+ // together later.
+ Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
+ PrevDeclID));
+ }
break;
}
}
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index cb1c6f0476e..7ae601810b9 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1051,7 +1051,7 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing.
- enum { FirstDeclaration, PointsToPrevious };
+ enum { FirstDeclaration, FirstInFile, PointsToPrevious };
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
RedeclarableTemplateDecl *First = 0;
if (!Prev) {
@@ -1063,7 +1063,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
Record.push_back(D->isMemberSpecialization());
} else {
First = D->getFirstDeclaration();
- Record.push_back(PointsToPrevious);
+ Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
Writer.AddDeclRef(First, Record);
Writer.AddDeclRef(Prev, Record);
}
@@ -1276,14 +1276,14 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
- enum { FirstDeclaration = 0, PointsToPrevious };
+ enum { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
T *Prev = D->getPreviousDeclaration();
T *First = D->getFirstDeclaration();
if (!Prev) {
Record.push_back(FirstDeclaration);
} else {
- Record.push_back(PointsToPrevious);
+ Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
Writer.AddDeclRef(First, Record);
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
}
diff --git a/clang/test/Modules/redecl-merge.m b/clang/test/Modules/redecl-merge.m
index c5da754dfe0..6497268c384 100644
--- a/clang/test/Modules/redecl-merge.m
+++ b/clang/test/Modules/redecl-merge.m
@@ -32,7 +32,7 @@ void g(A *a) {
#ifdef __cplusplus
void testVector() {
- Vector<int> *vec_int;
- // FIXME: vec_int.push_back(0);
+ Vector<int> vec_int;
+ vec_int.push_back(0);
}
#endif
OpenPOWER on IntegriCloud