]> granicus.if.org Git - clang/commitdiff
Implement AST import for Objective-C property implementations
authorDouglas Gregor <dgregor@apple.com>
Tue, 7 Dec 2010 18:32:03 +0000 (18:32 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 7 Dec 2010 18:32:03 +0000 (18:32 +0000)
(@synthesize and @dynamic).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121159 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticASTKinds.td
lib/AST/ASTImporter.cpp
test/ASTMerge/Inputs/property1.m
test/ASTMerge/Inputs/property2.m
test/ASTMerge/property.m

index eda735658ebefe489c9ee602103598b814f5a3c1..7d45bc58463cb1d2f380f8b5d11896cc451a0f68 100644 (file)
@@ -56,6 +56,8 @@ def note_odr_number_of_bases : Note<
   "class has %0 base %plural{1:class|:classes}0">;
 def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
 def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
+
+// Importing Objective-C ASTs
 def err_odr_ivar_type_inconsistent : Error<
   "instance variable %0 declared with incompatible types in different "
   "translation units (%1 vs. %2)">;
@@ -80,6 +82,18 @@ def note_odr_objc_method_here : Note<
 def err_odr_objc_property_type_inconsistent : Error<
   "property %0 declared with incompatible types in different "
   "translation units (%1 vs. %2)">;
+def err_odr_objc_property_impl_kind_inconsistent : Error<
+  "property %0 is implemented with %select{@synthesize|@dynamic}1 in one "
+  "translation but %select{@dynamic|@synthesize}1 in another translation unit">;
+def note_odr_objc_property_impl_kind : Note<
+  "property %0 is implemented with %select{@synthesize|@dynamic}1 here">;
+def err_odr_objc_synthesize_ivar_inconsistent : Error<
+  "property %0 is synthesized to different ivars in different translation "
+  "units (%1 vs. %2)">;
+def note_odr_objc_synthesize_ivar_here : Note<
+  "property is synthesized to ivar %0 here">;
+
+// Importing C++ ASTs
 def err_odr_different_num_template_parameters : Error<
   "template parameter lists have a different number of parameters (%0 vs %1)">;
 def note_odr_template_parameter_list : Note<
index c5314059c088ced87e63cacff52a7cddd65155fc..7a6afbd560e1292bf4e43200f3ec49faad6a51fa 100644 (file)
@@ -118,6 +118,7 @@ namespace {
     Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
     Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
     Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+    Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
     Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
     Decl *VisitObjCClassDecl(ObjCClassDecl *D);
     Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
@@ -3195,6 +3196,87 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
   return ToProperty;
 }
 
+Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+  ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>(
+                                        Importer.Import(D->getPropertyDecl()));
+  if (!Property)
+    return 0;
+
+  DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+  if (!DC)
+    return 0;
+  
+  // Import the lexical declaration context.
+  DeclContext *LexicalDC = DC;
+  if (D->getDeclContext() != D->getLexicalDeclContext()) {
+    LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
+    if (!LexicalDC)
+      return 0;
+  }
+
+  ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC);
+  if (!InImpl)
+    return 0;
+
+  // Import the ivar (for an @synthesize).
+  ObjCIvarDecl *Ivar = 0;
+  if (D->getPropertyIvarDecl()) {
+    Ivar = cast_or_null<ObjCIvarDecl>(
+                                    Importer.Import(D->getPropertyIvarDecl()));
+    if (!Ivar)
+      return 0;
+  }
+
+  ObjCPropertyImplDecl *ToImpl
+    = InImpl->FindPropertyImplDecl(Property->getIdentifier());
+  if (!ToImpl) {    
+    ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC,
+                                          Importer.Import(D->getLocStart()),
+                                          Importer.Import(D->getLocation()),
+                                          Property,
+                                          D->getPropertyImplementation(),
+                                          Ivar, 
+                                  Importer.Import(D->getPropertyIvarDeclLoc()));
+    ToImpl->setLexicalDeclContext(LexicalDC);
+    Importer.Imported(D, ToImpl);
+    LexicalDC->addDecl(ToImpl);
+  } else {
+    // Check that we have the same kind of property implementation (@synthesize
+    // vs. @dynamic).
+    if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) {
+      Importer.ToDiag(ToImpl->getLocation(), 
+                      diag::err_odr_objc_property_impl_kind_inconsistent)
+        << Property->getDeclName() 
+        << (ToImpl->getPropertyImplementation() 
+                                              == ObjCPropertyImplDecl::Dynamic);
+      Importer.FromDiag(D->getLocation(),
+                        diag::note_odr_objc_property_impl_kind)
+        << D->getPropertyDecl()->getDeclName()
+        << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
+      return 0;
+    }
+    
+    // For @synthesize, check that we have the same 
+    if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize &&
+        Ivar != ToImpl->getPropertyIvarDecl()) {
+      Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(), 
+                      diag::err_odr_objc_synthesize_ivar_inconsistent)
+        << Property->getDeclName()
+        << ToImpl->getPropertyIvarDecl()->getDeclName()
+        << Ivar->getDeclName();
+      Importer.FromDiag(D->getPropertyIvarDeclLoc(), 
+                        diag::note_odr_objc_synthesize_ivar_here)
+        << D->getPropertyIvarDecl()->getDeclName();
+      return 0;
+    }
+    
+    // Merge the existing implementation with the new implementation.
+    Importer.Imported(D, ToImpl);
+  }
+  
+  return ToImpl;
+}
+
 Decl *
 ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
   // Import the context of this declaration.
