r192115 - ObjectiveC: Warn when 'readonly' property has explicit

Fariborz Jahanian fjahanian at apple.com
Mon Oct 7 10:20:02 PDT 2013


Author: fjahanian
Date: Mon Oct  7 12:20:02 2013
New Revision: 192115

URL: http://llvm.org/viewvc/llvm-project?rev=192115&view=rev
Log:
ObjectiveC: Warn when 'readonly' property has explicit
ownership attribute (such as 'copy', 'assign' etc.)
// rdar://15131088

Modified:
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/test/SemaObjC/overriding-property-in-class-extension.m
    cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
    cfe/trunk/test/SemaObjC/tentative-property-decl.m

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=192115&r1=192114&r2=192115&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Oct  7 12:20:02 2013
@@ -321,6 +321,21 @@ static unsigned getOwnershipRule(unsigne
                  ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
 }
 
+static const char *NameOfOwnershipAttribute(unsigned attr) {
+  if (attr & ObjCPropertyDecl::OBJC_PR_assign)
+    return "assign";
+  if (attr & ObjCPropertyDecl::OBJC_PR_retain )
+    return "retain";
+  if (attr & ObjCPropertyDecl::OBJC_PR_copy)
+    return "copy";
+  if (attr & ObjCPropertyDecl::OBJC_PR_weak)
+    return "weak";
+  if (attr & ObjCPropertyDecl::OBJC_PR_strong)
+    return "strong";
+  assert(attr & ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+  return "unsafe_unretained";
+}
+
 ObjCPropertyDecl *
 Sema::HandlePropertyInClassExtension(Scope *S,
                                      SourceLocation AtLoc,
@@ -434,6 +449,8 @@ Sema::HandlePropertyInClassExtension(Sco
   // with continuation class's readwrite property attribute!
   unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
   if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
+    PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
+    PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
     PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType());
     unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
     unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
@@ -775,75 +792,6 @@ DiagnosePropertyMismatchDeclInProtocols(
     S.Diag(AtLoc, diag::note_property_synthesize);
 }
 
-/// DiagnoseClassAndClassExtPropertyMismatch - diagnose inconsistant property
-/// attribute declared in primary class and attributes overridden in any of its
-/// class extensions.
-static void
-DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl, 
-                                         ObjCPropertyDecl *property) {
-  unsigned Attributes = property->getPropertyAttributesAsWritten();
-  bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly);
-  for (ObjCInterfaceDecl::known_extensions_iterator
-         Ext = ClassDecl->known_extensions_begin(),
-         ExtEnd = ClassDecl->known_extensions_end();
-       Ext != ExtEnd; ++Ext) {
-    ObjCPropertyDecl *ClassExtProperty = 0;
-    DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
-    for (unsigned I = 0, N = R.size(); I != N; ++I) {
-      ClassExtProperty = dyn_cast<ObjCPropertyDecl>(R[0]);
-      if (ClassExtProperty)
-        break;
-    }
-
-    if (ClassExtProperty) {
-      warn = false;
-      unsigned classExtPropertyAttr = 
-        ClassExtProperty->getPropertyAttributesAsWritten();
-      // We are issuing the warning that we postponed because class extensions
-      // can override readonly->readwrite and 'setter' attributes originally
-      // placed on class's property declaration now make sense in the overridden
-      // property.
-      if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
-        if (!classExtPropertyAttr ||
-            (classExtPropertyAttr & 
-              (ObjCDeclSpec::DQ_PR_readwrite|
-               ObjCDeclSpec::DQ_PR_assign |
-               ObjCDeclSpec::DQ_PR_unsafe_unretained |
-               ObjCDeclSpec::DQ_PR_copy |
-               ObjCDeclSpec::DQ_PR_retain |
-               ObjCDeclSpec::DQ_PR_strong)))
-          continue;
-        warn = true;
-        break;
-      }
-    }
-  }
-  if (warn) {
-    unsigned setterAttrs = (ObjCDeclSpec::DQ_PR_assign |
-                            ObjCDeclSpec::DQ_PR_unsafe_unretained |
-                            ObjCDeclSpec::DQ_PR_copy |
-                            ObjCDeclSpec::DQ_PR_retain |
-                            ObjCDeclSpec::DQ_PR_strong);
-    if (Attributes & setterAttrs) {
-      const char * which =     
-      (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
-      "assign" :
-      (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
-      "unsafe_unretained" :
-      (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
-      "copy" : 
-      (Attributes & ObjCDeclSpec::DQ_PR_retain) ?
-      "retain" : "strong";
-      
-      S.Diag(property->getLocation(), 
-             diag::warn_objc_property_attr_mutually_exclusive)
-      << "readonly" << which;
-    }
-  }
-  
-  
-}
-
 /// ActOnPropertyImplDecl - This routine performs semantic checks and
 /// builds the AST node for a property implementation declaration; declared
 /// as \@synthesize or \@dynamic.
@@ -942,8 +890,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope
     }
     if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
       DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property);
