]> granicus.if.org Git - clang/commitdiff
objective-c: Warn if default synthesizing readonly IBOutlet properties
authorFariborz Jahanian <fjahanian@apple.com>
Sat, 19 May 2012 18:17:17 +0000 (18:17 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Sat, 19 May 2012 18:17:17 +0000 (18:17 +0000)
and provide a 'fixit' to change 'readonly' to 'readwrite'. 'fixit'
part needs little more work. // rdar://11448209

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaObjCProperty.cpp
test/SemaObjC/iboutlet.m [new file with mode: 0644]

index 8b76ccb1343eddb07380afb853bb8544b1c93f37..b3ae3aa4cfda8316764bb3f62e84ab6caa34963d 100644 (file)
@@ -711,6 +711,12 @@ def warn_undeclared_selector : Warning<
   "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
 def warn_implicit_atomic_property : Warning<
   "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore;
+def note_auto_readonly_iboutlet_fixup_suggest : Note<
+  "readonly IBOutlet property should be changed to be readwrite">;
+def warn_auto_readonly_iboutlet_property : Warning<
+  "readonly IBOutlet property when auto-synthesized may "
+  "not work correctly with 'nib' loader">,
+  InGroup<DiagGroup<"readonly-iboutlet-property">>;
 def warn_auto_implicit_atomic_property : Warning<
   "property is assumed atomic when auto-synthesizing the property">, 
   InGroup<ImplicitAtomic>, DefaultIgnore;
index f42259c68694e386899ace8c006d9b0acac3aa34..44e50852a55c9467bf2d060710130a4f0d221a48 100644 (file)
@@ -200,6 +200,53 @@ makePropertyAttributesAsWritten(unsigned Attributes) {
   return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten;
 }
 
+static std::string getPropertyAttributeString(const ObjCPropertyDecl *property,
+                                              unsigned Attributes) {
+  std::string attr;
+  if (!Attributes)
+    return attr;
+  attr = "(";
+  bool first = true;
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_readonly)
+    {attr +=  !first ? ", readonly" : "readonly"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)
+    {attr +=  !first ? ", readwrite" : "readwrite"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_getter)
+    {
+      if (!first)
+        attr += ", ";
+      attr += "getter=";
+      attr += property->getGetterName().getAsString();
+      first = false;
+   }
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_setter)
+    {
+      if (!first)
+        attr += ", ";
+      attr += "setter=";
+      attr += property->getSetterName().getAsString();
+      first = false;
+   }
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_assign)
+    {attr +=  !first ? ", assign" : "assign"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_retain)
+    {attr +=  !first ? ", retain" : "retain"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_strong)
+    {attr +=  !first ? ", strong" : "strong"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_weak)
+    {attr +=  !first ? ", weak" : "weak"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
+    {attr +=  !first ? ", copy" : "copy"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
+    {attr +=  !first ? ", unsafe_unretained" : "unsafe_unretained"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
+    {attr +=  !first ? ", nonatomic" : "nonatomic"; first = false; } 
+  if (Attributes & ObjCPropertyDecl::OBJC_PR_atomic)
+    {attr +=  !first ? ", atomic" : "atomic"; first = false; } 
+  attr += ")";
+  return attr;
+}
+
 Decl *
 Sema::HandlePropertyInClassExtension(Scope *S,
                                      SourceLocation AtLoc,
@@ -628,6 +675,26 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
         return 0;
       }
     }
+    
+    if (Synthesize&&
+        (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) &&
+        property->hasAttr<IBOutletAttr>() &&
+        !AtLoc.isValid()) {
+      unsigned rwPIKind = (PIkind | ObjCPropertyDecl::OBJC_PR_readwrite);
+      rwPIKind &= (~ObjCPropertyDecl::OBJC_PR_readonly);
+      Diag(IC->getLocation(), diag::warn_auto_readonly_iboutlet_property);
+      Diag(property->getLocation(), diag::note_property_declare);
+      // FIXME. End location must be that of closing ')' which is currently
+      // unavailable. Need to add it.
+      SourceLocation endLoc =
+              property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+      SourceRange PropSourceRange(property->getLParenLoc(), endLoc);
+      Diag(property->getLocation(), 
+           diag::note_auto_readonly_iboutlet_fixup_suggest) <<
+      FixItHint::CreateReplacement(PropSourceRange, getPropertyAttributeString(property,
+                                                                               rwPIKind));
+    }
+        
   } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
     if (Synthesize) {
       Diag(AtLoc, diag::error_synthesize_category_decl);
diff --git a/test/SemaObjC/iboutlet.m b/test/SemaObjC/iboutlet.m
new file mode 100644 (file)
index 0000000..13e5d53
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-default-synthesize-properties  -verify %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -fobjc-default-synthesize-properties  -verify %s
+// rdar://11448209
+
+@class NSView;
+
+#define IBOutlet __attribute__((iboutlet))
+
+@interface I
+@property (getter = MyGetter, readonly, assign) IBOutlet NSView *myView; // expected-note {{property declared here}} \
+                                                       // expected-note {{readonly IBOutlet property should be changed to be readwrite}}
+@end
+
+@implementation I // expected-warning {{readonly IBOutlet property when auto-synthesized may not work correctly with 'nib' loader}}
+@end