Extern the ASTImporter to import @implementation declarations.

llvm-svn: 121097
This commit is contained in:
Douglas Gregor 2010-12-07 01:26:03 +00:00
parent 7ce1c1eaa3
commit da8025c09e
4 changed files with 122 additions and 3 deletions

View File

@ -115,6 +115,7 @@ namespace {
Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D);
Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D);
Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
Decl *VisitObjCClassDecl(ObjCClassDecl *D);
@ -3012,8 +3013,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
// If we have an @implementation, import it as well.
if (D->getImplementation()) {
ObjCImplementationDecl *Impl
= cast<ObjCImplementationDecl>(Importer.Import(D->getImplementation()));
ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
Importer.Import(D->getImplementation()));
if (!Impl)
return 0;
@ -3023,6 +3024,79 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
return ToIface;
}
Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
// Find the corresponding interface.
ObjCInterfaceDecl *Iface = cast_or_null<ObjCInterfaceDecl>(
Importer.Import(D->getClassInterface()));
if (!Iface)
return 0;
// Import the superclass, if any.
ObjCInterfaceDecl *Super = 0;
if (D->getSuperClass()) {
Super = cast_or_null<ObjCInterfaceDecl>(
Importer.Import(D->getSuperClass()));
if (!Super)
return 0;
}
ObjCImplementationDecl *Impl = Iface->getImplementation();
if (!Impl) {
// We haven't imported an implementation yet. Create a new @implementation
// now.
Impl = ObjCImplementationDecl::Create(Importer.getToContext(),
Importer.ImportContext(D->getDeclContext()),
Importer.Import(D->getLocation()),
Iface, Super);
if (D->getDeclContext() != D->getLexicalDeclContext()) {
DeclContext *LexicalDC
= Importer.ImportContext(D->getLexicalDeclContext());
if (!LexicalDC)
return 0;
Impl->setLexicalDeclContext(LexicalDC);
}
// Associate the implementation with the class it implements.
Iface->setImplementation(Impl);
Importer.Imported(D, Iface->getImplementation());
} else {
Importer.Imported(D, Iface->getImplementation());
// Verify that the existing @implementation has the same superclass.
if ((Super && !Impl->getSuperClass()) ||
(!Super && Impl->getSuperClass()) ||
(Super && Impl->getSuperClass() &&
Super->getCanonicalDecl() != Impl->getSuperClass())) {
Importer.ToDiag(Impl->getLocation(),
diag::err_odr_objc_superclass_inconsistent)
<< Iface->getDeclName();
// FIXME: It would be nice to have the location of the superclass
// below.
if (Impl->getSuperClass())
Importer.ToDiag(Impl->getLocation(),
diag::note_odr_objc_superclass)
<< Impl->getSuperClass()->getDeclName();
else
Importer.ToDiag(Impl->getLocation(),
diag::note_odr_objc_missing_superclass);
if (D->getSuperClass())
Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_superclass)
<< D->getSuperClass()->getDeclName();
else
Importer.FromDiag(D->getLocation(),
diag::note_odr_objc_missing_superclass);
return 0;
}
}
// Import all of the members of this @implementation.
ImportDeclContext(D);
return Impl;
}
Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
// Import the major distinguishing characteristics of an @property.
DeclContext *DC, *LexicalDC;

View File

@ -79,3 +79,25 @@
@protocol P4
- (double)honk:(int)a;
@end
// Interface with implementation
@interface I13
@end
@implementation I13
@end
@interface I13a
@end
@implementation I13a
@end
// Implementation by itself
@implementation I14 : I12
@end
@implementation I15 : I12
@end

View File

@ -78,3 +78,23 @@
@protocol P5
- (double)honk:(int)a;
@end
// Interface with implementation
@interface I13
@end
@implementation I13
@end
@interface I13b
@end
@implementation I13b
@end
// Implementation by itself
@implementation I14 : I12
@end
@implementation I15 : I11
@end

View File

@ -15,5 +15,8 @@
// CHECK: interface1.m:46:1: note: class method 'bar:' also declared here
// CHECK: interface2.m:57:20: error: instance method 'bar:' has a parameter with a different types in different translation units ('double' vs. 'float')
// CHECK: interface1.m:58:19: note: declared here with type 'float'
// CHECK: 6 errors generated
// CHECK: interface1.m:100:1: error: class 'I15' has incompatible superclasses
// CHECK: interface1.m:100:1: note: inherits from superclass 'I12' here
// CHECK: interface2.m:99:1: note: inherits from superclass 'I11' here
// CHECK: 8 errors generated