forked from OSchip/llvm-project
Once we have fully deserialized a redeclaration chain for something
with a definition pointer (e.g., C++ and Objective-C classes), zip through the redeclaration chain to make sure that all of the declarations point to the definition data. As part of this, realized again why the first redeclaration of an entity in a file is important, and brought back that idea. llvm-svn: 146886
This commit is contained in:
parent
9ae4fc035b
commit
e80b31f7f9
|
@ -928,6 +928,7 @@ public:
|
||||||
static bool classof(const ObjCInterfaceDecl *D) { return true; }
|
static bool classof(const ObjCInterfaceDecl *D) { return true; }
|
||||||
static bool classofKind(Kind K) { return K == ObjCInterface; }
|
static bool classofKind(Kind K) { return K == ObjCInterface; }
|
||||||
|
|
||||||
|
friend class ASTReader;
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
friend class ASTDeclWriter;
|
friend class ASTDeclWriter;
|
||||||
};
|
};
|
||||||
|
|
|
@ -338,7 +338,10 @@ private:
|
||||||
/// the DefinitionData pointer of all pending references.
|
/// the DefinitionData pointer of all pending references.
|
||||||
PendingForwardRefsMap PendingForwardRefs;
|
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>
|
typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
|
||||||
FirstLatestDeclIDMap;
|
FirstLatestDeclIDMap;
|
||||||
/// \brief Map of first declarations from a chained PCH that point to the
|
/// \brief Map of first declarations from a chained PCH that point to the
|
||||||
|
|
|
@ -6095,6 +6095,29 @@ void ASTReader::finishPendingActions() {
|
||||||
}
|
}
|
||||||
PendingChainedObjCCategories.clear();
|
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() {
|
void ASTReader::FinishedDeserializing() {
|
||||||
|
|
|
@ -630,6 +630,9 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
||||||
// pending references were linked.
|
// pending references were linked.
|
||||||
Reader.PendingForwardRefs.erase(ID);
|
Reader.PendingForwardRefs.erase(ID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Note that we have deserialized a definition.
|
||||||
|
Reader.PendingDefinitions.insert(ID);
|
||||||
}
|
}
|
||||||
} else if (Def) {
|
} else if (Def) {
|
||||||
if (Def->Data) {
|
if (Def->Data) {
|
||||||
|
@ -1030,6 +1033,9 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D,
|
||||||
Reader.PendingForwardRefs.erase(D);
|
Reader.PendingForwardRefs.erase(D);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that we have deserialized a definition.
|
||||||
|
Reader.PendingDefinitions.insert(D);
|
||||||
} else if (DefinitionDecl) {
|
} else if (DefinitionDecl) {
|
||||||
if (DefinitionDecl->DefinitionData) {
|
if (DefinitionDecl->DefinitionData) {
|
||||||
D->DefinitionData = DefinitionDecl->DefinitionData;
|
D->DefinitionData = DefinitionDecl->DefinitionData;
|
||||||
|
@ -1162,7 +1168,7 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
||||||
void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
|
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
|
||||||
// can be used while this is still initializing.
|
// can be used while this is still initializing.
|
||||||
enum RedeclKind { FirstDeclaration, PointsToPrevious };
|
enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
|
||||||
RedeclKind Kind = (RedeclKind)Record[Idx++];
|
RedeclKind Kind = (RedeclKind)Record[Idx++];
|
||||||
|
|
||||||
// Determine the first declaration ID.
|
// Determine the first declaration ID.
|
||||||
|
@ -1190,7 +1196,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case FirstInFile:
|
||||||
case PointsToPrevious: {
|
case PointsToPrevious: {
|
||||||
FirstDeclID = ReadDeclID(Record, Idx);
|
FirstDeclID = ReadDeclID(Record, Idx);
|
||||||
DeclID PrevDeclID = ReadDeclID(Record, Idx);
|
DeclID PrevDeclID = ReadDeclID(Record, Idx);
|
||||||
|
@ -1204,9 +1211,13 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
// loaded and attached later on.
|
// loaded and attached later on.
|
||||||
D->CommonOrPrev = FirstDecl;
|
D->CommonOrPrev = FirstDecl;
|
||||||
|
|
||||||
// Make a note that we need to wire up this declaration to its
|
if (Kind == PointsToPrevious) {
|
||||||
// previous declaration, later.
|
// Make a note that we need to wire up this declaration to its
|
||||||
Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1412,7 +1423,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
||||||
enum RedeclKind { FirstDeclaration = 0, PointsToPrevious };
|
enum RedeclKind { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
|
||||||
RedeclKind Kind = (RedeclKind)Record[Idx++];
|
RedeclKind Kind = (RedeclKind)Record[Idx++];
|
||||||
|
|
||||||
DeclID FirstDeclID;
|
DeclID FirstDeclID;
|
||||||
|
@ -1420,7 +1431,8 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
||||||
case FirstDeclaration:
|
case FirstDeclaration:
|
||||||
FirstDeclID = ThisDeclID;
|
FirstDeclID = ThisDeclID;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FirstInFile:
|
||||||
case PointsToPrevious: {
|
case PointsToPrevious: {
|
||||||
FirstDeclID = ReadDeclID(Record, Idx);
|
FirstDeclID = ReadDeclID(Record, Idx);
|
||||||
DeclID PrevDeclID = ReadDeclID(Record, Idx);
|
DeclID PrevDeclID = ReadDeclID(Record, Idx);
|
||||||
|
@ -1433,10 +1445,14 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
||||||
// loaded & attached later on.
|
// loaded & attached later on.
|
||||||
D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
|
D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
|
||||||
|
|
||||||
// Make a note that we need to wire up this declaration to its
|
if (Kind == PointsToPrevious) {
|
||||||
// previous declaration, later.
|
// Make a note that we need to wire up this declaration to its
|
||||||
Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
|
// previous declaration, later. We don't need to do this for the first
|
||||||
PrevDeclID));
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1051,7 +1051,7 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
|
||||||
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
|
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
|
||||||
// getCommonPtr() can be used while this is still initializing.
|
// getCommonPtr() can be used while this is still initializing.
|
||||||
enum { FirstDeclaration, PointsToPrevious };
|
enum { FirstDeclaration, FirstInFile, PointsToPrevious };
|
||||||
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
|
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
|
||||||
RedeclarableTemplateDecl *First = 0;
|
RedeclarableTemplateDecl *First = 0;
|
||||||
if (!Prev) {
|
if (!Prev) {
|
||||||
|
@ -1063,7 +1063,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
Record.push_back(D->isMemberSpecialization());
|
Record.push_back(D->isMemberSpecialization());
|
||||||
} else {
|
} else {
|
||||||
First = D->getFirstDeclaration();
|
First = D->getFirstDeclaration();
|
||||||
Record.push_back(PointsToPrevious);
|
Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
|
||||||
Writer.AddDeclRef(First, Record);
|
Writer.AddDeclRef(First, Record);
|
||||||
Writer.AddDeclRef(Prev, Record);
|
Writer.AddDeclRef(Prev, Record);
|
||||||
}
|
}
|
||||||
|
@ -1276,14 +1276,14 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
|
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
|
||||||
enum { FirstDeclaration = 0, PointsToPrevious };
|
enum { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
|
||||||
T *Prev = D->getPreviousDeclaration();
|
T *Prev = D->getPreviousDeclaration();
|
||||||
T *First = D->getFirstDeclaration();
|
T *First = D->getFirstDeclaration();
|
||||||
|
|
||||||
if (!Prev) {
|
if (!Prev) {
|
||||||
Record.push_back(FirstDeclaration);
|
Record.push_back(FirstDeclaration);
|
||||||
} else {
|
} else {
|
||||||
Record.push_back(PointsToPrevious);
|
Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
|
||||||
Writer.AddDeclRef(First, Record);
|
Writer.AddDeclRef(First, Record);
|
||||||
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ void g(A *a) {
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
void testVector() {
|
void testVector() {
|
||||||
Vector<int> *vec_int;
|
Vector<int> vec_int;
|
||||||
// FIXME: vec_int.push_back(0);
|
vec_int.push_back(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue