r226339 - Suggest objc_method_family(none) for a property named -newFoo or similar.

Jordan Rose jordan_rose at apple.com
Fri Jan 16 15:04:32 PST 2015


Author: jrose
Date: Fri Jan 16 17:04:31 2015
New Revision: 226339

URL: http://llvm.org/viewvc/llvm-project?rev=226339&view=rev
Log:
Suggest objc_method_family(none) for a property named -newFoo or similar.

As mentioned in the previous commit, if a property (declared with @property)
has a name that matches a special Objective-C method family, the getter picks
up that family despite being declared by the property. The most correct way
to solve this problem is to add the 'objc_method_family' attribute to the
getter with an argument of 'none', which unfortunately requires an explicit
declaration of the getter.

This commit adds a note to the existing error (ARC) or warning (MRR) for
such a poorly-named property that suggests the solution; if there's already
a declaration of the getter, it even includes a fix-it.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/test/SemaObjC/arc-decls.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=226339&r1=226338&r2=226339&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jan 16 17:04:31 2015
@@ -797,6 +797,12 @@ def warn_cocoa_naming_owned_rule : Warni
   "property follows Cocoa naming"
   " convention for returning 'owned' objects">,
   InGroup<DiagGroup<"objc-property-matches-cocoa-ownership-rule">>;
+def err_cocoa_naming_owned_rule : Error<
+  "property follows Cocoa naming"
+  " convention for returning 'owned' objects">;
+def note_cocoa_naming_declare_family : Note<
+  "explicitly declare getter %objcinstance0 with '%1' to return an 'unowned' "
+  "object">;
 def warn_auto_synthesizing_protocol_property :Warning<
   "auto property synthesis will not synthesize property %0"
   " declared in protocol %1">,
@@ -828,9 +834,6 @@ def warn_property_getter_owning_mismatch
 def error_property_setter_ambiguous_use : Error<
   "synthesized properties %0 and %1 both claim setter %2 -"
   " use of this setter will cause unexpected behavior">;
-def err_cocoa_naming_owned_rule : Error<
-  "property follows Cocoa naming"
-  " convention for returning 'owned' objects">;
 def warn_default_atomic_custom_getter_setter : Warning<
   "atomic by default property %0 has a user defined %select{getter|setter}1 "
   "(property should be marked 'atomic' if this is intended)">,

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=226339&r1=226338&r2=226339&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Fri Jan 16 17:04:31 2015
@@ -19,6 +19,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Initialization.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallString.h"
@@ -1854,6 +1855,39 @@ void Sema::DiagnoseOwningPropertyGetterS
           Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
         else
           Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
+
+        // Look for a getter explicitly declared alongside the property.
+        // If we find one, use its location for the note.
+        SourceLocation noteLoc = PD->getLocation();
+        SourceLocation fixItLoc;
+        for (auto *getterRedecl : method->redecls()) {
+          if (getterRedecl->isImplicit())
+            continue;
+          if (getterRedecl->getDeclContext() != PD->getDeclContext())
+            continue;
+          noteLoc = getterRedecl->getLocation();
+          fixItLoc = getterRedecl->getLocEnd();
+        }
+
+        Preprocessor &PP = getPreprocessor();
+        TokenValue tokens[] = {
+          tok::kw___attribute, tok::l_paren, tok::l_paren,
+          PP.getIdentifierInfo("objc_method_family"), tok::l_paren,
+          PP.getIdentifierInfo("none"), tok::r_paren,
+          tok::r_paren, tok::r_paren
+        };
+        StringRef spelling = "__attribute__((objc_method_family(none)))";
+        StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens);
+        if (!macroName.empty())
+          spelling = macroName;
+
+        auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family)
+            << method->getDeclName() << spelling;
+        if (fixItLoc.isValid()) {
+          SmallString<64> fixItText(" ");
+          fixItText += spelling;
+          noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText);
+        }
       }
     }
   }

Modified: cfe/trunk/test/SemaObjC/arc-decls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-decls.m?rev=226339&r1=226338&r2=226339&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-decls.m (original)
+++ cfe/trunk/test/SemaObjC/arc-decls.m Fri Jan 16 17:04:31 2015
@@ -54,13 +54,13 @@ void func()
 // rdar://15757510
 
 @interface J
- at property (retain) id newFoo; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
- at property (strong) id copyBar;  // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
- at property (copy) id allocBaz; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
+ at property (retain) id newFoo; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note{{explicitly declare getter '-newFoo' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
+ at property (strong) id copyBar;  // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note{{explicitly declare getter '-copyBar' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
+ at property (copy) id allocBaz; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note{{explicitly declare getter '-allocBaz' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
 @property (copy, nonatomic) id new;
- at property (retain) id newDFoo; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
- at property (strong) id copyDBar; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
- at property (copy) id allocDBaz; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
+ at property (retain) id newDFoo; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note{{explicitly declare getter '-newDFoo' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
+ at property (strong) id copyDBar; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note{{explicitly declare getter '-copyDBar' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
+ at property (copy) id allocDBaz; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note{{explicitly declare getter '-allocDBaz' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
 @end
 
 @implementation J
@@ -76,6 +76,29 @@ void func()
 @end
 
 
+ at interface MethodFamilyDiags
+ at property (retain) id newFoo; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
+- (id)newFoo; // expected-note {{explicitly declare getter '-newFoo' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
+
+#define OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
+- (id)newBar; // expected-note {{explicitly declare getter '-newBar' with 'OBJC_METHOD_FAMILY_NONE' to return an 'unowned' object}}
+ at property (retain) id newBar; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}}
+
+ at property (retain) id newBaz; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note {{explicitly declare getter '-newBaz' with 'OBJC_METHOD_FAMILY_NONE' to return an 'unowned' object}}
+#undef OBJC_METHOD_FAMILY_NONE
+
+ at property (retain, readonly) id newGarply; // expected-error {{property follows Cocoa naming convention for returning 'owned' objects}} expected-note {{explicitly declare getter '-newGarply' with '__attribute__((objc_method_family(none)))' to return an 'unowned' object}}
+ at end
+
+ at interface MethodFamilyDiags (Redeclarations)
+- (id)newGarply; // no note here
+ at end
+
+ at implementation MethodFamilyDiags
+ at synthesize newGarply;
+ at end
+
+
 // rdar://10187884
 @interface Super
 - (void)bar:(id)b; // expected-note {{parameter declared here}}





More information about the cfe-commits mailing list