]> granicus.if.org Git - clang/commitdiff
objective-c: perform strict type checking on property
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 15 May 2012 22:37:04 +0000 (22:37 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 15 May 2012 22:37:04 +0000 (22:37 +0000)
type and its accessor type and issue error if types
are incompatible, instead of crashing in IRgen.
// rdar://1105153

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaObjCProperty.cpp
test/SemaObjC/property-impl-misuse.m
test/SemaObjC/property-typecheck-1.m

index 7436f8b3962084bb2460388b15c292eec549c619..0865619e6d088d7dda787f7f473e287507c51eb1 100644 (file)
@@ -685,6 +685,8 @@ def err_incomplete_synthesized_property : Error<
 
 def error_property_ivar_type : Error<
   "type of property %0 (%1) does not match type of ivar %2 (%3)">;
+def error_property_accessor_type : Error<
+  "type of property %0 (%1) does not match type of accessor %2 (%3)">;
 def error_ivar_in_superclass_use : Error<
   "property %0 attempting to use ivar %1 declared in super class %2">;
 def error_weak_property : Error<
index e826b47784b360caa4535620fc698b6c7dea43dc..f42259c68694e386899ace8c006d9b0acac3aa34 100644 (file)
@@ -1050,21 +1050,42 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
 bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
                                             ObjCMethodDecl *GetterMethod,
                                             SourceLocation Loc) {
-  if (GetterMethod &&
-      !Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(),
-                           property->getType().getNonReferenceType())) {
-    AssignConvertType result = Incompatible;
-    if (property->getType()->isObjCObjectPointerType())
-      result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
-                                          property->getType());
-    if (result != Compatible) {
-      Diag(Loc, diag::warn_accessor_property_type_mismatch)
-      << property->getDeclName()
-      << GetterMethod->getSelector();
-      Diag(GetterMethod->getLocation(), diag::note_declared_at);
-      return true;
+  if (!GetterMethod)
+    return false;
+  QualType GetterType = GetterMethod->getResultType().getNonReferenceType();
+  QualType PropertyIvarType = property->getType().getNonReferenceType();
+  bool compat = Context.hasSameType(PropertyIvarType, GetterType);
+  if (!compat) {
+    if (isa<ObjCObjectPointerType>(PropertyIvarType) && 
+        isa<ObjCObjectPointerType>(GetterType))
+      compat =
+        Context.canAssignObjCInterfaces(
+                                      PropertyIvarType->getAs<ObjCObjectPointerType>(),
+                                      GetterType->getAs<ObjCObjectPointerType>());
+    else if (CheckAssignmentConstraints(Loc, PropertyIvarType, GetterType) 
+              != Compatible) {
+          Diag(Loc, diag::error_property_accessor_type)
+            << property->getDeclName() << PropertyIvarType
+            << GetterMethod->getSelector() << GetterType;
+          Diag(GetterMethod->getLocation(), diag::note_declared_at);
+          return true;
+    } else {
+      compat = true;
+      QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
+      QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
+      if (lhsType != rhsType && lhsType->isArithmeticType())
+        compat = false;
     }
   }
+  
+  if (!compat) {
+    Diag(Loc, diag::warn_accessor_property_type_mismatch)
+    << property->getDeclName()
+    << GetterMethod->getSelector();
+    Diag(GetterMethod->getLocation(), diag::note_declared_at);
+    return true;
+  }
+
   return false;
 }
 
index c3cedb05ed61ae734ed98f890aee3462283dd3d6..1d3d64ce31697e9b3df870a0d4fc1a5d6c709256 100644 (file)
     self.gradientStyle; // expected-error {{property 'gradientStyle' not found on object of type 'Class'}}
 }
 @end
+
+// rdar://1105153
+@interface rdar1105153
+@property int P; // expected-error {{type of property 'P' ('int') does not match type of accessor 'P' ('void')}}
+- (void)P; // expected-note {{declared here}}
+
+@property int P1; // expected-warning {{type of property 'P1' does not match type of accessor 'P1'}} 
+- (double) P1; // expected-note {{declared here}}
+
+@property int P2; // expected-error {{type of property 'P2' ('int') does not match type of accessor 'P2' ('double *')}}
+- (double*)P2; // expected-note {{declared here}}
+
+@end
index f71e4a0f1c7f847efdbd345220872bba18d7ce14..b28108ac85d1c5a26f01c4fa14363011d1f18454 100644 (file)
@@ -73,11 +73,11 @@ typedef void (F)(void);
  NSArray* first;
 }
 
-@property (readonly) NSArray* pieces;  // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}}
-@property (readonly) NSMutableArray* first; 
+@property (readonly) NSArray* pieces;
+@property (readonly) NSMutableArray* first;  // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
 
-- (NSMutableArray*) pieces; // expected-note {{declared here}} // expected-note {{declared here}}
-- (NSArray*) first;
+- (NSMutableArray*) pieces;
+- (NSArray*) first; // expected-note 2 {{declared here}}
 @end
 
 @interface Class2  {
@@ -90,12 +90,12 @@ typedef void (F)(void);
 
 - (id) lastPiece
 {
- return container.pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}}
+ return container.pieces;
 }
 
 - (id)firstPeice
 {
-  return container.first; 
+  return container.first; // expected-warning {{type of property 'first' does not match type of accessor 'first'}}
 }
 @end