]> granicus.if.org Git - clang/commitdiff
Extern the ASTImporter to import @implementation declarations.
authorDouglas Gregor <dgregor@apple.com>
Tue, 7 Dec 2010 01:26:03 +0000 (01:26 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 7 Dec 2010 01:26:03 +0000 (01:26 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121097 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTImporter.cpp
test/ASTMerge/Inputs/interface1.m
test/ASTMerge/Inputs/interface2.m
test/ASTMerge/interface.m

index c4d1181528cc95a1d7569b6263953775ad561392..13b89e1ac07ace04ce2964c8923b026b80ae127c 100644 (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;
index 7e9935db7c7bf83ae7c967f5dcae1f7afe03b220..5865c0eff070262a41970e6c74f674eb93476913 100644 (file)
 @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
+
+
index bef7fb838c05d512c1b6a6e8ad5ea45c021b72ee..3fb43f5930c38b8600d9317aa57b0f7dca49c1bb 100644 (file)
 @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
index 420ae38825482a0e677a78a0d85767e28f2bdc2c..e37e3807e5147b0d2b1f129a79cc7c83c1841dec 100644 (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