Factor the merging of declarations in the AST reader out to a separate

member function template, since the behavior is identical for
ObjCInterfaceDecl and ObjCProtocolDecl. It's expected that all
redeclarable entities will have the same behavior.

llvm-svn: 147450
This commit is contained in:
Douglas Gregor 2012-01-03 17:27:13 +00:00
parent 787869b929
commit 2c46b5bd07
1 changed files with 48 additions and 78 deletions

View File

@ -269,9 +269,12 @@ namespace clang {
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
template <typename T>
template<typename T>
RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);
template<typename T>
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
@ -655,44 +658,7 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
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.
if (FindExistingResult ExistingRes = findExisting(ID)) {
if (ObjCInterfaceDecl *Existing = ExistingRes) {
ObjCInterfaceDecl *ExistingCanon = Existing->getCanonicalDecl();
ObjCInterfaceDecl *IDCanon = ID->getCanonicalDecl();
if (ExistingCanon != IDCanon) {
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
// 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. 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());
}
}
}
}
mergeRedeclarable(ID, Redecl);
ObjCInterfaceDecl *Def = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
if (ID == Def) {
@ -764,45 +730,7 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
RedeclarableResult Redecl = VisitRedeclarable(PD);
VisitObjCContainerDecl(PD);
// Determine whether we need to merge this declaration with another @protocol
// with the same name.
// FIXME: Not needed unless the module file graph is a DAG.
if (FindExistingResult ExistingRes = findExisting(PD)) {
if (ObjCProtocolDecl *Existing = ExistingRes) {
ObjCProtocolDecl *ExistingCanon = Existing->getCanonicalDecl();
ObjCProtocolDecl *PDCanon = PD->getCanonicalDecl();
if (ExistingCanon != PDCanon) {
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
PD->RedeclLink = ObjCProtocolDecl::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. We accept the linear algorithm here because the number of
// unique canonical declarations of an entity should always be tiny.
if (PDCanon == PD) {
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
== Merged.end())
Merged.push_back(Redecl.getFirstID());
}
}
}
}
mergeRedeclarable(PD, Redecl);
ObjCProtocolDecl *Def = ReadDeclAs<ObjCProtocolDecl>(Record, Idx);
if (PD == Def) {
@ -1579,6 +1507,48 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
return RedeclarableResult(Reader, FirstDeclID);
}
/// \brief Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
RedeclarableResult &Redecl) {
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) {
if (T *Existing = ExistingRes) {
T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
if (ExistingCanon != DCanon) {
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
D->RedeclLink
= typename Redeclarable<T>::PreviousDeclLink(ExistingCanon);
// Don't introduce DCanon 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. We accept the linear algorithm here because the number of
// unique canonical declarations of an entity should always be tiny.
if (DCanon == static_cast<T*>(D)) {
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
== Merged.end())
Merged.push_back(Redecl.getFirstID());
}
}
}
}
}
//===----------------------------------------------------------------------===//
// Attribute Reading
//===----------------------------------------------------------------------===//