index 37887a34f76721f0290d476fd130d3776544e456..22fe0a02220cf466cc58e17fa70ee9c69d018ae0 100644 (file)
 @property (readonly) float Prop1;
 @end
 
+// Properties with implementations
+@interface I3 {
+  int ivar1;
+  int ivar2;
+  int ivar3;
+  int Prop4;
+}
+@property int Prop1;
+@property int Prop2;
+@property int Prop3;
+@property int Prop4;
+@end
+
+@implementation I3
+@synthesize Prop1 = ivar1;
+@synthesize Prop2 = ivar3;
+@dynamic Prop3;
+@synthesize Prop4;
+@end
index 6039f10ec6e8a4e36bb3a27044d1745cde6b5bd0..64a03fb04ec3764c3d0344d9c979c42b84b459ca 100644 (file)
 @interface I2
 @property (readonly) int Prop1;
 @end
+
+// Properties with implementations
+@interface I3 {
+  int ivar1;
+  int ivar2;
+  int ivar3;
+  int Prop4;
+}
+@property int Prop1;
+@property int Prop2;
+@property int Prop3;
+@property int Prop4;
+@end
+
+@implementation I3
+@synthesize Prop2 = ivar2;
+@synthesize Prop1 = ivar1;
+@synthesize Prop3 = ivar3;
+@synthesize Prop4 = Prop4;
+@end
index 5f7a7308da653424f22373749923b52ce8d91f8e..a8dd7c420c89752ab185a6e8e207cdaebf10c852 100644 (file)
@@ -6,4 +6,8 @@
 // CHECK: property1.m:10:28: note: declared here with type 'float'
 // CHECK: property2.m:12:26: error: instance method 'Prop1' has incompatible result types in different translation units ('int' vs. 'float')
 // CHECK: property1.m:10:28: note: instance method 'Prop1' also declared here
-// CHECK: 2 errors generated.
+// CHECK: property1.m:28:21: error: property 'Prop2' is synthesized to different ivars in different translation units ('ivar3' vs. 'ivar2')
+// CHECK: property2.m:29:21: note: property is synthesized to ivar 'ivar2' here
+// CHECK: property1.m:29:10: error: property 'Prop3' is implemented with @dynamic in one translation but @synthesize in another translation unit
+// CHECK: property2.m:31:13: note: property 'Prop3' is implemented with @synthesize here
+// CHECK: 4 errors generated.