-    
-    DiagnoseClassAndClassExtPropertyMismatch(*this, IDecl, property);
         
   } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
     if (Synthesize) {
@@ -2055,55 +2001,30 @@ void Sema::CheckObjCPropertyAttributes(D
   // FIXME: Improve the reported location.
   if (!PDecl || PDecl->isInvalidDecl())
     return;
-
+  
+  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
+      (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
+    Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
+    << "readonly" << "readwrite";
+  
   ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
-  QualType PropertyTy = PropertyDecl->getType(); 
+  QualType PropertyTy = PropertyDecl->getType();
+  unsigned PropertyOwnership = getOwnershipRule(Attributes);
 
-  if (getLangOpts().ObjCAutoRefCount &&
-      (Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
-      PropertyTy->isObjCRetainableType()) {
-    // 'readonly' property with no obvious lifetime.
-    // its life time will be determined by its backing ivar.
-    unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained |
-                    ObjCDeclSpec::DQ_PR_copy |
-                    ObjCDeclSpec::DQ_PR_retain |
-                    ObjCDeclSpec::DQ_PR_strong |
-                    ObjCDeclSpec::DQ_PR_weak |
-                    ObjCDeclSpec::DQ_PR_assign);
-    if ((Attributes & rel) == 0)
+  if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
+    if (getLangOpts().ObjCAutoRefCount &&
+        PropertyTy->isObjCRetainableType() &&
+        !PropertyOwnership) {
+      // 'readonly' property with no obvious lifetime.
+      // its life time will be determined by its backing ivar.
       return;
-  }
-  
-  if (propertyInPrimaryClass) {
-    // we postpone most property diagnosis until class's implementation
-    // because, its readonly attribute may be overridden in its class 
-    // extensions making other attributes, which make no sense, to make sense.
-    if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
-        (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
-      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 
-        << "readonly" << "readwrite";
-  }
-  // readonly and readwrite/assign/retain/copy conflict.
-  else if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
-           (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
-                     ObjCDeclSpec::DQ_PR_assign |
-                     ObjCDeclSpec::DQ_PR_unsafe_unretained |
-                     ObjCDeclSpec::DQ_PR_copy |
-                     ObjCDeclSpec::DQ_PR_retain |
-                     ObjCDeclSpec::DQ_PR_strong))) {
-    const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
-                          "readwrite" :
-                         (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
-                          "assign" :
-                         (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
-                          "unsafe_unretained" :
-                         (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
-                          "copy" : "retain";
-
-    Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
-                 diag::err_objc_property_attr_mutually_exclusive :
-                 diag::warn_objc_property_attr_mutually_exclusive)
-      << "readonly" << which;
+    }
+    else if (PropertyOwnership) {
+      if (!getSourceManager().isInSystemHeader(Loc))
+        Diag(Loc, diag::warn_objc_property_attr_mutually_exclusive)
+          << "readonly" << NameOfOwnershipAttribute(Attributes);
+      return;
+    }
   }
 
   // Check for copy or retain on non-object types.

Modified: cfe/trunk/test/SemaObjC/overriding-property-in-class-extension.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/overriding-property-in-class-extension.m?rev=192115&r1=192114&r2=192115&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/overriding-property-in-class-extension.m (original)
+++ cfe/trunk/test/SemaObjC/overriding-property-in-class-extension.m Mon Oct  7 12:20:02 2013
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1  -fsyntax-only -verify -Weverything %s
-// expected-no-diagnostics
 // rdar://12103434
 
 @class NSString;
@@ -8,7 +7,7 @@
 
 @interface MyClass  : NSObject
 
- at property (nonatomic, copy, readonly) NSString* name;
+ at property (nonatomic, copy, readonly) NSString* name; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}}
 
 @end
 

Modified: cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension-1.m?rev=192115&r1=192114&r2=192115&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-in-class-extension-1.m (original)
+++ cfe/trunk/test/SemaObjC/property-in-class-extension-1.m Mon Oct  7 12:20:02 2013
@@ -8,19 +8,20 @@
 
 @property (nonatomic, readonly) NSString* addingMemoryModel;
 
- at property (nonatomic, copy, readonly) NSString* matchingMemoryModel;
+ at property (nonatomic, copy, readonly) NSString* matchingMemoryModel; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}}
 
- at property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel;
+ at property (nonatomic, retain, readonly) NSString* addingNoNewMemoryModel; // expected-warning {{property attributes 'readonly' and 'retain' are mutually exclusive}}
 
 @property (readonly) NSString* none;
 @property (readonly) NSString* none1;
 
- at property (assign, readonly) NSString* changeMemoryModel; // expected-note {{property declared here}}
+ at property (assign, readonly) NSString* changeMemoryModel; // expected-note {{property declared here}} \
+                                                          // expected-warning {{property attributes 'readonly' and 'assign' are mutually exclusive}}
 
 @property (readonly) __weak id weak_prop;
 @property (readonly) __weak id weak_prop1;
 
- at property (assign, readonly) NSString* assignProperty;
+ at property (assign, readonly) NSString* assignProperty; // expected-warning {{property attributes 'readonly' and 'assign' are mutually exclusive}}
 
 @property (readonly) NSString* readonlyProp;
 

Modified: cfe/trunk/test/SemaObjC/tentative-property-decl.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/tentative-property-decl.m?rev=192115&r1=192114&r2=192115&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/tentative-property-decl.m (original)
+++ cfe/trunk/test/SemaObjC/tentative-property-decl.m Mon Oct  7 12:20:02 2013
@@ -14,7 +14,7 @@
 @class NSString;
 
 @interface MyClass : Super
- at property(nonatomic, copy, readonly) NSString *prop;
+ at property(nonatomic, copy, readonly) NSString *prop; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}}
 @property(nonatomic, copy, readonly) id warnProp; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}}
 @end
 
@@ -29,7 +29,7 @@
 
 
 @protocol P
- at property(nonatomic, copy, readonly) NSString *prop;
+ at property(nonatomic, copy, readonly) NSString *prop; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}}
 @property(nonatomic, copy, readonly) id warnProp; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}}
 @end
 





More information about the cfe-commits mailing list