Implement declaration merging for Objective-C protocols across

multiple, disjoint modules. There is far too much duplicating with the
ObjCInterfaceDecl case here, which I'll eliminate shortly.

llvm-svn: 147417
This commit is contained in:
Douglas Gregor 2012-01-01 21:47:52 +00:00
parent a503bb9ce4
commit da38930cf3
6 changed files with 68 additions and 6 deletions

View File

@ -677,9 +677,9 @@ private:
/// \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.
/// FIXME: This data structure is currently only used for ObjCInterfaceDecls
/// and ObjCProtocolDecls to 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> >

View File

@ -759,12 +759,54 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
}
void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
VisitRedeclarable(PD);
// Record the declaration -> global ID mapping.
Reader.DeclToID[PD] = ThisDeclID;
RedeclarableResult Redecl = VisitRedeclarable(PD);
VisitObjCContainerDecl(PD);
PD->InitiallyForwardDecl = Record[Idx++];
PD->isForwardProtoDecl = Record[Idx++];
PD->setLocEnd(ReadSourceLocation(Record, Idx));
// 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());
}
}
}
}
ObjCProtocolDecl *Def = ReadDeclAs<ObjCProtocolDecl>(Record, Idx);
if (PD == Def) {
// Read the definition.
@ -1645,8 +1687,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
Y->getDeclContext()->getRedeclContext()))
return false;
// Objective-C classes with the same name always match.
if (isa<ObjCInterfaceDecl>(X))
// Objective-C classes and protocols with the same name always match.
if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
return true;
// FIXME: Many other cases to implement.

View File

@ -2,6 +2,9 @@ __import_module__ redecl_merge_left;
@class C4;
@class C4;
@protocol P4;
@protocol P4;
@protocol P4;
__import_module__ redecl_merge_right;
@class B;

View File

@ -35,6 +35,10 @@ int *explicit_func(void);
struct explicit_struct;
@protocol P3, P4;
@protocol P3;
#ifdef __cplusplus
template<typename T> class Vector;

View File

@ -42,6 +42,11 @@ int *explicit_func(void);
struct explicit_struct;
@protocol P4, P3;
@protocol P3;
@protocol P3;
@protocol P3;
#ifdef __cplusplus
template<typename T> class Vector {
public:

View File

@ -6,6 +6,7 @@
@class C3;
__import_module__ redecl_merge_left;
@protocol P4;
@class C3;
@class C3;
__import_module__ redecl_merge_right;
@ -83,6 +84,13 @@ void g(A *a) {
[a init];
}
@protocol P3
- (void)p3_method;
@end
id<P4> p4;
id<P3> p3;
#ifdef __cplusplus
void testVector() {
Vector<int> vec_int;