forked from OSchip/llvm-project
Teach the AST importer about redeclaration chains for Objective-C
classes and protocols, implementing lazy-import semantics for both. llvm-svn: 148816
This commit is contained in:
parent
681db34eae
commit
2aa53777e7
|
@ -90,6 +90,10 @@ namespace clang {
|
||||||
bool ForceImport = false);
|
bool ForceImport = false);
|
||||||
bool ImportDefinition(EnumDecl *From, EnumDecl *To,
|
bool ImportDefinition(EnumDecl *From, EnumDecl *To,
|
||||||
bool ForceImport = false);
|
bool ForceImport = false);
|
||||||
|
bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
|
||||||
|
bool ForceImport = false);
|
||||||
|
bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To,
|
||||||
|
bool ForceImport = false);
|
||||||
TemplateParameterList *ImportTemplateParameterList(
|
TemplateParameterList *ImportTemplateParameterList(
|
||||||
TemplateParameterList *Params);
|
TemplateParameterList *Params);
|
||||||
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
|
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
|
||||||
|
@ -3098,7 +3102,56 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
|
||||||
return ToCategory;
|
return ToCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
|
||||||
|
ObjCProtocolDecl *To,
|
||||||
|
bool ForceImport) {
|
||||||
|
if (To->getDefinition()) {
|
||||||
|
ImportDeclContext(From);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the protocol definition
|
||||||
|
To->startDefinition();
|
||||||
|
|
||||||
|
// Import protocols
|
||||||
|
SmallVector<ObjCProtocolDecl *, 4> Protocols;
|
||||||
|
SmallVector<SourceLocation, 4> ProtocolLocs;
|
||||||
|
ObjCProtocolDecl::protocol_loc_iterator
|
||||||
|
FromProtoLoc = From->protocol_loc_begin();
|
||||||
|
for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(),
|
||||||
|
FromProtoEnd = From->protocol_end();
|
||||||
|
FromProto != FromProtoEnd;
|
||||||
|
++FromProto, ++FromProtoLoc) {
|
||||||
|
ObjCProtocolDecl *ToProto
|
||||||
|
= cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
|
||||||
|
if (!ToProto)
|
||||||
|
return true;
|
||||||
|
Protocols.push_back(ToProto);
|
||||||
|
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: If we're merging, make sure that the protocol list is the same.
|
||||||
|
To->setProtocolList(Protocols.data(), Protocols.size(),
|
||||||
|
ProtocolLocs.data(), Importer.getToContext());
|
||||||
|
|
||||||
|
// Import all of the members of this protocol.
|
||||||
|
ImportDeclContext(From);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
|
Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
|
||||||
|
// If this protocol has a definition in the translation unit we're coming
|
||||||
|
// from, but this particular declaration is not that definition, import the
|
||||||
|
// definition and map to that.
|
||||||
|
ObjCProtocolDecl *Definition = D->getDefinition();
|
||||||
|
if (Definition && Definition != D) {
|
||||||
|
Decl *ImportedDef = Importer.Import(Definition);
|
||||||
|
if (!ImportedDef)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return Importer.Imported(D, ImportedDef);
|
||||||
|
}
|
||||||
|
|
||||||
// Import the major distinguishing characteristics of a protocol.
|
// Import the major distinguishing characteristics of a protocol.
|
||||||
DeclContext *DC, *LexicalDC;
|
DeclContext *DC, *LexicalDC;
|
||||||
DeclarationName Name;
|
DeclarationName Name;
|
||||||
|
@ -3118,51 +3171,131 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCProtocolDecl *ToProto = MergeWithProtocol;
|
ObjCProtocolDecl *ToProto = MergeWithProtocol;
|
||||||
if (!ToProto || !ToProto->hasDefinition()) {
|
if (!ToProto) {
|
||||||
if (!ToProto) {
|
ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
|
||||||
ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
|
Name.getAsIdentifierInfo(), Loc,
|
||||||
Name.getAsIdentifierInfo(), Loc,
|
Importer.Import(D->getAtStartLoc()),
|
||||||
Importer.Import(D->getAtStartLoc()),
|
/*PrevDecl=*/0);
|
||||||
/*PrevDecl=*/0);
|
ToProto->setLexicalDeclContext(LexicalDC);
|
||||||
ToProto->setLexicalDeclContext(LexicalDC);
|
LexicalDC->addDeclInternal(ToProto);
|
||||||
LexicalDC->addDeclInternal(ToProto);
|
|
||||||
}
|
|
||||||
if (!ToProto->hasDefinition())
|
|
||||||
ToProto->startDefinition();
|
|
||||||
|
|
||||||
Importer.Imported(D, ToProto);
|
|
||||||
|
|
||||||
// Import protocols
|
|
||||||
SmallVector<ObjCProtocolDecl *, 4> Protocols;
|
|
||||||
SmallVector<SourceLocation, 4> ProtocolLocs;
|
|
||||||
ObjCProtocolDecl::protocol_loc_iterator
|
|
||||||
FromProtoLoc = D->protocol_loc_begin();
|
|
||||||
for (ObjCProtocolDecl::protocol_iterator FromProto = D->protocol_begin(),
|
|
||||||
FromProtoEnd = D->protocol_end();
|
|
||||||
FromProto != FromProtoEnd;
|
|
||||||
++FromProto, ++FromProtoLoc) {
|
|
||||||
ObjCProtocolDecl *ToProto
|
|
||||||
= cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
|
|
||||||
if (!ToProto)
|
|
||||||
return 0;
|
|
||||||
Protocols.push_back(ToProto);
|
|
||||||
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: If we're merging, make sure that the protocol list is the same.
|
|
||||||
ToProto->setProtocolList(Protocols.data(), Protocols.size(),
|
|
||||||
ProtocolLocs.data(), Importer.getToContext());
|
|
||||||
} else {
|
|
||||||
Importer.Imported(D, ToProto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Importer.Imported(D, ToProto);
|
||||||
|
|
||||||
// Import all of the members of this protocol.
|
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto))
|
||||||
ImportDeclContext(D);
|
return 0;
|
||||||
|
|
||||||
return ToProto;
|
return ToProto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
|
||||||
|
ObjCInterfaceDecl *To,
|
||||||
|
bool ForceImport) {
|
||||||
|
if (To->getDefinition()) {
|
||||||
|
// Check consistency of superclass.
|
||||||
|
ObjCInterfaceDecl *FromSuper = From->getSuperClass();
|
||||||
|
if (FromSuper) {
|
||||||
|
FromSuper = cast_or_null<ObjCInterfaceDecl>(Importer.Import(FromSuper));
|
||||||
|
if (!FromSuper)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjCInterfaceDecl *ToSuper = To->getSuperClass();
|
||||||
|
if ((bool)FromSuper != (bool)ToSuper ||
|
||||||
|
(FromSuper && !declaresSameEntity(FromSuper, ToSuper))) {
|
||||||
|
Importer.ToDiag(To->getLocation(),
|
||||||
|
diag::err_odr_objc_superclass_inconsistent)
|
||||||
|
<< To->getDeclName();
|
||||||
|
if (ToSuper)
|
||||||
|
Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass)
|
||||||
|
<< To->getSuperClass()->getDeclName();
|
||||||
|
else
|
||||||
|
Importer.ToDiag(To->getLocation(),
|
||||||
|
diag::note_odr_objc_missing_superclass);
|
||||||
|
if (From->getSuperClass())
|
||||||
|
Importer.FromDiag(From->getSuperClassLoc(),
|
||||||
|
diag::note_odr_objc_superclass)
|
||||||
|
<< From->getSuperClass()->getDeclName();
|
||||||
|
else
|
||||||
|
Importer.FromDiag(From->getLocation(),
|
||||||
|
diag::note_odr_objc_missing_superclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportDeclContext(From);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the definition.
|
||||||
|
To->startDefinition();
|
||||||
|
|
||||||
|
// If this class has a superclass, import it.
|
||||||
|
if (From->getSuperClass()) {
|
||||||
|
ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>(
|
||||||
|
Importer.Import(From->getSuperClass()));
|
||||||
|
if (!Super)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
To->setSuperClass(Super);
|
||||||
|
To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import protocols
|
||||||
|
SmallVector<ObjCProtocolDecl *, 4> Protocols;
|
||||||
|
SmallVector<SourceLocation, 4> ProtocolLocs;
|
||||||
|
ObjCInterfaceDecl::protocol_loc_iterator
|
||||||
|
FromProtoLoc = From->protocol_loc_begin();
|
||||||
|
|
||||||
|
for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(),
|
||||||
|
FromProtoEnd = From->protocol_end();
|
||||||
|
FromProto != FromProtoEnd;
|
||||||
|
++FromProto, ++FromProtoLoc) {
|
||||||
|
ObjCProtocolDecl *ToProto
|
||||||
|
= cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
|
||||||
|
if (!ToProto)
|
||||||
|
return true;
|
||||||
|
Protocols.push_back(ToProto);
|
||||||
|
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: If we're merging, make sure that the protocol list is the same.
|
||||||
|
To->setProtocolList(Protocols.data(), Protocols.size(),
|
||||||
|
ProtocolLocs.data(), Importer.getToContext());
|
||||||
|
|
||||||
|
// Import categories. When the categories themselves are imported, they'll
|
||||||
|
// hook themselves into this interface.
|
||||||
|
for (ObjCCategoryDecl *FromCat = From->getCategoryList(); FromCat;
|
||||||
|
FromCat = FromCat->getNextClassCategory())
|
||||||
|
Importer.Import(FromCat);
|
||||||
|
|
||||||
|
// If we have an @implementation, import it as well.
|
||||||
|
if (From->getImplementation()) {
|
||||||
|
ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
|
||||||
|
Importer.Import(From->getImplementation()));
|
||||||
|
if (!Impl)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
To->setImplementation(Impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import all of the members of this class.
|
||||||
|
ImportDeclContext(From);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||||
|
// If this class has a definition in the translation unit we're coming from,
|
||||||
|
// but this particular declaration is not that definition, import the
|
||||||
|
// definition and map to that.
|
||||||
|
ObjCInterfaceDecl *Definition = D->getDefinition();
|
||||||
|
if (Definition && Definition != D) {
|
||||||
|
Decl *ImportedDef = Importer.Import(Definition);
|
||||||
|
if (!ImportedDef)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return Importer.Imported(D, ImportedDef);
|
||||||
|
}
|
||||||
|
|
||||||
// Import the major distinguishing characteristics of an @interface.
|
// Import the major distinguishing characteristics of an @interface.
|
||||||
DeclContext *DC, *LexicalDC;
|
DeclContext *DC, *LexicalDC;
|
||||||
DeclarationName Name;
|
DeclarationName Name;
|
||||||
|
@ -3170,6 +3303,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||||
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
|
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Look for an existing interface with the same name.
|
||||||
ObjCInterfaceDecl *MergeWithIface = 0;
|
ObjCInterfaceDecl *MergeWithIface = 0;
|
||||||
llvm::SmallVector<NamedDecl *, 2> FoundDecls;
|
llvm::SmallVector<NamedDecl *, 2> FoundDecls;
|
||||||
DC->localUncachedLookup(Name, FoundDecls);
|
DC->localUncachedLookup(Name, FoundDecls);
|
||||||
|
@ -3181,127 +3315,22 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create an interface declaration, if one does not already exist.
|
||||||
ObjCInterfaceDecl *ToIface = MergeWithIface;
|
ObjCInterfaceDecl *ToIface = MergeWithIface;
|
||||||
if (!ToIface || !ToIface->hasDefinition()) {
|
if (!ToIface) {
|
||||||
if (!ToIface) {
|
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
|
||||||
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
|
Importer.Import(D->getAtStartLoc()),
|
||||||
Importer.Import(D->getAtStartLoc()),
|
Name.getAsIdentifierInfo(),
|
||||||
Name.getAsIdentifierInfo(),
|
/*PrevDecl=*/0,Loc,
|
||||||
/*PrevDecl=*/0,Loc,
|
D->isImplicitInterfaceDecl());
|
||||||
D->isImplicitInterfaceDecl());
|
ToIface->setLexicalDeclContext(LexicalDC);
|
||||||
ToIface->setLexicalDeclContext(LexicalDC);
|
LexicalDC->addDeclInternal(ToIface);
|
||||||
LexicalDC->addDeclInternal(ToIface);
|
|
||||||
}
|
|
||||||
Importer.Imported(D, ToIface);
|
|
||||||
|
|
||||||
if (D->hasDefinition()) {
|
|
||||||
if (!ToIface->hasDefinition())
|
|
||||||
ToIface->startDefinition();
|
|
||||||
|
|
||||||
if (D->getSuperClass()) {
|
|
||||||
ObjCInterfaceDecl *Super
|
|
||||||
= cast_or_null<ObjCInterfaceDecl>(
|
|
||||||
Importer.Import(D->getSuperClass()));
|
|
||||||
if (!Super)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ToIface->setSuperClass(Super);
|
|
||||||
ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import protocols
|
|
||||||
SmallVector<ObjCProtocolDecl *, 4> Protocols;
|
|
||||||
SmallVector<SourceLocation, 4> ProtocolLocs;
|
|
||||||
ObjCInterfaceDecl::protocol_loc_iterator
|
|
||||||
FromProtoLoc = D->protocol_loc_begin();
|
|
||||||
|
|
||||||
for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
|
|
||||||
FromProtoEnd = D->protocol_end();
|
|
||||||
FromProto != FromProtoEnd;
|
|
||||||
++FromProto, ++FromProtoLoc) {
|
|
||||||
ObjCProtocolDecl *ToProto
|
|
||||||
= cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
|
|
||||||
if (!ToProto)
|
|
||||||
return 0;
|
|
||||||
Protocols.push_back(ToProto);
|
|
||||||
ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: If we're merging, make sure that the protocol list is the same.
|
|
||||||
ToIface->setProtocolList(Protocols.data(), Protocols.size(),
|
|
||||||
ProtocolLocs.data(), Importer.getToContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import @end range
|
|
||||||
ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
|
|
||||||
} else {
|
|
||||||
Importer.Imported(D, ToIface);
|
|
||||||
|
|
||||||
if (D->hasDefinition()) {
|
|
||||||
// Check for consistency of superclasses.
|
|
||||||
DeclarationName FromSuperName, ToSuperName;
|
|
||||||
|
|
||||||
// If the superclass hasn't been imported yet, do so before checking.
|
|
||||||
ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
|
|
||||||
ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
|
|
||||||
|
|
||||||
if (DSuperClass && !ToIfaceSuperClass) {
|
|
||||||
Decl *ImportedSuperClass = Importer.Import(DSuperClass);
|
|
||||||
ObjCInterfaceDecl *ImportedSuperIface
|
|
||||||
= cast<ObjCInterfaceDecl>(ImportedSuperClass);
|
|
||||||
|
|
||||||
ToIface->setSuperClass(ImportedSuperIface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (D->getSuperClass())
|
|
||||||
FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
|
|
||||||
if (ToIface->getSuperClass())
|
|
||||||
ToSuperName = ToIface->getSuperClass()->getDeclName();
|
|
||||||
if (FromSuperName != ToSuperName) {
|
|
||||||
Importer.ToDiag(ToIface->getLocation(),
|
|
||||||
diag::err_odr_objc_superclass_inconsistent)
|
|
||||||
<< ToIface->getDeclName();
|
|
||||||
if (ToIface->getSuperClass())
|
|
||||||
Importer.ToDiag(ToIface->getSuperClassLoc(),
|
|
||||||
diag::note_odr_objc_superclass)
|
|
||||||
<< ToIface->getSuperClass()->getDeclName();
|
|
||||||
else
|
|
||||||
Importer.ToDiag(ToIface->getLocation(),
|
|
||||||
diag::note_odr_objc_missing_superclass);
|
|
||||||
if (D->getSuperClass())
|
|
||||||
Importer.FromDiag(D->getSuperClassLoc(),
|
|
||||||
diag::note_odr_objc_superclass)
|
|
||||||
<< D->getSuperClass()->getDeclName();
|
|
||||||
else
|
|
||||||
Importer.FromDiag(D->getLocation(),
|
|
||||||
diag::note_odr_objc_missing_superclass);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Importer.Imported(D, ToIface);
|
||||||
|
|
||||||
if (!D->hasDefinition())
|
if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
|
||||||
return ToIface;
|
return 0;
|
||||||
|
|
||||||
// Import categories. When the categories themselves are imported, they'll
|
|
||||||
// hook themselves into this interface.
|
|
||||||
for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat;
|
|
||||||
FromCat = FromCat->getNextClassCategory())
|
|
||||||
Importer.Import(FromCat);
|
|
||||||
|
|
||||||
// Import all of the members of this class.
|
|
||||||
ImportDeclContext(D);
|
|
||||||
|
|
||||||
// If we have an @implementation, import it as well.
|
|
||||||
if ( D->getImplementation()) {
|
|
||||||
ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
|
|
||||||
Importer.Import(D->getImplementation()));
|
|
||||||
if (!Impl)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ToIface->setImplementation(Impl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ToIface;
|
return ToIface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4391,7 +4420,23 @@ void ASTImporter::ImportDefinition(Decl *From) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ObjCInterfaceDecl *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
|
||||||
|
if (!ToIFace->getDefinition()) {
|
||||||
|
Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace,
|
||||||
|
/*ForceImport=*/true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
|
||||||
|
if (!ToProto->getDefinition()) {
|
||||||
|
Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto,
|
||||||
|
/*ForceImport=*/true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Importer.ImportDeclContext(FromDC, true);
|
Importer.ImportDeclContext(FromDC, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue