From dd182ff10b9145e432dea1fd2fb67100ccca3b10 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 7 Dec 2010 01:26:03 +0000 Subject: [PATCH] Extern the ASTImporter to import @implementation declarations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121097 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 78 ++++++++++++++++++++++++++++++- test/ASTMerge/Inputs/interface1.m | 22 +++++++++ test/ASTMerge/Inputs/interface2.m | 20 ++++++++ test/ASTMerge/interface.m | 5 +- 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index c4d1181528..13b89e1ac0 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -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(Importer.Import(D->getImplementation())); + ObjCImplementationDecl *Impl = cast_or_null( + 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( + Importer.Import(D->getClassInterface())); + if (!Iface) + return 0; + + // Import the superclass, if any. + ObjCInterfaceDecl *Super = 0; + if (D->getSuperClass()) { + Super = cast_or_null( + 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; diff --git a/test/ASTMerge/Inputs/interface1.m b/test/ASTMerge/Inputs/interface1.m index 7e9935db7c..5865c0eff0 100644 --- a/test/ASTMerge/Inputs/interface1.m +++ b/test/ASTMerge/Inputs/interface1.m @@ -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 + + diff --git a/test/ASTMerge/Inputs/interface2.m b/test/ASTMerge/Inputs/interface2.m index bef7fb838c..3fb43f5930 100644 --- a/test/ASTMerge/Inputs/interface2.m +++ b/test/ASTMerge/Inputs/interface2.m @@ -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 diff --git a/test/ASTMerge/interface.m b/test/ASTMerge/interface.m index 420ae38825..e37e3807e5 100644 --- a/test/ASTMerge/interface.m +++ b/test/ASTMerge/interface.m @@ -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 -- 2.40.0