[PATCH] D60920: [ASTMatchers] Introduce Objective-C matchers `isClassMessage`, `isClassMethod`, and `isInstanceMethod`

2019-04-19 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: benhamilton, klimek.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

isClassMessage is an equivalent to isInstanceMessage for ObjCMessageExpr, but 
matches message expressions to classes.

isClassMethod and isInstanceMethod check whether a method declaration (or 
definition) is for a class method or instance method (respectively).


Repository:
  rC Clang

https://reviews.llvm.org/D60920

Files:
  clang/docs/LibASTMatchersReference.html
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -454,6 +454,20 @@
   objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x";
 }
 
+TEST(Matcher, isClassMessage) {
+  EXPECT_TRUE(matchesObjC(
+  "@interface NSString +(NSString *) stringWithFormat; @end "
+  "void f() { [NSString stringWithFormat]; }",
+  objcMessageExpr(isClassMessage(;
+
+  EXPECT_FALSE(matchesObjC(
+  "@interface NSString @end "
+  "void f(NSString *x) {"
+  "[x containsString];"
+  "}",
+  objcMessageExpr(isClassMessage(;
+}
+
 TEST(Matcher, isInstanceMessage) {
   EXPECT_TRUE(matchesObjC(
   "@interface NSString @end "
@@ -469,6 +483,46 @@
 
 }
 
+TEST(Matcher, isClassMethod) {
+  EXPECT_TRUE(matchesObjC(
+"@interface Bar + (void)bar; @end",
+objcMethodDecl(isClassMethod(;
+
+  EXPECT_TRUE(matchesObjC(
+"@interface Bar @end"
+"@implementation Bar + (void)bar {} @end",
+objcMethodDecl(isClassMethod(;
+
+  EXPECT_FALSE(matchesObjC(
+"@interface Foo - (void)foo; @end",
+objcMethodDecl(isClassMethod(;
+
+  EXPECT_FALSE(matchesObjC(
+"@interface Foo @end "
+"@implementation Foo - (void)foo {} @end",
+objcMethodDecl(isClassMethod(;
+}
+
+TEST(Matcher, isInstanceMethod) {
+  EXPECT_TRUE(matchesObjC(
+"@interface Foo - (void)foo; @end",
+objcMethodDecl(isInstanceMethod(;
+
+  EXPECT_TRUE(matchesObjC(
+"@interface Foo @end "
+"@implementation Foo - (void)foo {} @end",
+objcMethodDecl(isInstanceMethod(;
+
+  EXPECT_FALSE(matchesObjC(
+"@interface Bar + (void)bar; @end",
+objcMethodDecl(isInstanceMethod(;
+
+  EXPECT_FALSE(matchesObjC(
+"@interface Bar @end"
+"@implementation Bar + (void)bar {} @end",
+objcMethodDecl(isInstanceMethod(;
+}
+
 TEST(MatcherCXXMemberCallExpr, On) {
   auto Snippet1 = R"cc(
 struct Y {
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -344,6 +344,8 @@
   REGISTER_MATCHER(isBitField);
   REGISTER_MATCHER(isCatchAll);
   REGISTER_MATCHER(isClass);
+  REGISTER_MATCHER(isClassMessage);
+  REGISTER_MATCHER(isClassMethod);
   REGISTER_MATCHER(isConst);
   REGISTER_MATCHER(isConstQualified);
   REGISTER_MATCHER(isConstexpr);
@@ -367,6 +369,7 @@
   REGISTER_MATCHER(isInTemplateInstantiation);
   REGISTER_MATCHER(isInline);
   REGISTER_MATCHER(isInstanceMessage);
+  REGISTER_MATCHER(isInstanceMethod);
   REGISTER_MATCHER(isInstantiated);
   REGISTER_MATCHER(isInstantiationDependent);
   REGISTER_MATCHER(isInteger);
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2938,10 +2938,59 @@
   return InnerMatcher.matches(TypeDecl, Finder, Builder);
 }
 
+/// Returns true when the Objective-C method declaration is a class method.
+///
+/// Example
+/// matcher = objcMethodDecl(isClassMethod())
+/// matches
+/// \code
+/// @interface I + (void)foo; @end
+/// \endcode
+/// but not
+/// \code
+/// @interface I - (void)bar; @end
+/// \endcode
+AST_MATCHER(ObjCMethodDecl, isClassMethod) {
+  return Node.isClassMethod();
+}
+
+/// Returns true when the Objective-C method declaration is an instance method.
+///
+/// Example
+/// matcher = objcMethodDecl(isInstanceMethod())
+/// matches
+/// \code
+/// @interface I - (void)bar; @end
+/// \endcode
+/// but not
+/// \code
+/// @interface I + (void)foo; @end
+/// \endcode
+AST_MATCHER(ObjCMethodDecl, isInstanceMethod) {
+  return Node.isInstanceMethod();
+}
+
+/// Returns true when the Objective-C message is sent to a class.
+///
+/// Example
+/// matcher = objcMessageExpr(isClassMessage())
+/// matches
+/// \code
+///   [NSString stringWithFormat:@"format"];
+/// \endcode
+/// but not
+/// \code
+///   NSString *x = @"hello";
+///   [x containsString:@"h"];
+/// \endcode
+AST_MATCHER(ObjCMessageExpr, isClassMessage) {

[PATCH] D60920: [ASTMatchers] Introduce Objective-C matchers `isClassMessage`, `isClassMethod`, and `isInstanceMethod`

2019-04-22 Thread Michael Wyman via Phabricator via cfe-commits
mwyman accepted this revision.
mwyman added a comment.

Thanks. I don't believe I have commit access, so I'll need someone to commit 
this to trunk.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60920/new/

https://reviews.llvm.org/D60920



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61350: New clang-tidy check calling out uses of +new in Objective-C code

2019-04-30 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: benhamilton, hokein.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Google's Objective-C style guide forbids calling or overriding +new to 
instantiate objects. This check warns on violations.

Style guide reference: 
https://google.github.io/styleguide/objcguide.html#do-not-use-new


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+=
+
+Finds uses of +new to create objects in Objective-C files.
+
+The Google Objective-C style guide forbids calling +new or overriding it in
+class implementations, preferring +alloc and -init methods to instantiate
+objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use +alloc/-init or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+The corresponding style guide rule:
+https://google.github.io/styleguide/objcguide.html#do-not-use-new
Index: clang-tools-extra/docs/ReleaseNotes.rst
==

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-01 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 197660.
mwyman marked 6 inline comments as done.
mwyman added a comment.

Fixes per review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,28 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Checks for calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+The corresponding style guide rule:
+https://google.github.io/styleguide/objcguide.html#do-not-use-new
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -101,6 +101,12 

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-01 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 197681.
mwyman marked 7 inline comments as done.
mwyman added a comment.

Updated per review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Checks for calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do Not Use +new
+`_.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ cla

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 198495.
mwyman added a comment.

Updated to address code review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Checks for calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do Not Use +new
+`_.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNo

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 3 inline comments as done.
mwyman added inline comments.



Comment at: clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp:76-77
+  // Some classes should use standard factory methods instead of alloc/init.
+  const std::map ClassToFactoryMethodMap = {
+  {"NSDate", "date"}, {"NSNull", "null"}};
+  const auto FoundClassFactory = ClassToFactoryMethodMap.find(Receiver);

aaron.ballman wrote:
> Should this be configurable, or will users not need to control the behavior 
> here?
For now I think there is only this handful of Foundation types commonly created 
only with the factory methods; I'm not sure it makes a huge amount of sense to 
open it for configuration at this time.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 198503.
mwyman marked an inline comment as done.
mwyman added a comment.

Update comments/doc based on feedback.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Finds calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do Not Use +new
+`_.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
++

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-08 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added inline comments.



Comment at: clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp:112
+  Result.Nodes.getNodeAs("new_call")) {
+// Don't warn if the call expression originates from a macro expansion.
+if (isMessageExpressionInsideMacro(CallExpr))

stephanemoore wrote:
> If the message expression is within a macro expansion, maybe we should emit 
> the diagnostic without the fixit?
I'm leery of emitting a warning in a case where the code may not originate from 
the code in question. Maybe if the macro is defined in the same source file, 
but I think perhaps that could be a follow-up.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-08 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 198702.
mwyman marked 2 inline comments as done.
mwyman added a comment.

Update for review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface NSProxy  // Root class with no -init method.
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+@interface ProxyFoo : NSProxy
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+
+  ProxyFoo *proxy = [ProxyFoo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Finds calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do No

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-10 Thread Michael Wyman via Phabricator via cfe-commits
mwyman accepted this revision.
mwyman added a comment.

I don't have commit access, so if somebody could submit them that would be 
wonderful!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 199338.
mwyman added a comment.

Update for comments


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface NSProxy  // Root class with no -init method.
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+@interface ProxyFoo : NSProxy
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+
+  ProxyFoo *proxy = [ProxyFoo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Finds calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do Not Use +new
+

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 199341.
mwyman added a comment.

Added +new declaration for ProxyFoo.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface NSProxy  // Root class with no -init method.
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+@interface ProxyFoo : NSProxy
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+
+  ProxyFoo *proxy = [ProxyFoo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Finds calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do Not Use +new
+

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-14 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 199375.
mwyman added a comment.

Bah, previous changes not caught in Git commit; switching back and forth 
between Git/Mercurial makes for some mix-ups, I guess.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,80 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface NSProxy  // Root class with no -init method.
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+@interface ProxyFoo : NSProxy
++ (instancetype)new;
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+
+  ProxyFoo *proxy = [ProxyFoo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -133,6 +133,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Finds calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] i

[PATCH] D61350: [clang-tidy] New check calling out uses of +new in Objective-C code

2019-05-22 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 200824.
mwyman added a comment.

Syncing code with HEAD


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61350/new/

https://reviews.llvm.org/D61350

Files:
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp
  clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h
  clang-tools-extra/clang-tidy/google/CMakeLists.txt
  clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m

Index: clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m
@@ -0,0 +1,80 @@
+// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
+
+@interface NSObject
++ (instancetype)new;
++ (instancetype)alloc;
+- (instancetype)init;
+@end
+
+@interface NSProxy  // Root class with no -init method.
+@end
+
+// NSDate provides a specific factory method.
+@interface NSDate : NSObject
++ (instancetype)date;
+@end
+
+// For testing behavior with Objective-C Generics.
+@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
+@end
+
+@class NSString;
+
+#define ALLOCATE_OBJECT(_Type) [_Type new]
+
+void CheckSpecificInitRecommendations(void) {
+  NSObject *object = [NSObject new];
+  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSObject alloc] init];
+
+  NSDate *correctDate = [NSDate date];
+  NSDate *incorrectDate = [NSDate new];
+  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSDate date];
+
+  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
+
+  NSMutableDictionary *dict = [NSMutableDictionary new];
+  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+  // CHECK-FIXES: [NSMutableDictionary alloc] init];
+}
+
+@interface Foo : NSObject
++ (instancetype)new; // Declare again to suppress warning.
+- (instancetype)initWithInt:(int)anInt;
+- (instancetype)init __attribute__((unavailable));
+
+- (id)new;
+@end
+
+@interface Baz : Foo // Check unavailable -init through inheritance.
+@end
+
+@interface ProxyFoo : NSProxy
++ (instancetype)new;
+@end
+
+void CallNewWhenInitUnavailable(void) {
+  Foo *foo = [Foo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  Baz *baz = [Baz new];
+  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+
+  // Instance method -new calls may be weird, but are not strictly forbidden.
+  Foo *bar = [[Foo alloc] initWithInt:4];
+  [bar new];
+
+  ProxyFoo *proxy = [ProxyFoo new];
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
+}
+
+@interface HasNewOverride : NSObject
+@end
+
+@implementation HasNewOverride
++ (instancetype)new {
+  return [[self alloc] init];
+}
+// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -135,6 +135,7 @@
google-default-arguments
google-explicit-constructor
google-global-names-in-headers
+   google-objc-avoid-nsobject-new
google-objc-avoid-throwing-exception
google-objc-function-naming
google-objc-global-variable-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - google-objc-avoid-nsobject-new
+
+google-objc-avoid-nsobject-new
+==
+
+Finds calls to ``+new`` or overrides of it, which are prohibited by the
+Google Objective-C style guide.
+
+The Google Objective-C style guide forbids calling ``+new`` or overriding it in
+class implementations, preferring ``+alloc`` and ``-init`` methods to
+instantiate objects.
+
+An example:
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate new];
+  Foo *bar = [Foo new];
+
+Instead, code should use ``+alloc``/``-init`` or class factory methods.
+
+.. code-block:: objc
+
+  NSDate *now = [NSDate date];
+  Foo *bar = [[Foo alloc] init];
+
+This check corresponds to the Google Objective-C Style Guide rule
+`Do Not Use +new
+

[PATCH] D67567: New ClangTidy checks to warn about misusing dispatch_once_t

2019-09-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: benhamilton, hokein, stephanemoore.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Adds two new ClangTidy checks:

- misc-dispatch-once-assignment: warns about assignment to a dispatch_once_t 
variable. In code reviews I've encountered enough attempts to "reset" a 
dispatch_once.
- misc-dispatch-once-nonstatic: warns about dispatch_once_t variables not in 
static or global storage. This catches a missing static for local variables in 
e.g. singleton initialization behavior, and also warns on storing 
dispatch_once_t values in Objective-C instance variables. C/C++ struct/class 
instances may potentially live in static/global storage, and are ignored for 
this check.

The osx.API static analysis checker can find the non-static storage use of 
dispatch_once_t; I thought it useful to also catch these issues in clang-tidy 
when possible.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D67567

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/DispatchOnceAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/misc/DispatchOnceAssignmentCheck.h
  clang-tools-extra/clang-tidy/misc/DispatchOnceNonstaticCheck.cpp
  clang-tools-extra/clang-tidy/misc/DispatchOnceNonstaticCheck.h
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-assignment.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-nonstatic.rst
  clang-tools-extra/test/clang-tidy/misc-dispatch-once-assignment.cpp
  clang-tools-extra/test/clang-tidy/misc-dispatch-once-nonstatic.mm

Index: clang-tools-extra/test/clang-tidy/misc-dispatch-once-nonstatic.mm
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/misc-dispatch-once-nonstatic.mm
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-dispatch-once-nonstatic %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+
+void bad_dispatch_once(dispatch_once_t once, void(^block)(void)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: dispatch_once_ts must have static or global storage duration; function parameters should be pointer references [misc-dispatch-once-nonstatic]
+
+// file-scope dispatch_once_ts have static storage duration.
+dispatch_once_t global_once;
+static dispatch_once_t file_static_once;
+namespace {
+dispatch_once_t anonymous_once;
+} // end anonymous namespace
+
+int Correct(void) {
+  static int value;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+int Incorrect(void) {
+  static int value;
+  dispatch_once_t once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration [misc-dispatch-once-nonstatic]
+  // CHECK-FIXES: static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+struct OnceStruct {
+  static dispatch_once_t staticOnce; // Allowed
+  int value;
+  dispatch_once_t once;  // Allowed (at this time)
+};
+
+@interface MyObject {
+  dispatch_once_t _once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration and cannot be Objective-C instance variables [misc-dispatch-once-nonstatic]
+}
+@end
Index: clang-tools-extra/test/clang-tidy/misc-dispatch-once-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/misc-dispatch-once-assignment.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s misc-dispatch-once-assignment %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+static dispatch_once_t onceToken;
+
+void DoOnce(void(^block)(void)) {
+  dispatch_once(&onceToken, block);
+}
+
+void ResetOnce() {
+  onceToken = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not assign to dispatch_once_t variables [misc-dispatch-once-assignment]
+}
Index: clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-nonstatic.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-nonstatic.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - misc-dispatch-once-nonstatic
+
+misc-dispatch-once-nonstatic
+
+
+Finds declarations of ``dispatch_once_t`` variables without static or global
+storage. The behavior of using ``dispatch_once_t`` predicates with automatic
+or dynamic storage is undefined by libdispatch, and should be avoided.
+
+It is a common paradigm to have functions initialize internal static or global
+data once when the function runs, but programmers have been known to miss the
+static on the 

[PATCH] D67567: New ClangTidy checks to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 220169.
mwyman retitled this revision from "New ClangTidy checks to warn about misusing 
dispatch_once_t" to "New ClangTidy checks to warn when storing dispatch_once_t 
in non-static, non-global storage".
mwyman added a comment.

Moved the assignment check to a separate review.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/DispatchOnceNonstaticCheck.cpp
  clang-tools-extra/clang-tidy/misc/DispatchOnceNonstaticCheck.h
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-nonstatic.rst
  clang-tools-extra/test/clang-tidy/misc-dispatch-once-nonstatic.mm

Index: clang-tools-extra/test/clang-tidy/misc-dispatch-once-nonstatic.mm
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/misc-dispatch-once-nonstatic.mm
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s misc-dispatch-once-nonstatic %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+
+void bad_dispatch_once(dispatch_once_t once, void(^block)(void)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: dispatch_once_ts must have static or global storage duration; function parameters should be pointer references [misc-dispatch-once-nonstatic]
+
+// file-scope dispatch_once_ts have static storage duration.
+dispatch_once_t global_once;
+static dispatch_once_t file_static_once;
+namespace {
+dispatch_once_t anonymous_once;
+} // end anonymous namespace
+
+int Correct(void) {
+  static int value;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+int Incorrect(void) {
+  static int value;
+  dispatch_once_t once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration [misc-dispatch-once-nonstatic]
+  // CHECK-FIXES: static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+struct OnceStruct {
+  static dispatch_once_t staticOnce; // Allowed
+  int value;
+  dispatch_once_t once;  // Allowed (at this time)
+};
+
+@interface MyObject {
+  dispatch_once_t _once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration and cannot be Objective-C instance variables [misc-dispatch-once-nonstatic]
+}
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-nonstatic.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-nonstatic.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - misc-dispatch-once-nonstatic
+
+misc-dispatch-once-nonstatic
+
+
+Finds declarations of ``dispatch_once_t`` variables without static or global
+storage. The behavior of using ``dispatch_once_t`` predicates with automatic
+or dynamic storage is undefined by libdispatch, and should be avoided.
+
+It is a common paradigm to have functions initialize internal static or global
+data once when the function runs, but programmers have been known to miss the
+static on the ``dispatch_once_t`` predicate, leading to an uninitialized flag
+value at the mercy of the stack.
+
+Programmers have also been known to make ``dispatch_once_t``s be members of
+structs/classes, with the intent to lazily perform some expensive struct or
+class member initialization only once; however, this violates the libdispatch
+requirements.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -278,6 +278,7 @@
llvm-prefer-register-over-unsigned
llvm-twine-local
misc-definitions-in-headers
+   misc-dispatch-once-nonstatic
misc-misplaced-const
misc-new-delete-overloads
misc-non-copyable-objects
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -73,6 +73,12 @@
   Finds instances where variables with static storage are initialized
   dynamically in header files.
 
+- New :doc:`misc-dispatch-once-nonstatic
+  ` check.
+
+  Finds instances of ``dispatch_once_t`` variables not having static or global
+  storage.
+
 - New :doc:`linuxkernel-must-use-errs
   ` check.
 
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/m

[PATCH] D67567: New ClangTidy check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D67567#1669866 , @lebedev.ri wrote:

> 1. Please split each check into separate review.
> 2. Is `dispatch_once_t` OSX-specific thing? Should those checks be in `osx` 
> module?




1. I split the review.
2. I don't see an `osx` module—am I somehow missing seeing it? 
`dispatch_once_t` is something from `libdispatch`which is an Apple-created API, 
but is OSS and available outside Apple. It's also a C API, which is why I 
didn't feel `objc` was an appropriate module either. I'm open to a better home 
module for this check, it's just not clear to me where that might be.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67578: New ClangTidy check to warn when writing to a dispatch_once_t variable.

2019-09-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: benhamilton, hokein, stephanemoore.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Libdispatch documentation specifies that dispatch_once_ts must never have been 
non-zero, and assigning to them violates this.

Currently adding this to the `misc` module. Per discussion in 
https://reviews.llvm.org/D67567, perhaps this should be moved to a new, more 
specific module.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D67578

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/DispatchOnceAssignmentCheck.cpp
  clang-tools-extra/clang-tidy/misc/DispatchOnceAssignmentCheck.h
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-assignment.rst
  clang-tools-extra/test/clang-tidy/misc-dispatch-once-assignment.cpp

Index: clang-tools-extra/test/clang-tidy/misc-dispatch-once-assignment.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/misc-dispatch-once-assignment.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy %s misc-dispatch-once-assignment %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+static dispatch_once_t onceToken;
+
+void DoOnce(void(^block)(void)) {
+  dispatch_once(&onceToken, block);
+}
+
+void ResetOnce() {
+  onceToken = 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not assign to dispatch_once_t variables [misc-dispatch-once-assignment]
+}
Index: clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-assignment.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-dispatch-once-assignment.rst
@@ -0,0 +1,9 @@
+.. title:: clang-tidy - misc-dispatch-once-assignment
+
+misc-dispatch-once-assignment
+=
+
+Finds assignments to variables of type ``dispatch_once_t`` and warns to avoid
+assigning to them. Libdispatch intends that such writes should be guarded
+and making such direct writes may potentially violate the run-once protections
+intended by the library.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -278,6 +278,7 @@
llvm-prefer-register-over-unsigned
llvm-twine-local
misc-definitions-in-headers
+   misc-dispatch-once-assignment
misc-misplaced-const
misc-new-delete-overloads
misc-non-copyable-objects
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -73,6 +73,11 @@
   Finds instances where variables with static storage are initialized
   dynamically in header files.
 
+- New :doc:`misc-dispatch-once-assignment
+  ` check.
+
+  Finds instances of explicitly writing to ``dispatch_once_t`` variables.
+
 - New :doc:`linuxkernel-must-use-errs
   ` check.
 
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "DefinitionsInHeadersCheck.h"
+#include "DispatchOnceAssignmentCheck.h"
 #include "MisplacedConstCheck.h"
 #include "NewDeleteOverloadsCheck.h"
 #include "NonCopyableObjects.h"
@@ -32,6 +33,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck(
 "misc-definitions-in-headers");
+CheckFactories.registerCheck(
+"misc-dispatch-once-assignment");
 CheckFactories.registerCheck("misc-misplaced-const");
 CheckFactories.registerCheck(
 "misc-new-delete-overloads");
Index: clang-tools-extra/clang-tidy/misc/DispatchOnceAssignmentCheck.h
===
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/DispatchOnceAssignmentCheck.h
@@ -0,0 +1,36 @@
+//===--- DispatchOnceAssignmentCheck.h - clang-tidy -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DISPATCHONCEASSIGNMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_DISPATCHONCEASSIGNMENTCHEC

[PATCH] D67567: New ClangTidy check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-13 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D67567#1670035 , @lebedev.ri wrote:

> In D67567#1670017 , @mwyman wrote:
>
> > In D67567#1669866 , @lebedev.ri 
> > wrote:
> >
> > > 1. Please split each check into separate review.
> > > 2. Is `dispatch_once_t` OSX-specific thing? Should those checks be in 
> > > `osx` module?
> >
> >
> >
> >
> > 1. I split the review.
>
>
>
>
> > 2. I don't see an `osx` module—am I somehow missing seeing it?
>
> One can be added.
>
> > `dispatch_once_t` is something from `libdispatch`which is an Apple-created 
> > API, but is OSS and available outside Apple. It's also a C API, which is 
> > why I didn't feel `objc` was an appropriate module either. I'm open to a 
> > better home module for this check, it's just not clear to me where that 
> > might be.
>
> No opinion on my question, just thought it should be asked,


As Ben commented, I don't feel this should be in an `osx` module, as 
libdispatch is highly used on iOS and other Apple platforms. I know it's 
available elsewhere, but it may be so seldom used that I think a `darwin`module 
might be reasonable. I looked at the process for creating a new module, and can 
do that if we'd like, but should that be part of this same review?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-16 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D67567#1670264 , @NoQ wrote:

> FTR, we already have a similar Static Analyzer check, eg.:
>  
> https://github.com/llvm-mirror/clang/blob/release_80/test/Analysis/dispatch-once.m#L15
>  
> https://github.com/llvm-mirror/clang/blob/release_80/test/Analysis/dispatch-once.m#L26
>
> Your check is a bit more aggressive but i don't see why didn't we do it that 
> way in the first place :) Though you won't be able to warn on the heap 
> example.


The Static Analyzer check was pointed out by a colleague; unfortunately our 
build environment doesn't currently play nice with running the static analyzer 
(so many devs don't end up running it) but ClangTidy gets run as part of our 
code review process. Given libdispatch's documented requirements, it seemed 
reasonable to be aggressive with a ClangTidy check when we can reasonably 
identify non-static/global storage.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-16 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 220357.
mwyman edited the summary of this revision.
mwyman added a comment.
Herald added subscribers: usaxena95, kadircet, arphaman, jkorous.

Migrated check to new `darwin` module.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567

Files:
  clang-tools-extra/clang-tidy/CMakeLists.txt
  clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
  clang-tools-extra/clang-tidy/darwin/CMakeLists.txt
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.h
  clang-tools-extra/clang-tidy/plugin/CMakeLists.txt
  clang-tools-extra/clang-tidy/tool/CMakeLists.txt
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm

Index: clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s darwin-dispatch-once-nonstatic %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+
+void bad_dispatch_once(dispatch_once_t once, void(^block)(void)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: dispatch_once_ts must have static or global storage duration; function parameters should be pointer references [darwin-dispatch-once-nonstatic]
+
+// file-scope dispatch_once_ts have static storage duration.
+dispatch_once_t global_once;
+static dispatch_once_t file_static_once;
+namespace {
+dispatch_once_t anonymous_once;
+} // end anonymous namespace
+
+int Correct(void) {
+  static int value;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+int Incorrect(void) {
+  static int value;
+  dispatch_once_t once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+struct OnceStruct {
+  static dispatch_once_t staticOnce; // Allowed
+  int value;
+  dispatch_once_t once;  // Allowed (at this time)
+};
+
+@interface MyObject {
+  dispatch_once_t _once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration and cannot be Objective-C instance variables [darwin-dispatch-once-nonstatic]
+}
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -211,6 +211,7 @@
cppcoreguidelines-pro-type-vararg
cppcoreguidelines-slicing
cppcoreguidelines-special-member-functions
+   darwin-dispatch-once-nonstatic
fuchsia-default-arguments-calls
fuchsia-default-arguments-declarations
fuchsia-header-anon-namespaces (redirects to google-build-namespaces) 
Index: clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - darwin-dispatch-once-nonstatic
+
+darwin-dispatch-once-nonstatic
+==
+
+Finds declarations of ``dispatch_once_t`` variables without static or global
+storage. The behavior of using ``dispatch_once_t`` predicates with automatic
+or dynamic storage is undefined by libdispatch, and should be avoided.
+
+It is a common paradigm to have functions initialize internal static or global
+data once when the function runs, but programmers have been known to miss the
+static on the ``dispatch_once_t`` predicate, leading to an uninitialized flag
+value at the mercy of the stack.
+
+Programmers have also been known to make ``dispatch_once_t``s be members of
+structs/classes, with the intent to lazily perform some expensive struct or
+class member initialization only once; however, this violates the libdispatch
+requirements.
+
+See the discussion section of
+`Apple's dispatch_once documentation `_
+for more information.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -73,6 +73,12 @@
   Finds instances where variables with static storage are initialized
   dyn

[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-18 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 220751.
mwyman added a comment.

Addressed review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567

Files:
  clang-tools-extra/clang-tidy/CMakeLists.txt
  clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
  clang-tools-extra/clang-tidy/darwin/CMakeLists.txt
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.h
  clang-tools-extra/clang-tidy/plugin/CMakeLists.txt
  clang-tools-extra/clang-tidy/tool/CMakeLists.txt
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm

Index: clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy %s darwin-dispatch-once-nonstatic %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+
+void bad_dispatch_once(dispatch_once_t once, void(^block)(void)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: dispatch_once_ts must have static or global storage duration; function parameters should be pointer references [darwin-dispatch-once-nonstatic]
+
+// file-scope dispatch_once_ts have static storage duration.
+dispatch_once_t global_once;
+static dispatch_once_t file_static_once;
+namespace {
+dispatch_once_t anonymous_once;
+} // end anonymous namespace
+
+int Correct(void) {
+  static int value;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+int Incorrect(void) {
+  static int value;
+  dispatch_once_t once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+struct OnceStruct {
+  static dispatch_once_t staticOnce; // Allowed
+  int value;
+  dispatch_once_t once;  // Allowed (at this time)
+};
+
+@interface MyObject {
+  dispatch_once_t _once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration and cannot be Objective-C instance variables [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: dispatch_once_t _once;
+}
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -211,6 +211,7 @@
cppcoreguidelines-pro-type-vararg
cppcoreguidelines-slicing
cppcoreguidelines-special-member-functions
+   darwin-dispatch-once-nonstatic
fuchsia-default-arguments-calls
fuchsia-default-arguments-declarations
fuchsia-header-anon-namespaces (redirects to google-build-namespaces) 
Index: clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - darwin-dispatch-once-nonstatic
+
+darwin-dispatch-once-nonstatic
+==
+
+Finds declarations of ``dispatch_once_t`` variables without static or global
+storage. The behavior of using ``dispatch_once_t`` predicates with automatic
+or dynamic storage is undefined by libdispatch, and should be avoided.
+
+It is a common pattern to have functions initialize internal static or global
+data once when the function runs, but programmers have been known to miss the
+static on the ``dispatch_once_t`` predicate, leading to an uninitialized flag
+value at the mercy of the stack.
+
+Programmers have also been known to make ``dispatch_once_t``s be members of
+structs/classes, with the intent to lazily perform some expensive struct or
+class member initialization only once; however, this violates the libdispatch
+requirements.
+
+See the discussion section of
+`Apple's dispatch_once documentation `_
+for more information.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -73,6 +73,12 @@
   Finds instances where variables with static storage are initialized
   dynamically in header files.
 
+- New :doc:`darwin-dispatch-once-nonstatic
+  `check

[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D67567#1683905 , @gribozavr wrote:

> Thanks! Do you need me to commit the patch for you?


Yes, thank you. I don't have commit access—and also wasn't sure if anyone else 
had further comment.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 222016.
mwyman added a comment.

Rebased patch to apply to current master.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567

Files:
  clang-tools-extra/clang-tidy/CMakeLists.txt
  clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
  clang-tools-extra/clang-tidy/darwin/CMakeLists.txt
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.h
  clang-tools-extra/clang-tidy/plugin/CMakeLists.txt
  clang-tools-extra/clang-tidy/tool/CMakeLists.txt
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm

Index: clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy %s darwin-dispatch-once-nonstatic %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+
+void bad_dispatch_once(dispatch_once_t once, void(^block)(void)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: dispatch_once_ts must have static or global storage duration; function parameters should be pointer references [darwin-dispatch-once-nonstatic]
+
+// file-scope dispatch_once_ts have static storage duration.
+dispatch_once_t global_once;
+static dispatch_once_t file_static_once;
+namespace {
+dispatch_once_t anonymous_once;
+} // end anonymous namespace
+
+int Correct(void) {
+  static int value;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+int Incorrect(void) {
+  static int value;
+  dispatch_once_t once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+struct OnceStruct {
+  static dispatch_once_t staticOnce; // Allowed
+  int value;
+  dispatch_once_t once;  // Allowed (at this time)
+};
+
+@interface MyObject {
+  dispatch_once_t _once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration and cannot be Objective-C instance variables [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: dispatch_once_t _once;
+}
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -212,6 +212,7 @@
cppcoreguidelines-pro-type-vararg
cppcoreguidelines-slicing
cppcoreguidelines-special-member-functions
+   darwin-dispatch-once-nonstatic
fuchsia-default-arguments-calls
fuchsia-default-arguments-declarations
fuchsia-header-anon-namespaces (redirects to google-build-namespaces) 
Index: clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - darwin-dispatch-once-nonstatic
+
+darwin-dispatch-once-nonstatic
+==
+
+Finds declarations of ``dispatch_once_t`` variables without static or global
+storage. The behavior of using ``dispatch_once_t`` predicates with automatic
+or dynamic storage is undefined by libdispatch, and should be avoided.
+
+It is a common pattern to have functions initialize internal static or global
+data once when the function runs, but programmers have been known to miss the
+static on the ``dispatch_once_t`` predicate, leading to an uninitialized flag
+value at the mercy of the stack.
+
+Programmers have also been known to make ``dispatch_once_t``s be members of
+structs/classes, with the intent to lazily perform some expensive struct or
+class member initialization only once; however, this violates the libdispatch
+requirements.
+
+See the discussion section of
+`Apple's dispatch_once documentation `_
+for more information.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -79,6 +79,12 @@
   Finds obvious infinite loops (loops where the condition variable is not
   changed at all).
 
+- New :doc:`darwin-dispatch-once-nonstatic
+ 

[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D67567#1684785 , @gribozavr wrote:

> Sorry, could you rebase the patch to apply cleanly to master? Seems like 
> someone else edited ReleaseNotes.rst in the meanwhile.
>
>   $ arc patch D67567
>   ...
>   Checking patch clang-tools-extra/docs/ReleaseNotes.rst...
>   error: while searching for:
> Finds instances where variables with static storage are initialized
> dynamically in header files.
>


Just rebased, resolved the conflict and uploaded, should be good.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 222036.
mwyman marked 4 inline comments as done.
mwyman added a comment.

Addressed Stephane's review feedback.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567

Files:
  clang-tools-extra/clang-tidy/CMakeLists.txt
  clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
  clang-tools-extra/clang-tidy/darwin/CMakeLists.txt
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.cpp
  clang-tools-extra/clang-tidy/darwin/DispatchOnceNonstaticCheck.h
  clang-tools-extra/clang-tidy/plugin/CMakeLists.txt
  clang-tools-extra/clang-tidy/tool/CMakeLists.txt
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm

Index: clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/darwin-dispatch-once-nonstatic.mm
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy %s darwin-dispatch-once-nonstatic %t
+
+typedef int dispatch_once_t;
+extern void dispatch_once(dispatch_once_t *pred, void(^block)(void));
+
+
+void bad_dispatch_once(dispatch_once_t once, void(^block)(void)) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: dispatch_once_t variables must have static or global storage duration; function parameters should be pointer references [darwin-dispatch-once-nonstatic]
+
+// file-scope dispatch_once_ts have static storage duration.
+dispatch_once_t global_once;
+static dispatch_once_t file_static_once;
+namespace {
+dispatch_once_t anonymous_once;
+} // end anonymous namespace
+
+int Correct(void) {
+  static int value;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+int Incorrect(void) {
+  static int value;
+  dispatch_once_t once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: static dispatch_once_t once;
+  dispatch_once(&once, ^{
+value = 1;
+  });
+  return value;
+}
+
+struct OnceStruct {
+  static dispatch_once_t staticOnce; // Allowed
+  int value;
+  dispatch_once_t once;  // Allowed (at this time)
+};
+
+@interface MyObject {
+  dispatch_once_t _once;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: dispatch_once_t variables must have static or global storage duration and cannot be Objective-C instance variables [darwin-dispatch-once-nonstatic]
+  // CHECK-FIXES: dispatch_once_t _once;
+}
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -212,6 +212,7 @@
cppcoreguidelines-pro-type-vararg
cppcoreguidelines-slicing
cppcoreguidelines-special-member-functions
+   darwin-dispatch-once-nonstatic
fuchsia-default-arguments-calls
fuchsia-default-arguments-declarations
fuchsia-header-anon-namespaces (redirects to google-build-namespaces) 
Index: clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/darwin-dispatch-once-nonstatic.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - darwin-dispatch-once-nonstatic
+
+darwin-dispatch-once-nonstatic
+==
+
+Finds declarations of ``dispatch_once_t`` variables without static or global
+storage. The behavior of using ``dispatch_once_t`` predicates with automatic or
+dynamic storage is undefined by libdispatch, and should be avoided.
+
+It is a common pattern to have functions initialize internal static or global
+data once when the function runs, but programmers have been known to miss the
+static on the ``dispatch_once_t`` predicate, leading to an uninitialized flag
+value at the mercy of the stack.
+
+Programmers have also been known to make ``dispatch_once_t`` variables be
+members of structs or classes, with the intent to lazily perform some expensive
+struct or class member initialization only once; however, this violates the
+libdispatch requirements.
+
+See the discussion section of
+`Apple's dispatch_once documentation `_
+for more information.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -79,6 +79,12 @@
   Finds obvious infinite loops (loops where the condition variable is not
   changed

[PATCH] D67567: [clang-tidy] New check to warn when storing dispatch_once_t in non-static, non-global storage

2019-09-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D67567#1685036 , @gribozavr wrote:

> Sorry, I reverted it in r373032 because the test fails on Linux: 
> http://lab.llvm.org:8011/builders/clang-x86_64-debian-fast/builds/18323 . 
> Could you please take a look? Thanks!


What's the process for re-landing a change? New Differential, or update this 
one?


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67567/new/

https://reviews.llvm.org/D67567



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68148: [clang-tidy] Rename objc-avoid-spinlock check to darwin-avoid-spinlock

2019-09-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: stephanemoore, dmaclach.
mwyman added projects: clang-tools-extra, clang, LLVM.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.
mwyman edited the summary of this revision.

OSSpinLock* are Apple/Darwin functions, but were previously located with ObjC 
checks as those were most closely tied to Apple platforms before.

Now that there's a specific Darwin module, relocating the check there.

This change was prepared by running rename_check.py.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D68148

Files:
  clang-tools-extra/clang-tidy/darwin/AvoidSpinlockCheck.cpp
  clang-tools-extra/clang-tidy/darwin/AvoidSpinlockCheck.h
  clang-tools-extra/clang-tidy/darwin/CMakeLists.txt
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
  clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.cpp
  clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.h
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-avoid-spinlock.rst
  clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
  clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m

Index: clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
===
--- clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
+++ clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s objc-avoid-spinlock %t
+// RUN: %check_clang_tidy %s darwin-avoid-spinlock %t
 
 typedef int OSSpinLock;
 
@@ -6,10 +6,10 @@
 - (void)f {
 int i = 1;
 OSSpinlockLock(&i);
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [darwin-avoid-spinlock]
 OSSpinlockTry(&i);
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [darwin-avoid-spinlock]
 OSSpinlockUnlock(&i);
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [darwin-avoid-spinlock]
 }
 @end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -212,6 +212,7 @@
cppcoreguidelines-pro-type-vararg
cppcoreguidelines-slicing
cppcoreguidelines-special-member-functions
+   darwin-avoid-spinlock
darwin-dispatch-once-nonstatic
fuchsia-default-arguments-calls
fuchsia-default-arguments-declarations
@@ -325,7 +326,6 @@
mpi-buffer-deref
mpi-type-mismatch
objc-avoid-nserror-init
-   objc-avoid-spinlock
objc-forbidden-subclassing
objc-missing-hash
objc-property-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
+++ clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
@@ -1,7 +1,7 @@
-.. title:: clang-tidy - objc-avoid-spinlock
+.. title:: clang-tidy - darwin-avoid-spinlock
 
-objc-avoid-spinlock
-===
+darwin-avoid-spinlock
+=
 
 Finds usages of ``OSSpinlock``, which is deprecated due to potential livelock
 problems. 
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -67,6 +67,9 @@
 Improvements to clang-tidy
 --
 
+- The 'objc-avoid-spinlock' check was renamed to :doc:`darwin-avoid-spinlock
+  `
+
 - New :doc:`bugprone-dynamic-static-initializers
   ` check.
 
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
+++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -10,7 +10,6 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidNSErrorInitCheck.h"
-#include "AvoidSpinlockCheck.h"
 #incl

[PATCH] D68148: [clang-tidy] Rename objc-avoid-spinlock check to darwin-avoid-spinlock

2019-09-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 53.
mwyman added a comment.

Moved release note below list of new checks.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68148/new/

https://reviews.llvm.org/D68148

Files:
  clang-tools-extra/clang-tidy/darwin/AvoidSpinlockCheck.cpp
  clang-tools-extra/clang-tidy/darwin/AvoidSpinlockCheck.h
  clang-tools-extra/clang-tidy/darwin/CMakeLists.txt
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
  clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.cpp
  clang-tools-extra/clang-tidy/objc/AvoidSpinlockCheck.h
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-avoid-spinlock.rst
  clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
  clang-tools-extra/test/clang-tidy/objc-avoid-spinlock.m

Index: clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
===
--- clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
+++ clang-tools-extra/test/clang-tidy/darwin-avoid-spinlock.m
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s objc-avoid-spinlock %t
+// RUN: %check_clang_tidy %s darwin-avoid-spinlock %t
 
 typedef int OSSpinLock;
 
@@ -6,10 +6,10 @@
 - (void)f {
 int i = 1;
 OSSpinlockLock(&i);
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [darwin-avoid-spinlock]
 OSSpinlockTry(&i);
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [darwin-avoid-spinlock]
 OSSpinlockUnlock(&i);
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [objc-avoid-spinlock]
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use os_unfair_lock_lock() or dispatch queue APIs instead of the deprecated OSSpinLock [darwin-avoid-spinlock]
 }
 @end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -212,6 +212,7 @@
cppcoreguidelines-pro-type-vararg
cppcoreguidelines-slicing
cppcoreguidelines-special-member-functions
+   darwin-avoid-spinlock
darwin-dispatch-once-nonstatic
fuchsia-default-arguments-calls
fuchsia-default-arguments-declarations
@@ -325,7 +326,6 @@
mpi-buffer-deref
mpi-type-mismatch
objc-avoid-nserror-init
-   objc-avoid-spinlock
objc-forbidden-subclassing
objc-missing-hash
objc-property-declaration
Index: clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
+++ clang-tools-extra/docs/clang-tidy/checks/darwin-avoid-spinlock.rst
@@ -1,7 +1,7 @@
-.. title:: clang-tidy - objc-avoid-spinlock
+.. title:: clang-tidy - darwin-avoid-spinlock
 
-objc-avoid-spinlock
-===
+darwin-avoid-spinlock
+=
 
 Finds usages of ``OSSpinlock``, which is deprecated due to potential livelock
 problems. 
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -115,6 +115,9 @@
   Now also checks if any calls to ``pthread_*`` functions expect negative return
   values.
 
+- The 'objc-avoid-spinlock' check was renamed to :doc:`darwin-avoid-spinlock
+  `
+
 Improvements to include-fixer
 -
 
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
+++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -10,7 +10,6 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidNSErrorInitCheck.h"
-#include "AvoidSpinlockCheck.h"
 #include "ForbiddenSubclassingCheck.h"
 #include "MissingHashCheck.h"
 #include "PropertyDeclarationCheck.h"
@@ -27,8 +26,6 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck(
 "objc-avoid-nserror-init");
-CheckFactories.registerCheck(
-"objc-avoi

[PATCH] D68251: [clang-tidy] Fix module registry name and description for Darwin clang-tidy module.

2019-09-30 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: stephanemoore, benhamilton, gribozavr.
mwyman added projects: clang, clang-tools-extra, LLVM.
Herald added subscribers: cfe-commits, xazax.hun.

When creating the module, must have copy-pasted from the misc module, and 
forgotten to update the name/description of the module in the registry.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D68251

Files:
  clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp


Index: clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
+++ clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
@@ -27,7 +27,7 @@
 
 // Register the DarwinTidyModule using this statically initialized variable.
 static ClangTidyModuleRegistry::Add
-X("misc-module", "Adds miscellaneous lint checks.");
+X("darwin-module", "Adds Darwin-specific lint checks.");
 
 // This anchor is used to force the linker to link in the generated object file
 // and thus register the DarwinModule.


Index: clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
+++ clang-tools-extra/clang-tidy/darwin/DarwinTidyModule.cpp
@@ -27,7 +27,7 @@
 
 // Register the DarwinTidyModule using this statically initialized variable.
 static ClangTidyModuleRegistry::Add
-X("misc-module", "Adds miscellaneous lint checks.");
+X("darwin-module", "Adds Darwin-specific lint checks.");
 
 // This anchor is used to force the linker to link in the generated object file
 // and thus register the DarwinModule.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D77571: Add ClangTidy check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.
mwyman added reviewers: stephanemoore, benhamilton, dmaclach.
mwyman added a project: clang-tools-extra.
mwyman edited the summary of this revision.

This check is similar to an ARC Migration check that warned about this 
incorrect usage under ARC, but most projects are no longer undergoing migration 
from pre-ARC code. The documentation for NSInvocation is not explicit about 
these requirements and incorrect usage has been found in many of our projects.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,63 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t -- -fobjc-arc
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation's 'getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void*)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+  id Argument;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - objc-nsinvocation-argument-lifetime
+
+objc-nsinvocation-argument-lifetime
+===
+
+Finds calls to NSInvocation methods under ARC that don't have proper
+argument object lifetimes. When passing Objective-C objects as parameters
+to the NSInvocation methods ``getArgument:atIndex:`` and ``getReturnValue:``,
+the values are copied by value into the argument pointer, which leads to
+to incorrect releasing behavior if the object pointers are not declared
+``__unsafe_unretained``.
+
+For code:
+
+.. code-block:: objc
+
+id arg;
+[invocation getArgument:&arg atIndex:2];
+
+__strong id returnValue;
+[invocation getReturnValue:&returnValue];
+
+The fix will be:
+
+.. code-block:

[PATCH] D77571: Add ClangTidy check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 255423.
mwyman added a comment.

Check for Objective-C block pointers as well, which also require 
__unsafe_unretained when retrieved as arguments from NSInvocation under ARC.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t -- -fobjc-arc
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation's 'getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void*)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+  id Argument;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation's 'getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - objc-nsinvocation-argument-lifetime
+
+objc-nsinvocation-argument-lifetime
+===
+
+Finds calls to NSInvocation methods under ARC that don't have proper
+argument object lifetimes. When passing Objective-C objects as parameters
+to the NSInvocation methods ``getArgument:atIndex:`` and ``getReturnValue:``,
+the values are copied by value into the argument pointer, which leads to
+to incorrect releasing behavior if the object pointers are not declared
+``__unsafe_unretained``.
+
+For code:
+
+.. code-block:: objc
+
+id arg;
+[invocation getArgument:&arg atIndex:2];
+
+__strong id returnValue;
+   

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 255461.
mwyman marked 6 inline comments as done.
mwyman added a comment.

Responding to review feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t -- -fobjc-arc
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void*)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+  id Argument;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - objc-nsinvocation-argument-lifetime
+
+objc-nsinvocation-argument-lifetime
+===
+
+Finds calls to ``NSInvocation`` methods under ARC that don't have proper
+argument object lifetimes. When passing Objective-C objects as parameters
+to the ``NSInvocation`` methods ``getArgument:atIndex:`` and
+``getReturnValue:``, the values are copied by value into the argument pointer,
+which leads to to incorrect releasing behavior if the object pointers are
+not declared ``__unsafe_unretained``.
+
+For code:
+
+.. code-block:: objc
+
+id arg;
+[invocation getArgument:&arg atIndex:2];
+
+__strong id returnValue;
+[invocation getReturnValue:&returnValue];
+
+The fix will be:
+
+.. c

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked an inline comment as done.
mwyman added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp:71-73
+  // Currently there is no way to directly get the source range for the
+  // __weak/__strong ObjC lifetime qualifiers, so it's necessary to string
+  // search in the source code.

benhamilton wrote:
> Is there a bug filed for this? Seems like an oversight.
> 
Maybe I'm incorrectly reading this, but per the comment on QualifiedTypeLoc it 
seems like this is intentional at this time: 
https://github.com/llvm/llvm-project/blob/549e87f3d04bbae91bc7bc38609ce7073e2c8a6d/clang/include/clang/AST/TypeLoc.h#L275



Comment at: 
clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp:116
+  auto Diag = diag(MatchedExpr->getArg(0)->getBeginLoc(),
+   "NSInvocation's %0 should only pass pointers to "
+   "objects with ownership __unsafe_unretained")

benhamilton wrote:
> -[NSInvocation %0] should
> 
Tweaked the format string so it now outputs "NSInvocation '-…'", since the 
diagnostic formatter inserts single-quotes, which would otherwise make it read 
"-[NSInvocation 'getArgument:atIndex:']", which seems weirder.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 255519.
mwyman added a comment.

Missed CHECK-FIXES for block argument.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,71 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+  id Argument;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - objc-nsinvocation-argument-lifetime
+
+objc-nsinvocation-argument-lifetime
+===
+
+Finds calls to ``NSInvocation`` methods under ARC that don't have proper
+argument object lifetimes. When passing Objective-C objects as parameters
+to the ``NSInvocation`` methods ``getArgument:atIndex:`` and
+``getReturnValue:``, the values are copied by value into the argument pointer,
+which leads to to incorrect releasing behavior if the object pointers are
+not declared ``__unsafe_unretained``.
+
+For code:
+
+.. code-block:: objc
+
+id arg;
+[invocation getArgument:&arg atIndex:2];
+
+__strong id returnValue;
+[invocation getReturnValue:&returnValue];
+
+The fix wi

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 255513.
mwyman added a comment.

Trying to fix Harbormaster build.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NsinvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void*)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+  id Argument;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - objc-nsinvocation-argument-lifetime
+
+objc-nsinvocation-argument-lifetime
+===
+
+Finds calls to ``NSInvocation`` methods under ARC that don't have proper
+argument object lifetimes. When passing Objective-C objects as parameters
+to the ``NSInvocation`` methods ``getArgument:atIndex:`` and
+``getReturnValue:``, the values are copied by value into the argument pointer,
+which leads to to incorrect releasing behavior if the object pointers are
+not declared ``__unsafe_unretained``.
+
+For code:
+
+.. code-block:: objc
+
+id arg;
+[invocation getArgument:&arg atIndex:2];
+
+__strong id returnValue;
+[invocation getReturnValue:&returnValue];
+
+The fix will be:
+
+.. code-block:: objc
+
+__unsafe_unretained id arg;

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-08 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 256070.
mwyman added a comment.

Renamed NsinvocationArgumentLifetimeCheck -> NSInvocationArgumentLifetimeCheck 
to match other ObjC checker names.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,71 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+  id Argument;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
@@ -0,0 +1,39 @@
+.. title:: clang-tidy - objc-nsinvocation-argument-lifetime
+
+objc-nsinvocation-argument-lifetime
+===
+
+Finds calls to ``NSInvocation`` methods under ARC that don't have proper
+argument object lifetimes. When passing Objective-C objects as parameters
+to the ``NSInvocation`` methods ``getArgument:atIndex:`` and
+``getReturnValue:``, the values are copied by value into the argument pointer,
+which leads to to incorrect releasing behavior if the object pointers are
+not declared ``__unsafe_unretained``.
+
+For code:
+
+.. code-block:: objc
+
+id arg;
+[invocation getArgument:&arg atIndex:2];
+
+__strong 

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-09 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 256210.
mwyman added a comment.

Add matching MemberRefExpr case, not just the non-matching case there was 
before.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,91 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+struct Foo {
+  __unsafe_unretained id Field1;
+  id Field2;
+};
+
+@interface TestClass : NSObject {
+@public
+  id Argument1;
+  __unsafe_unretained id Argument2;
+  struct Foo Bar;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Argument2 atIndex:2];
+  [Invocation getArgument:&self->Argument2 atIndex:2];
+
+  [Invocation getReturnValue:&(self->Bar.Field1)];
+  [Invocation getReturnValue:&(self->Bar.Field2)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}
+
+@end
+
+void baz(NSInvocation *Invocation, TestClass *Obj) {
+  [Invocation getArgument:&Obj->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Obj->Argument2 atIndex:2];
+}
Index: clang-tools-extra/docs/clang-tidy/checks/objc-nsinvoc

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-09 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 256209.
mwyman marked an inline comment as done.
mwyman added a comment.

Updating per Stephane's comments. To deal with struct fields needed to match 
MemberRefExprs.

However, in doing so I discovered that the match conditions I thought were 
catching ObjcIvarRefExpr or MemberRefExpr were sometimes incorrectly matching 
on the self reference, which is itself a DeclRefExpr to an object with strong 
lifetime semantics. This meant correct usages would sometimes be caught, 
because the ObjcIvarRefExpr wouldn't match but the DeclRefExpr (to self) did.

That self (or other object) that is dereferenced (implicity or explicitly) has 
a parent ImplicitCastExpr in the AST, so I've dealt with this situation by 
excluding that case from matching the declRefExpr.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+struct Foo {
+  __unsafe_unretained id Field;
+};
+
+@interface TestClass : NSObject {
+@public
+  id Argument1;
+  __unsafe_unretained id Argument2;
+  struct Foo Bar;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Argument2 atIndex:2];
+  [Invocation getArgument:&self->Argument2 atIndex:2];
+
+  [Invocation getReturnValue:&(self->Bar.Field)];
+}
+
+@end
+
+void baz(NSInvocation *Invocatio

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-09 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 4 inline comments as done.
mwyman added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp:49
+  QT->getScalarTypeKind() == Type::STK_BlockPointer) &&
+ QT.getQualifiers().getObjCLifetime() > Qualifiers::OCL_ExplicitNone;
+}

stephanemoore wrote:
> I'm not sure but I guess it's okay to assume that the enumeration ordering 
> will remain stable?
I don't know why anyone would change the ordering, but FWIW this is the same 
approach used by the ARC migrator code.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m:64-69
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation 
'-getArgument:atIndex:' should only pass pointers to objects with ownership 
__unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation 
'-getArgument:atIndex:' should only pass pointers to objects with ownership 
__unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}

stephanemoore wrote:
> stephanemoore wrote:
> > How about a test case where we take the address of something on an ivar?
> > 
> > For example, I think the code below should not produce a diagnostic 
> > finding, right?
> > ```
> > struct Example {
> >   __unsafe_unretained id Field;
> > };
> > 
> > @interface TestClass : NSObject {
> >   struct Example ExampleIvar;
> > }
> > 
> > @end
> > 
> > @implementation TestClass
> > 
> > - (void)processInvocation:(NSInvocation *)Invocation {
> >   [Invocation getArgument:&(self->ExampleIvar.Field) atIndex:2];
> > }
> > 
> > @end
> > ```
> Maybe worth adding an ivar case that doesn't produce a diagnostic?
This required checking MemberRefExprs too. Added both a matching and 
non-matching case here.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m:64-69
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation 
'-getArgument:atIndex:' should only pass pointers to objects with ownership 
__unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation 
'-getArgument:atIndex:' should only pass pointers to objects with ownership 
__unsafe_unretained [objc-nsinvocation-argument-lifetime]
+}

mwyman wrote:
> stephanemoore wrote:
> > stephanemoore wrote:
> > > How about a test case where we take the address of something on an ivar?
> > > 
> > > For example, I think the code below should not produce a diagnostic 
> > > finding, right?
> > > ```
> > > struct Example {
> > >   __unsafe_unretained id Field;
> > > };
> > > 
> > > @interface TestClass : NSObject {
> > >   struct Example ExampleIvar;
> > > }
> > > 
> > > @end
> > > 
> > > @implementation TestClass
> > > 
> > > - (void)processInvocation:(NSInvocation *)Invocation {
> > >   [Invocation getArgument:&(self->ExampleIvar.Field) atIndex:2];
> > > }
> > > 
> > > @end
> > > ```
> > Maybe worth adding an ivar case that doesn't produce a diagnostic?
> This required checking MemberRefExprs too. Added both a matching and 
> non-matching case here.
Added a non-matching ivar case, and in doing so discovered it was often 
actually matching the "self" reference, which is an ImplicitParamDecl, itself a 
type of VarDecl, which matched the declRefExpr(), leading to even cases that 
shouldn't have produced diagnostics to produce them.

Have fixed this by excluding the self case (by ensuring the declRefExpr's 
parent is not an implicitCastExpr, which only appears in the AST that I've seen 
around the self—or other dereferenced object—reference).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-09 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 256332.
mwyman marked 2 inline comments as done.
mwyman added a comment.

Adding non-object types for argument to getArgument:atIndex: to verify they 
don't cause problems.

Done while investigating Harbormaster failures.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,97 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+  int IntVar;
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+  [Invocation getArgument:&IntVar atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+struct Foo {
+  __unsafe_unretained id Field1;
+  id Field2;
+  int IntField;
+};
+
+@interface TestClass : NSObject {
+@public
+  id Argument1;
+  __unsafe_unretained id Argument2;
+  struct Foo Bar;
+  int IntIvar;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Argument2 atIndex:2];
+  [Invocation getArgument:&self->Argument2 atIndex:2];
+  [Invocation getArgument:&self->IntIvar atIndex:2];
+
+  [Invocation getReturnValue:&(self->Bar.Field1)];
+  [Invocation getReturnValue:&(self->Bar.Field2)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getReturnValue:&(self->Bar.IntField)];
+}
+
+@end
+
+void baz(NSInvocation *Invocation, TestClass *Obj) {
+  [Invocation getArgument:&Obj->Argument1 atIndex:2];
+  /

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-09 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 256344.
mwyman added a comment.

Add check for isScalarType before getting the type, which seems to be 
triggering an assert. Maybe this is a Mac vs Linux thing?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,97 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+  int IntVar;
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+  [Invocation getArgument:&IntVar atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+struct Foo {
+  __unsafe_unretained id Field1;
+  id Field2;
+  int IntField;
+};
+
+@interface TestClass : NSObject {
+@public
+  id Argument1;
+  __unsafe_unretained id Argument2;
+  struct Foo Bar;
+  int IntIvar;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Argument2 atIndex:2];
+  [Invocation getArgument:&self->Argument2 atIndex:2];
+  [Invocation getArgument:&self->IntIvar atIndex:2];
+
+  [Invocation getReturnValue:&(self->Bar.Field1)];
+  [Invocation getReturnValue:&(self->Bar.Field2)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getReturnValue:&(self->Bar.IntField)];
+}
+
+@end
+
+void baz(NSInvocation *Invocation, TestClass *Obj) {
+  [Invocation getArgument:&Obj->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-g

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-10 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 256521.
mwyman added a comment.

Added struct member reference from local variable, per review comment.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+struct Foo {
+  __unsafe_unretained id Field1;
+  id Field2;
+  int IntField;
+};
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+  int IntVar;
+  struct Foo Bar;
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+  [Invocation getArgument:&IntVar atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+
+  [Invocation getArgument:&Bar.Field1 atIndex:2];
+  [Invocation getArgument:&Bar.Field2 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Bar.IntField atIndex:2];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+@public
+  id Argument1;
+  __unsafe_unretained id Argument2;
+  struct Foo Bar;
+  int IntIvar;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Argument2 atIndex:2];
+  [Invocation getArgument:&self->Argument2 atIndex:2];
+  [Invocation getArgument:&self->IntIvar atIndex:2];
+
+  [Invocation getReturnValue:&(self->Bar.Field1)];
+  [Invocation getReturnValue:&(self->Bar.Field2)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects

[PATCH] D77571: [clang-tidy] Add check to find calls to NSInvocation methods under ARC that don't have proper object argument lifetimes.

2020-04-10 Thread Michael Wyman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG89f1321fe4ef: [clang-tidy] Add check to find calls to 
NSInvocation methods under ARC that… (authored by mwyman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77571/new/

https://reviews.llvm.org/D77571

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp
  clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-nsinvocation-argument-lifetime.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-nsinvocation-argument-lifetime.m
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t
+
+__attribute__((objc_root_class))
+@interface NSObject
+@end
+
+@interface NSInvocation : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+- (void)getReturnValue:(void *)ReturnValue;
+@end
+
+@interface OtherClass : NSObject
+- (void)getArgument:(void *)Arg atIndex:(int)Index;
+@end
+
+struct Foo {
+  __unsafe_unretained id Field1;
+  id Field2;
+  int IntField;
+};
+
+void foo(NSInvocation *Invocation) {
+  __unsafe_unretained id Arg2;
+  id Arg3;
+  // CHECK-FIXES: __unsafe_unretained id Arg3;
+  NSObject __strong *Arg4;
+  // CHECK-FIXES: NSObject __unsafe_unretained *Arg4;
+  __weak id Arg5;
+  // CHECK-FIXES: __unsafe_unretained id Arg5;
+  id ReturnValue;
+  // CHECK-FIXES: __unsafe_unretained id ReturnValue;
+  void (^BlockArg1)();
+  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
+  __unsafe_unretained void (^BlockArg2)();
+  int IntVar;
+  struct Foo Bar;
+
+  [Invocation getArgument:&Arg2 atIndex:2];
+  [Invocation getArgument:&IntVar atIndex:2];
+
+  [Invocation getArgument:&Arg3 atIndex:3];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg4 atIndex:4];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&Arg5 atIndex:5];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg1 atIndex:6];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:&BlockArg2 atIndex:6];
+
+  [Invocation getReturnValue:&ReturnValue];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+
+  [Invocation getArgument:(void *)0 atIndex:6];
+
+  [Invocation getArgument:&Bar.Field1 atIndex:2];
+  [Invocation getArgument:&Bar.Field2 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Bar.IntField atIndex:2];
+}
+
+void bar(OtherClass *OC) {
+  id Arg;
+  [OC getArgument:&Arg atIndex:2];
+}
+
+@interface TestClass : NSObject {
+@public
+  id Argument1;
+  __unsafe_unretained id Argument2;
+  struct Foo Bar;
+  int IntIvar;
+}
+@end
+
+@implementation TestClass
+
+- (void)processInvocation:(NSInvocation *)Invocation {
+  [Invocation getArgument:&Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&self->Argument1 atIndex:2];
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime]
+  [Invocation getArgument:&Argument2 atIndex:2];
+  [Invocation getArgument:&self->Argument2 atIndex:2];
+  [Invocation getArgument:&self->IntIvar atIndex:2];
+
+  [Invocation getReturnValue:&(self->Bar.Field1)];
+  [Invocation getReturnValue:&(self->Bar.Field2)];
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSI

[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-09-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

This is related to changes for https://reviews.llvm.org/D86049.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131424/new/

https://reviews.llvm.org/D131424

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86049: RFC: Implement optional exportable wrapper function generation for objc_direct methods.

2022-09-12 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added inline comments.



Comment at: clang/include/clang/Basic/Attr.td:2251-2256
+def ObjCDirectVisible : Attr {
+  let Spellings = [Clang<"objc_direct_visible">];
+  let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+  let LangOpts = [ObjC];
+  let Documentation = [ObjCDirectVisibleDocs];
+}

plotfi wrote:
> plotfi wrote:
> > mwyman wrote:
> > > Should this inherit `ObjCDirect`, to include both objc_direct and the 
> > > visibility aspect? I don't see any reason we would want to add 
> > > `objc_direct_visible` without also having `objc_direct`, so why make 
> > > developers add both?
> > > 
> > > As an alternative, would it make sense to allow adding 
> > > `__attribute__((visibility("default")))` on direct methods?
> > > 
> > > Also, it doesn't seem like this allows making `@property`s visible, so 
> > > should there be a similar attribute for properties?
> > I'd prefer to do `@property`s in a separate commit, but I suppose you are 
> > thinking like a `objc_direct_members_visible` attribute? I think I can add 
> > that in a subsequent commit. 
> > 
> > I took a look at how to make things inherit and I think the most 
> > straightforward way is to have `handleObjCDirectVisibleAttr` set the 
> > objc_direct attribute if it is not set already.
> > 
> > As for `__attribute__((visibility("default")))` I think the trouble lies in 
> > what we want the default visibility behavior for objc methods to be and if 
> > we want the behavior to be controlled by `-fvisibility=`. I tried going by 
> > attribute visibility before and had some trouble too (I forget exactly what 
> > though). 
> > 
> > 
> I gave visibility a try and it seems that the trouble is everything is 
> visible by default where for objc methods we want them hidden by default. I 
> think I would rather add a separate attr for this than add an additional 
> non-conformant visibility mode. 
Re: visibility, I wonder if it might make sense to create an optional enum 
argument on the `objc_direct` and `objc_direct_members` attributes, with either 
`hidden` or `visible` values (and presumably `hidden` being default); if we 
have an `objc_direct_members_visible`-like attribute, would there be cases 
where someone may wish to hide individual members?

This is quite possibly over-thinking the issue, but it also then avoids having 
an entirely new pair of method attributes. It doesn't solve the `@property` 
attributes, which don't have arguments, but it may be unavoidable to add a 
completely new attribute for that.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128556: Make Objective-C++ match Objective-C's behavior on implicit ivar access when `self` is shadowed

2022-06-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 440311.
mwyman added a comment.

Added codegen test.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128556/new/

https://reviews.llvm.org/D128556

Files:
  clang/lib/Sema/SemaLookup.cpp
  clang/test/CodeGenObjC/ivar-implicit-self-shadow.m


Index: clang/test/CodeGenObjC/ivar-implicit-self-shadow.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/ivar-implicit-self-shadow.m
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-apple-iossimulator -fobjc-arc -x objective-c 
-emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
+// RUN: %clang_cc1 -triple x86_64-apple-iossimulator -fobjc-arc -x 
objective-c++ -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
+
+__attribute__((objc_root_class))
+@interface Foo
+@end
+
+extern Foo *CreateObject(void) __attribute__((ns_returns_retained));
+
+@implementation Foo {
+  int _ivar;
+}
+
+// CHECK-LABEL: define{{.*}}-[Foo foo]"(ptr noundef %self, ptr noundef %_cmd) 
#0 {
+- (void)foo {
+  {
+Foo *self = CreateObject();
+_ivar = 42;
+// CHECK:   [[PTR:%.*]] = load ptr, ptr %self.addr, align 8
+// CHECK-NEXT:  [[IVAR:%.*]] = load i64, ptr @"OBJC_IVAR_$_Foo._ivar", 
align 8, {{.*}}
+// CHECK-NEXT:  [[OFFSET:%.*]] = getelementptr inbounds i8, ptr [[PTR]], 
i64 [[IVAR]]
+// CHECK-NEXT:  store i32 42, ptr [[OFFSET]]
+  }
+}
+@end
+
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -1313,6 +1313,9 @@
 R.setShadowed();
 continue;
   }
+} else if (NameKind == LookupObjCImplicitSelfParam &&
+   !isa(*I)) {
+  continue;
 } else {
   // We found something in this scope, we should not look at the
   // namespace scope


Index: clang/test/CodeGenObjC/ivar-implicit-self-shadow.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/ivar-implicit-self-shadow.m
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-apple-iossimulator -fobjc-arc -x objective-c -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
+// RUN: %clang_cc1 -triple x86_64-apple-iossimulator -fobjc-arc -x objective-c++ -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK
+
+__attribute__((objc_root_class))
+@interface Foo
+@end
+
+extern Foo *CreateObject(void) __attribute__((ns_returns_retained));
+
+@implementation Foo {
+  int _ivar;
+}
+
+// CHECK-LABEL: define{{.*}}-[Foo foo]"(ptr noundef %self, ptr noundef %_cmd) #0 {
+- (void)foo {
+  {
+Foo *self = CreateObject();
+_ivar = 42;
+// CHECK:   [[PTR:%.*]] = load ptr, ptr %self.addr, align 8
+// CHECK-NEXT:  [[IVAR:%.*]] = load i64, ptr @"OBJC_IVAR_$_Foo._ivar", align 8, {{.*}}
+// CHECK-NEXT:  [[OFFSET:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[IVAR]]
+// CHECK-NEXT:  store i32 42, ptr [[OFFSET]]
+  }
+}
+@end
+
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -1313,6 +1313,9 @@
 R.setShadowed();
 continue;
   }
+} else if (NameKind == LookupObjCImplicitSelfParam &&
+   !isa(*I)) {
+  continue;
 } else {
   // We found something in this scope, we should not look at the
   // namespace scope
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128556: Make Objective-C++ match Objective-C's behavior on implicit ivar access when `self` is shadowed

2022-06-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

Unit test passes both pre- and post- this change for `-x objective-c`, fails 
pre-change with `-x objective-c++` and passes post-change.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128556/new/

https://reviews.llvm.org/D128556

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128031: Don't emit `-Wnullability-completeness` warnings on `weak` Objective-C properties.

2022-06-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 440390.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128031/new/

https://reviews.llvm.org/D128031

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4683,8 +4683,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) 
{
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4683,8 +4683,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128031: Don't emit `-Wnullability-completeness` warnings on `weak` Objective-C properties.

2022-06-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a reviewer: doug.gregor.
mwyman added a comment.

Adding Doug Gregor who appears to have created the original warning.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128031/new/

https://reviews.llvm.org/D128031

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128556: Make Objective-C++ match Objective-C's behavior on implicit ivar access when `self` is shadowed

2022-06-29 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 441270.
mwyman added a comment.

Change to use a unit test on the semantic lookup code, rather than a codegen 
test; I realized the name lookup behavior could be more directly checked by 
inspecting the internal references in the generated AST to ensure the found 
"self" is the implicit parameter "self".


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128556/new/

https://reviews.llvm.org/D128556

Files:
  clang/lib/Sema/SemaLookup.cpp
  clang/unittests/Sema/SemaLookupTest.cpp

Index: clang/unittests/Sema/SemaLookupTest.cpp
===
--- clang/unittests/Sema/SemaLookupTest.cpp
+++ clang/unittests/Sema/SemaLookupTest.cpp
@@ -1,4 +1,6 @@
 #include "clang/AST/DeclarationName.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/Parse/ParseAST.h"
@@ -10,6 +12,7 @@
 using namespace llvm;
 using namespace clang;
 using namespace clang::tooling;
+using namespace clang::ast_matchers;
 
 namespace {
 
@@ -57,4 +60,84 @@
 file_contents, {"-x", "objective-c++"},
 "test.mm"));
 }
+
+using ExprMatcher = internal::Matcher;
+using StmtMatcher = internal::Matcher;
+
+AST_MATCHER(ObjCIvarRefExpr, isFreeIvar) {
+  return Node.isFreeIvar();
+}
+
+ExprMatcher objcIvarRefTo(StringRef Name) {
+  return declRefExpr(hasAncestor(objcIvarRefExpr(allOf(isFreeIvar(),
+   hasDeclaration(namedDecl(
+   hasName(Name)
+ .bind("ivarref")))
+  .bind("selfref");
+}
+
+StmtMatcher withEnclosingMethod(ExprMatcher Matcher) {
+  return expr(Matcher,
+  hasAncestor(objcMethodDecl(isDefinition()).bind("method")))
+  .bind("expr");
+}
+
+class IvarLookupImplicitSelf : public ASTFrontendAction {
+  std::unique_ptr
+  CreateASTConsumer(CompilerInstance &CI, StringRef /* Unused */) override {
+return std::make_unique();
+  }
+
+  void ExecuteAction() override {
+CompilerInstance &CI = getCompilerInstance();
+ASSERT_FALSE(CI.hasSema());
+CI.createSema(getTranslationUnitKind(), nullptr);
+ASSERT_TRUE(CI.hasSema());
+Sema &S = CI.getSema();
+ParseAST(S);
+
+ASTContext &Ctx = S.getASTContext();
+const auto Results =
+match(withEnclosingMethod(objcIvarRefTo("_ivar")), Ctx);
+const auto *MD = selectFirst("method", Results);
+const auto *SelfRef = selectFirst("selfref", Results);
+ASSERT_TRUE(MD && SelfRef);
+
+// When name lookup is occurring correctly, the SelfRef should refer to the
+// Method's ImplicitParamDecl of 'self'.
+const auto *SelfDecl = SelfRef->getDecl();
+EXPECT_TRUE(isa(SelfDecl) &&
+MD->getSelfDecl() == SelfDecl);
+  }
+};
+
+constexpr StringRef ImplicitIvarFileContents = R"objcxx(
+__attribute__((objc_root_class))
+@interface Foo
+@end
+extern Foo *CreateFoo();
+@implementation Foo {
+  int _ivar;
+}
+- (void)foo {
+  {
+Foo *self = CreateFoo();
+_ivar = 42;
+  }
+}
+@end
+  )objcxx";
+
+TEST(SemaLookupTest, ImplicitIvarSelfRefLookupObjCpp) {
+  ASSERT_TRUE(runToolOnCodeWithArgs(std::make_unique(),
+ImplicitIvarFileContents,
+{"-x", "objective-c++"}, "test.mm"));
+}
+
+TEST(SemaLookupTest, ImplicitIvarSelfRefLookupObjC) {
+  ASSERT_TRUE(runToolOnCodeWithArgs(std::make_unique(),
+ImplicitIvarFileContents,
+{"-x", "objective-c"}, "test.m"));
+}
+
 } // namespace
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -1313,6 +1313,9 @@
 R.setShadowed();
 continue;
   }
+} else if (NameKind == LookupObjCImplicitSelfParam &&
+   !isa(*I)) {
+  continue;
 } else {
   // We found something in this scope, we should not look at the
   // namespace scope
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-08-08 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: dmaclach, plotfi.
mwyman added a project: clang.
Herald added a project: All.
mwyman requested review of this revision.
Herald added a subscriber: cfe-commits.

When `objc_direct` methods were implemented, the implicit `_cmd` parameter was 
left as an argument to the method implementation function, but was unset by 
callers; if the method body referenced the `_cmd` variable, a selector load 
would be emitted inside the body. However, this leaves an unused argument in 
the ABI, and is unnecessary.

This change removes the empty/unset argument, and if `_cmd` is referenced 
inside an `objc_direct` method it will emit local storage for the implicit 
variable. From the ABI perspective, `objc_direct` methods will have the 
implicit `self` parameter, immediately followed by whatever explicit arguments 
are defined on the method, rather than having one unset/undefined register in 
the middle.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131424

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/test/CodeGenObjC/direct-method.m

Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -28,9 +28,7 @@
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -60,9 +58,7 @@
   // loading parameters
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // [self self]
   // CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]],
@@ -81,9 +77,7 @@
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -125,9 +119,7 @@
   // loading parameters
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -159,6 +151,19 @@
   // CHECK: ret void
 }
 
+// CHECK-LABEL: define hidden void @"\01-[Root accessCmd]"(
+- (void)accessCmd __attribute__((objc_direct)) {
+  // CHECK-LABEL: entry:
+  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+  // CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+
+  // loading the _cmd selector
+  // CHECK-LABEL: objc_direct_method.cont:
+  // CHECK-NEXT: [[CMD1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+  // CHECK-NEXT: store i8* [[CMD1]], i8** [[CMDVAL]],
+  SEL sel = _cmd;
+}
+
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
@@ -205,19 +210,19 @@
 
 int useRoot(Root *r) {
   // CHECK-LABEL: define{{.*}} i32 @useRoot
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]"
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]" to i32 (i8*)
   return [r getInt] + [r intProperty] + [r intProperty2];
 }
 
 int useFoo(Foo *f) {
   // CHECK-LABEL: define{{.*}} i32 @useFoo
-  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]"
+  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]" to void (i8*, i32)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = ca

[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-08-08 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 451051.
mwyman added a comment.

Fixed assert due to mis-matched number of expected parameters.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131424/new/

https://reviews.llvm.org/D131424

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/test/CodeGenObjC/direct-method.m

Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -28,9 +28,7 @@
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -60,9 +58,7 @@
   // loading parameters
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // [self self]
   // CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]],
@@ -81,9 +77,7 @@
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -125,9 +119,7 @@
   // loading parameters
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -159,6 +151,19 @@
   // CHECK: ret void
 }
 
+// CHECK-LABEL: define hidden void @"\01-[Root accessCmd]"(
+- (void)accessCmd __attribute__((objc_direct)) {
+  // CHECK-LABEL: entry:
+  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+  // CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+
+  // loading the _cmd selector
+  // CHECK-LABEL: objc_direct_method.cont:
+  // CHECK-NEXT: [[CMD1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+  // CHECK-NEXT: store i8* [[CMD1]], i8** [[CMDVAL]],
+  SEL sel = _cmd;
+}
+
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
@@ -205,19 +210,19 @@
 
 int useRoot(Root *r) {
   // CHECK-LABEL: define{{.*}} i32 @useRoot
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]"
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]" to i32 (i8*)
   return [r getInt] + [r intProperty] + [r intProperty2];
 }
 
 int useFoo(Foo *f) {
   // CHECK-LABEL: define{{.*}} i32 @useFoo
-  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]"
+  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]" to void (i8*, i32)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]" to i32 (i8*)
   [f setGetDynamic_setDirect:1];
   return [f getDirect_setDynamic] +
  [f directMethodInExtension] +
Index: clang/lib/CodeGen/CGObjCMac.cpp
===
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -2145,7 +2145,8 @@
   if (!IsSuper)
 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
   ActualArgs.add(RValue::get(Arg0), Arg0Ty);
-  ActualArgs.add(RValue::get(SelValue), selTy);
+  if (!Method || !Method->isDirectMethod())
+ActualArgs.add(RValue::get(SelValue), selTy);
   ActualArgs.addFrom(CallArgs);
 
   // If we're calling a method, use the formal signature.
@@ -4103,6 +4104,9 @@
 
   // on

[PATCH] D86049: RFC: Implement optional exportable wrapper function generation for objc_direct methods.

2022-08-09 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added inline comments.



Comment at: clang/include/clang/Basic/Attr.td:2251-2256
+def ObjCDirectVisible : Attr {
+  let Spellings = [Clang<"objc_direct_visible">];
+  let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+  let LangOpts = [ObjC];
+  let Documentation = [ObjCDirectVisibleDocs];
+}

Should this inherit `ObjCDirect`, to include both objc_direct and the 
visibility aspect? I don't see any reason we would want to add 
`objc_direct_visible` without also having `objc_direct`, so why make developers 
add both?

As an alternative, would it make sense to allow adding 
`__attribute__((visibility("default")))` on direct methods?

Also, it doesn't seem like this allows making `@property`s visible, so should 
there be a similar attribute for properties?



Comment at: clang/lib/CodeGen/CGObjCMac.cpp:4025-4036
+  if (OMD->isDirectMethodVisible() && Fn->getName().str()[0] == '\1') {
+// Drop '\1' to work with dlsym.
+std::string Name = Fn->getName().str().substr(1);
+
+assert(Name[0] == '-' || Name[0] == '+');
+assert(Name[1] == '[' && Name[Name.length() - 1] == ']');
+

Should this move to clang/lib/AST/Mangle.cpp's mangleObjCMethodName?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86049: RFC: Implement optional exportable wrapper function generation for objc_direct methods.

2022-07-19 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

Hi, I work with @dmaclach. I know this has been sitting around without much 
activity for two years, but we believe there is a solid use-case for this on 
our end and I'd like to help get the ABI nailed down and land this change (or 
one accomplishing the same goal). Do you still have interest in this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128031: Don't emit `-Wnullability-completeness` warnings on `weak` Objective-C properties.

2022-10-19 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 469020.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128031/new/

https://reviews.llvm.org/D128031

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4746,8 +4746,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) 
{
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4746,8 +4746,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128031: Don't emit `-Wnullability-completeness` warnings on `weak` Objective-C properties.

2022-10-20 Thread Michael Wyman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG34020d39b8a1: Don't emit `-Wnullability-completeness` 
warnings on `weak` Objective-C… (authored by mwyman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128031/new/

https://reviews.llvm.org/D128031

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4748,8 +4748,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) 
{
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4748,8 +4748,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-09-20 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a reviewer: ahatanak.
mwyman added a comment.

Hi Akira,

I'd reached out to John offline and he'd mentioned you might be able to help on 
some of these objc_direct reviews; if so, that would be wonderful!

-Michael


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131424/new/

https://reviews.llvm.org/D131424

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-09-21 Thread Michael Wyman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGaa4bcaab9600: Remove the unused/undefined `_cmd` parameter 
in `objc_direct` methods. (authored by mwyman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131424/new/

https://reviews.llvm.org/D131424

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/test/CodeGenObjC/direct-method.m

Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -28,9 +28,7 @@
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -60,9 +58,7 @@
   // loading parameters
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca i8*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store i8* %{{.*}}, i8** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // [self self]
   // CHECK-NEXT: [[SELF:%.*]] = load i8*, i8** [[SELFADDR]],
@@ -81,9 +77,7 @@
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[RETVAL:%.*]] = alloca
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -125,9 +119,7 @@
   // loading parameters
   // CHECK-LABEL: entry:
   // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
-  // CHECK-NEXT: [[_CMDADDR:%.*]] = alloca i8*,
   // CHECK-NEXT: store %0* %{{.*}}, %0** [[SELFADDR]],
-  // CHECK-NEXT: store i8* %{{.*}}, i8** [[_CMDADDR]],
 
   // self nil-check
   // CHECK-NEXT: [[SELF:%.*]] = load %0*, %0** [[SELFADDR]],
@@ -159,6 +151,19 @@
   // CHECK: ret void
 }
 
+// CHECK-LABEL: define hidden void @"\01-[Root accessCmd]"(
+- (void)accessCmd __attribute__((objc_direct)) {
+  // CHECK-LABEL: entry:
+  // CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+  // CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+
+  // loading the _cmd selector
+  // CHECK-LABEL: objc_direct_method.cont:
+  // CHECK-NEXT: [[CMD1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+  // CHECK-NEXT: store i8* [[CMD1]], i8** [[CMDVAL]],
+  SEL sel = _cmd;
+}
+
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
@@ -205,19 +210,19 @@
 
 int useRoot(Root *r) {
   // CHECK-LABEL: define{{.*}} i32 @useRoot
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]"
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]" to i32 (i8*)
   return [r getInt] + [r intProperty] + [r intProperty2];
 }
 
 int useFoo(Foo *f) {
   // CHECK-LABEL: define{{.*}} i32 @useFoo
-  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]"
-  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]"
+  // CHECK: call void bitcast {{.*}} @"\01-[Foo setGetDynamic_setDirect:]" to void (i8*, i32)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo getDirect_setDynamic]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInExtension]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategory]" to i32 (i8*)
+  // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Foo directMethodInCategoryNoDecl]" to i32 (i8*)
   [f setGetDynamic_setDirect:1];
   return [f getDirect_setDynamic] +
  [f directMethodInExtension] +
Index: clang/lib/CodeGen/CGObjCMac.cpp
===
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -2145,7 +2145,8 @@
   if (!IsSuper)
 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
   ActualArgs.add(RValue::get(Arg0), Arg0Ty);
-  ActualArgs.add(RValue::get(SelValue), selTy);
+  if (!Method || !Method->isDirectMethod())
+ActualArgs.add(RValue::get(SelValue), selTy);
   ActualArgs.addFro

[PATCH] D86049: RFC: Implement optional exportable wrapper function generation for objc_direct methods.

2022-09-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D86049#3816006 , @plotfi wrote:

> @dmaclach @ahatanak @mwyman How do things look from here? Do you want 
> something for properties as well or would it be ok if we did this in a later 
> commit?

Huh, for some reason I thought when I'd last poked at using the `visibility` 
attribute it wasn't allowed on ObjC methods, which is why I'd suggested adding 
the enum on `objc_direct`, but as that no longer appears to be the case yes I 
like this approach better.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86049: RFC: Implement optional exportable wrapper function generation for objc_direct methods.

2022-09-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

I think it's reasonable to do `@property` behavior in a follow-up.

Are we thinking to allow `__attribute__((visibility("default")))` on an 
`@property` declaration, to keep the visibility behavior consistent?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86049: RFC: Implement optional exportable wrapper function generation for objc_direct methods.

2022-09-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D86049#3818981 , @plotfi wrote:

> @ahatanak I can revive some of what I was working on from 
> https://reviews.llvm.org/D86049?id=285923 if we think we need a thunk for the 
> checks as @rjmccall mentioned.

I believe the generated direct methods already handle the null checks and class 
init in `CGObjCCommonMac::GenerateDirectMethodPrologue`, meaning the thunks 
aren't strictly necessary for the callee to handle them.

Could the thunks instead allow us to have publicly-visible mangled names 
(something akin to the new selector stubs `_objc_msgSend$selectorName` but for 
`_objc_direct$Class_selectorName`) while leaving the actual impl name alone, 
letting the stack traces see normal ObjC symbol names?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-09-30 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D131424#3828647 , @ahatanak wrote:

> `-fobjc-arc` is needed to see the assertion fail.

Oops, yep I'll send a patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131424/new/

https://reviews.llvm.org/D131424

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135091: Load the `_cmd` selector for generated getters/setters of `direct` Objective-C properties.

2022-10-03 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: ahatanak, plotfi, dmaclach.
mwyman added a project: clang.
Herald added a project: All.
mwyman requested review of this revision.
Herald added a subscriber: cfe-commits.

This fixes a bug from https://reviews.llvm.org/D131424 that removed the 
implicit `_cmd` parameter as an argument to `objc_direct` method 
implementations. In many cases the generated getter/setter will call 
`objc_getProperty` or `objc_setProperty`, both of which require the selector of 
the getter/setter; since `_cmd` didn't automatically have backing storage, 
attempting to load the address asserted.

This adds an explicit load of the selector, similar to if it's referenced in an 
`objc_direct` method body; since the getter/setter is entirely synthesized, 
there's no reason to preemptively load the selector and store it locally, so 
the value is directly loaded and no additional storage is created for it.

Added a test that triggers the assert prior to the implementation code.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,14 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+// CHECK: call i8* @objc_getProperty({{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -1189,8 +1189,17 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+llvm::Value *cmd;
+if (getterMethod->isDirectMethod()) {
+  // Direct methods do not have the `_cmd` parameter; the selector must be
+  // loaded explicitly. Since it is not otherwise used in the getter, there
+  // is no reason to create a local variable for it.
+  cmd =
+  CGM.getObjCRuntime().GetSelector(*this, getterMethod->getSelector());
+} else {
+  cmd = Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()),
+   "cmd");
+}
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,10 +1484,18 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
-llvm::Value *self =
-  Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
+llvm::Value *cmd;
+if (setterMethod->isDirectMethod()) {
+  // Direct methods do not have the `_cmd` parameter; the selector must be
+  // loaded explicitly. Since it is not otherwise used in the setter, there
+  // is no reason to create a local variable for it.
+  cmd =
+  CGM.getObjCRuntime().GetSelector(*this, setterMethod->getSelector());
+} else {
+  cmd = Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()),
+   "cmd");
+}
+llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
 Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,14 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); th

[PATCH] D131424: Remove the unused/undefined _cmd parameter to objc_direct methods.

2022-10-03 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

In D131424#3828656 , @mwyman wrote:

> In D131424#3828647 , @ahatanak 
> wrote:
>
>> `-fobjc-arc` is needed to see the assertion fail.
>
> Oops, yep I'll send a patch.

Sent https://reviews.llvm.org/D135091


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131424/new/

https://reviews.llvm.org/D131424

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 465857.
mwyman retitled this revision from "Load the `_cmd` selector for generated 
getters/setters of `direct` Objective-C properties." to "Create storage for the 
`_cmd` argument to the helper function for generated getters/setters of 
`direct` Objective-C properties.".
mwyman edited the summary of this revision.
mwyman added a comment.

Updated to eliminate loading the selector, as the prior implementation didn't 
pass a valid `_cmd` value (it just re-used the `_cmd` argument in the ABI, 
which was unset by the caller and so undefined in value).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,18 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: entry:
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca i8*,
+// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+// CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK: [[CMD:%.*]] = load i8*, i8** [[CMDVAL]],
+// CHECK: call i8* @objc_getProperty({{.*}}, i8*{{.*}} [[CMD]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -1189,8 +1189,15 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+if (getterMethod->isDirectMethod()) {
+  // Direct methods no longer have a `_cmd` argument, so storage must be
+  // emitted for it to be passed to the property helper. Since the `_cmd`
+  // argument was never being initialized by the caller before, still pass
+  // an uninitialized/undefined value here.
+  EmitVarDecl(*getterMethod->getCmdDecl());
+}
+llvm::Value *cmd = 
Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()),
+ "cmd");
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,10 +1482,16 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
-llvm::Value *self =
-  Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
+if (setterMethod->isDirectMethod()) {
+  // Direct methods no longer have a `_cmd` argument, so storage must be
+  // emitted for it to be passed to the property helper. Since the `_cmd`
+  // argument was never being initialized by the caller before, still pass
+  // an uninitialized/undefined value here.
+  EmitVarDecl(*setterMethod->getCmdDecl());
+}
+llvm::Value *cmd = 
Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()),
+   "cmd");
+llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
 Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,18 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL:

[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked an inline comment as done.
mwyman added inline comments.



Comment at: clang/test/CodeGenObjC/direct-method.m:171-177
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_
+// CHECK: call i8* @objc_getProperty({{.*}})

stephanemoore wrote:
> I'm not intricately familiar with the codegen checking mechanism in these 
> tests but without fully knowing the details, this seems consistent with the 
> checks in `-[Root accessCmd]` above which I would expect to require similar 
> checks.
> 
> Did you check that these added tests reproduce the previous assertion/failure 
> so that we can be confident that the code changes resolve the issue?
Yes, this new test previously triggered the assertion.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 465896.
mwyman marked an inline comment as done.
mwyman added a comment.

Extracted the common new code into a helper function.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,18 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: entry:
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca i8*,
+// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+// CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK: [[CMD:%.*]] = load i8*, i8** [[CMDVAL]],
+// CHECK: call i8* @objc_getProperty({{.*}}, i8*{{.*}} [[CMD]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -,6 +,21 @@
callee, ReturnValueSlot(), args);
 }
 
+// emitCmdLoadForGetterSetterBody - Handle emitting local storage declarations
+// for the `_cmd` argument that no longer exists for direct methods.
+static llvm::Value *emitCmdLoadForGetterSetterBody(CodeGenFunction &CGF,
+   ObjCMethodDecl *MD) {
+  if (MD->isDirectMethod()) {
+// Direct methods no longer have a `_cmd` argument, so storage must be
+// emitted for it to be passed to the property helper. Since the `_cmd`
+// argument was never being initialized by the caller before, still pass
+// an uninitialized/undefined value here.
+CGF.EmitVarDecl(*MD->getCmdDecl());
+  }
+
+  return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), 
"cmd");
+}
+
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl 
*classImpl,
 const ObjCPropertyImplDecl *propImpl,
@@ -1189,8 +1204,7 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+llvm::Value *cmd = emitCmdLoadForGetterSetterBody(*this, getterMethod);
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,8 +1489,7 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
+llvm::Value *cmd = emitCmdLoadForGetterSetterBody(*this, setterMethod);
 llvm::Value *self =
   Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,18 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method accesses _cmd (or rather loads the
+// selector, as it is an argument to objc_getProperty).
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: entry:
+// CHECK-NEXT: [[RETVAL:%.*]] = alloca i8*,
+// CHECK-NEXT: [[SELFADDR:%.*]] = alloca %0*,
+// CHECK-NEXT: [[CMDVAL:%_cmd]] = alloca i8*,
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK: [[CMD:%.*]] = load i8*, i8** [[CMDVAL]],
+// CHECK: call i8* @objc_getProperty({{.*}}, i8*{{.*}} [[CMD]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clan

[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 465925.
mwyman added a comment.
Herald added a subscriber: nlopes.

Use explicit `undef` for the `cmd` parameter to 
`objc_getProperty`/`objc_setProperty` rather declaring and not initializing 
storage for the implicit `_cmd`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
+// CHECK-NEXT: [[SELF:%.*]] = bitcast {{.*}} [[SELFVAL]] to i8*
+// CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
+// CHECK-NEXT: call i8* @objc_getProperty(i8* noundef [[SELF]], i8* noundef 
undef, i64 noundef [[IVAR]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/ObjCARCUtil.h"
 #include "llvm/BinaryFormat/MachO.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InlineAsm.h"
 using namespace clang;
@@ -,6 +1112,22 @@
callee, ReturnValueSlot(), args);
 }
 
+// emitCmdLoadForGetterSetterBody - Handle emitting local storage declarations
+// for the `_cmd` argument that no longer exists for direct methods.
+static llvm::Value *emitCmdLoadForGetterSetterBody(CodeGenFunction &CGF,
+   ObjCMethodDecl *MD) {
+  if (MD->isDirectMethod()) {
+// Direct methods no longer have a `_cmd` argument, so storage must be
+// emitted for it to be passed to the property helper. Since the `_cmd`
+// argument was never being initialized by the caller before, still pass
+// an uninitialized/undefined value here.
+llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+return llvm::UndefValue::get(selType);
+  }
+
+  return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), 
"cmd");
+}
+
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl 
*classImpl,
 const ObjCPropertyImplDecl *propImpl,
@@ -1189,8 +1206,7 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+llvm::Value *cmd = emitCmdLoadForGetterSetterBody(*this, getterMethod);
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,8 +1491,7 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
+llvm::Value *cmd = emitCmdLoadForGetterSetterBody(*this, setterMethod);
 llvm::Value *self =
   Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
+// CHECK-NEXT: [[SELF:%.*]] = bitcast {{.*}} [[SELFVAL]] to i8*
+// CHECK-NEXT: [[IVAR:%.

[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 2 inline comments as done.
mwyman added inline comments.



Comment at: clang/lib/CodeGen/CGObjC.cpp:1116
+// for the `_cmd` argument that no longer exists for direct methods.
+static llvm::Value *emitCmdLoadForGetterSetterBody(CodeGenFunction &CGF,
+   ObjCMethodDecl *MD) {

ahatanak wrote:
> Since this is loading from an uninitialized alloca, can we just pass an 
> `undef` to the call to `objc_get/setProperty`? The optimization passes will 
> just do that, but we can still reduce the code size at `-O0`.
Great suggestion! Done.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added inline comments.



Comment at: clang/lib/CodeGen/CGObjC.cpp:1125
+llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+return llvm::UndefValue::get(selType);
+  }

nlopes wrote:
> Please consider using PoisonValue here instead (if appropriate). We are 
> trying to get rid of undef.
> Thank you!
> A poison value is a result of an erroneous operation.

I could very well be misunderstanding, but based on this description from 
LangRef.html `PoisonValue` doesn't seem appropriate here; this is not 
"erroneous" behavior: it is just continuing the behavior prior to removing the 
`_cmd` implicit argument from the ABI, which was that the value was `undef` 
from the generated getter/setter's caller.

https://github.com/llvm/llvm-project/blob/49acab3f1408be9439a57833aa7b67678c9a05ba/clang/lib/CodeGen/CGObjCMac.cpp#L2142

Since this is (essentially) replicating that behavior, I'm not sure 
`PoisonValue` is what we want.



Comment at: clang/test/CodeGenObjC/direct-method.m:178
+// CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
+// CHECK-NEXT: call i8* @objc_getProperty(i8* noundef [[SELF]], i8* noundef 
undef, i64 noundef [[IVAR]], {{.*}})
+

ahatanak wrote:
> `noundef` means the value isn't undefined, right? Is it safe to use it with 
> `undef`? We might want to fix this if it isn't.
It does feel questionable, however the pre-D131424 behavior was similar with 
the `undef` value coming from the caller and opaque to these generated 
getters/setters.

At least according to the OSS drop of `libobjc`, nothing in 
`objc_getProperty`/`objc_setProperty` actually references the `_cmd` argument 
so it seems safe-ish for now: 
https://github.com/apple-oss-distributions/objc4/blob/8701d5672d3fd3cd817aeb84db1077aafe1a1604/runtime/objc-accessors.mm#L48

FWIW, searching the code, I do see a handful of `noundef undef` in some other 
tests.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 466212.
mwyman edited the summary of this revision.
mwyman added a comment.

Updated to use `PoisonValue` rather than `UndefValue`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
+// CHECK-NEXT: [[SELF:%.*]] = bitcast {{.*}} [[SELFVAL]] to i8*
+// CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
+// CHECK-NEXT: call i8* @objc_getProperty(i8* noundef [[SELF]], i8* noundef 
poison, i64 noundef [[IVAR]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/ObjCARCUtil.h"
 #include "llvm/BinaryFormat/MachO.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InlineAsm.h"
 using namespace clang;
@@ -,6 +1112,25 @@
callee, ReturnValueSlot(), args);
 }
 
+// emitCmdValueForGetterSetterBody - Handle emitting the load necessary for
+// the `_cmd` selector argument for getter/setter bodies. For direct methods,
+// this returns an undefined/poison value; this matches behavior prior to 
`_cmd`
+// being removed from the direct method ABI as the getter/setter caller would
+// never load one. For non-direct methods, this emits a load of the implicit
+// `_cmd` storage.
+static llvm::Value *emitCmdValueForGetterSetterBody(CodeGenFunction &CGF,
+   ObjCMethodDecl *MD) {
+  if (MD->isDirectMethod()) {
+// Direct methods do not have a `_cmd` argument. Emit an undefined/poison
+// value. This will be passed to objc_getProperty/objc_setProperty, which
+// has not appeared bothered by the `_cmd` argument being undefined before.
+llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+return llvm::PoisonValue::get(selType);
+  }
+
+  return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), 
"cmd");
+}
+
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl 
*classImpl,
 const ObjCPropertyImplDecl *propImpl,
@@ -1189,8 +1209,7 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod);
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,8 +1494,7 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
+llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, setterMethod);
 llvm::Value *self =
   Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-N

[PATCH] D135091: Create storage for the `_cmd` argument to the helper function for generated getters/setters of `direct` Objective-C properties.

2022-10-07 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 2 inline comments as done.
mwyman added inline comments.



Comment at: clang/lib/CodeGen/CGObjC.cpp:1125
+llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+return llvm::UndefValue::get(selType);
+  }

nlopes wrote:
> mwyman wrote:
> > nlopes wrote:
> > > Please consider using PoisonValue here instead (if appropriate). We are 
> > > trying to get rid of undef.
> > > Thank you!
> > > A poison value is a result of an erroneous operation.
> > 
> > I could very well be misunderstanding, but based on this description from 
> > LangRef.html `PoisonValue` doesn't seem appropriate here; this is not 
> > "erroneous" behavior: it is just continuing the behavior prior to removing 
> > the `_cmd` implicit argument from the ABI, which was that the value was 
> > `undef` from the generated getter/setter's caller.
> > 
> > https://github.com/llvm/llvm-project/blob/49acab3f1408be9439a57833aa7b67678c9a05ba/clang/lib/CodeGen/CGObjCMac.cpp#L2142
> > 
> > Since this is (essentially) replicating that behavior, I'm not sure 
> > `PoisonValue` is what we want.
> If the value is not used, then it can be poison.
> If it gets used somehow then it depends on the callers. I don't know anything 
> about ObjC to know what the right answer is here.
> As we want to remove undef, the fewer the uses the better. Thank you!
Fair enough. I've changed to pass poison into the helper functions.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135091: Fix assert in generated `direct` property getter/setters due to removal of `_cmd` parameter.

2022-10-10 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 466602.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
+// CHECK-NEXT: [[SELF:%.*]] = bitcast {{.*}} [[SELFVAL]] to i8*
+// CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
+// CHECK-NEXT: call i8* @objc_getProperty(i8* noundef [[SELF]], i8* noundef 
poison, i64 noundef [[IVAR]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/ObjCARCUtil.h"
 #include "llvm/BinaryFormat/MachO.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InlineAsm.h"
 using namespace clang;
@@ -,6 +1112,25 @@
callee, ReturnValueSlot(), args);
 }
 
+// emitCmdValueForGetterSetterBody - Handle emitting the load necessary for
+// the `_cmd` selector argument for getter/setter bodies. For direct methods,
+// this returns an undefined/poison value; this matches behavior prior to 
`_cmd`
+// being removed from the direct method ABI as the getter/setter caller would
+// never load one. For non-direct methods, this emits a load of the implicit
+// `_cmd` storage.
+static llvm::Value *emitCmdValueForGetterSetterBody(CodeGenFunction &CGF,
+   ObjCMethodDecl *MD) {
+  if (MD->isDirectMethod()) {
+// Direct methods do not have a `_cmd` argument. Emit an undefined/poison
+// value. This will be passed to objc_getProperty/objc_setProperty, which
+// has not appeared bothered by the `_cmd` argument being undefined before.
+llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+return llvm::PoisonValue::get(selType);
+  }
+
+  return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), 
"cmd");
+}
+
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl 
*classImpl,
 const ObjCPropertyImplDecl *propImpl,
@@ -1189,8 +1209,7 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod);
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,8 +1494,7 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
+llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, setterMethod);
 llvm::Value *self =
   Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
+// CHECK-NEXT: [[SELF:%.*]] = bitcast {{.*}} [[SELFVAL]] to i8*
+// CHECK-NEX

[PATCH] D135091: Fix assert in generated `direct` property getter/setters due to removal of `_cmd` parameter.

2022-10-11 Thread Michael Wyman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1fbb6d8b34de: Fix assert in generated `direct` property 
getter/setters due to removal of… (authored by mwyman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135091/new/

https://reviews.llvm.org/D135091

Files:
  clang/lib/CodeGen/CGObjC.cpp
  clang/test/CodeGenObjC/direct-method.m


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cmd` argument.
+// CHECK-LABEL: define hidden i8* @"\01-[Root objectProperty]"(
+// CHECK-LABEL: objc_direct_method.cont:
+// CHECK-NEXT: [[SELFVAL:%.*]] = load {{.*}} %self.addr,
+// CHECK-NEXT: [[SELF:%.*]] = bitcast {{.*}} [[SELFVAL]] to i8*
+// CHECK-NEXT: [[IVAR:%.*]] = load {{.*}} @"OBJC_IVAR_$_Root._objectProperty",
+// CHECK-NEXT: call i8* @objc_getProperty(i8* noundef [[SELF]], i8* noundef 
poison, i64 noundef [[IVAR]], {{.*}})
+
 @interface Foo : Root {
   id __strong _cause_cxx_destruct;
 }
Index: clang/lib/CodeGen/CGObjC.cpp
===
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Analysis/ObjCARCUtil.h"
 #include "llvm/BinaryFormat/MachO.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InlineAsm.h"
 using namespace clang;
@@ -,6 +1112,25 @@
callee, ReturnValueSlot(), args);
 }
 
+// emitCmdValueForGetterSetterBody - Handle emitting the load necessary for
+// the `_cmd` selector argument for getter/setter bodies. For direct methods,
+// this returns an undefined/poison value; this matches behavior prior to 
`_cmd`
+// being removed from the direct method ABI as the getter/setter caller would
+// never load one. For non-direct methods, this emits a load of the implicit
+// `_cmd` storage.
+static llvm::Value *emitCmdValueForGetterSetterBody(CodeGenFunction &CGF,
+   ObjCMethodDecl *MD) {
+  if (MD->isDirectMethod()) {
+// Direct methods do not have a `_cmd` argument. Emit an undefined/poison
+// value. This will be passed to objc_getProperty/objc_setProperty, which
+// has not appeared bothered by the `_cmd` argument being undefined before.
+llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+return llvm::PoisonValue::get(selType);
+  }
+
+  return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), 
"cmd");
+}
+
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl 
*classImpl,
 const ObjCPropertyImplDecl *propImpl,
@@ -1189,8 +1209,7 @@
 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
 // FIXME: Can't this be simpler? This might even be worse than the
 // corresponding gcc code.
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod);
 llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =
   EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -1475,8 +1494,7 @@
 
 // Emit objc_setProperty((id) self, _cmd, offset, arg,
 //   , ).
-llvm::Value *cmd =
-  Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
+llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, setterMethod);
 llvm::Value *self =
   Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
 llvm::Value *ivarOffset =


Index: clang/test/CodeGenObjC/direct-method.m
===
--- clang/test/CodeGenObjC/direct-method.m
+++ clang/test/CodeGenObjC/direct-method.m
@@ -14,6 +14,7 @@
 - (int)getInt __attribute__((objc_direct));
 @property(direct, readonly) int intProperty;
 @property(direct, readonly) int intProperty2;
+@property(direct, readonly) id objectProperty;
 @end
 
 @implementation Root
@@ -167,6 +168,15 @@
 @end
 // CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
 
+// Check the synthesized objectProperty calls objc_getProperty(); this also
+// checks that the synthesized method passes undef for the `cm

[PATCH] D128031: Don't emit `-Wnullability-completeness` warnings on `weak` Objective-C properties.

2022-06-16 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: dmaclach, stephanemoore.
mwyman added a project: clang.
Herald added a project: All.
mwyman requested review of this revision.
Herald added a subscriber: cfe-commits.

Zeroing weak references are by definition `nullable`, and adding `nonnull` or 
`_Nonnull` yields a mutual-exclusivity error. However, when 
`-Wnullability-completeness` is enabled, in non-audited header regions it's 
necessary to add the `nullable` property keyword to avoid a warning. It should 
not be necessary to add code clutter to restate the nullability of a `weak` 
property even under `-Wnullability-completeness`.

Additionally, the fix-it hints are both non-idiomatic Objective-C (adding 
`_Nullable` to the property's pointer type rather than in the `@property` 
attributes) and suggest the option of adding `_Nonnull` (which would be an 
error).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128031

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing 
a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4683,8 +4683,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) 
{
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 


Index: clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
===
--- clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ clang/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -19,13 +19,9 @@
 @property (retain,nullable) SomeClass *property2;
 - (nullable SomeClass *)method1;
 - (void)method2:(nonnull SomeClass *)param;
-@property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property3;
 @end
 
 @interface SomeClass ()
-@property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}}
-// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
-// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+@property (readonly, weak) SomeClass *property4;
 @end
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -4683,8 +4683,13 @@
   }
 
   // Weak properties are inferred to be nullable.
-  if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
-inferNullability = NullabilityKind::Nullable;
+  if (state.getDeclarator().isObjCWeakProperty()) {
+// Weak properties cannot be nonnull, and should not complain about
+// missing nullable attributes during completeness checks.
+complainAboutMissingNullability = CAMN_No;
+if (inAssumeNonNullRegion) {
+  inferNullability = NullabilityKind::Nullable;
+}
 break;
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128031: Don't emit `-Wnullability-completeness` warnings on `weak` Objective-C properties.

2022-06-17 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

Created Github issue to track: https://github.com/llvm/llvm-project/issues/56096


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128031/new/

https://reviews.llvm.org/D128031

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128556: Make Objective-C++ match Objective-C's behavior on implicit ivar access when `self` is shadowed

2022-06-24 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added a project: clang.
Herald added a project: All.
mwyman requested review of this revision.
Herald added a subscriber: cfe-commits.

When compiling Objective-C++, name lookup uses the C++ lookup behavior that 
skips the filtering of non-implicit-self references, and will use a shadowed 
name that matches the type. As a result implicit ivar access behavior differs 
between Objective-C and Objective-C++, which can impact local access but also 
block captures.

This addresses the issue #56193 
 as reported on Github.

Unfortunately it appears the behavior has differed for 11 years (since the 
original fix for ObjC was applied in 2011).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128556

Files:
  clang/lib/Sema/SemaLookup.cpp


Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -1313,6 +1313,9 @@
 R.setShadowed();
 continue;
   }
+} else if (NameKind == LookupObjCImplicitSelfParam &&
+   !isa(*I)) {
+  continue;
 } else {
   // We found something in this scope, we should not look at the
   // namespace scope


Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -1313,6 +1313,9 @@
 R.setShadowed();
 continue;
   }
+} else if (NameKind == LookupObjCImplicitSelfParam &&
+   !isa(*I)) {
+  continue;
 } else {
   // We found something in this scope, we should not look at the
   // namespace scope
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126522: Create specialization of `-Wgnu-statement-expression` for expressions found in macros.

2022-05-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: stephanemoore, hokein, ymandel, dmaclach.
mwyman added a project: clang.
Herald added a project: All.
mwyman requested review of this revision.
Herald added a subscriber: cfe-commits.

`-Wgnu-statement-expression` currently warns for both direct source uses of 
statement expressions but also macro expansions; since they may be used by 
macros to avoid multiple evaluation of macro arguments, engineers might want to 
suppress warnings when statement expressions are expanded from macros but see 
them if introduced directly in source code.

This change adds the warning flag `-Wgnu-statement-expression-macro` to 
enable/disable diagnostics generated from macro expansions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126522

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseExpr.cpp
  clang/test/Sema/gnu-flags.c


Index: clang/test/Sema/gnu-flags.c
===
--- clang/test/Sema/gnu-flags.c
+++ clang/test/Sema/gnu-flags.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu
-// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu 
+// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-alignof-expression -Wgnu-case-range -Wgnu-complex-integer 
-Wgnu-conditional-omitted-operand \
 // RUN:   -Wgnu-empty-initializer -Wgnu-label-as-value 
-Wgnu-statement-expression \
@@ -20,6 +20,7 @@
 // %clang_cc1 -fsyntax-only -verify %s -DEMPTYINIT -Wno-gnu 
-Wgnu-empty-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DLABELVALUE -Wno-gnu 
-Wgnu-label-as-value
 // %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXP -Wno-gnu 
-Wgnu-statement-expression
+// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXPMACRO -Wno-gnu 
-Wgnu-statement-expression-macro
 // %clang_cc1 -fsyntax-only -verify %s -DCOMPOUNDLITERALINITIALIZER -Wno-gnu 
-Wgnu-compound-literal-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYINITIALIZER -Wno-gnu 
-Wgnu-flexible-array-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDENUM -Wno-gnu 
-Wgnu-redeclared-enum
@@ -95,6 +96,14 @@
int a = ({ 1; });
 }
 
+#if ALL || STATEMENTEXPMACRO
+// expected-warning@+5 {{use of GNU statement expression extension from macro 
expansion}}
+#endif
+
+#define STMT_EXPR_MACRO(a) ({ (a); })
+void statementexprmacro(void) {
+  int a = STMT_EXPR_MACRO(1);
+}
 
 #if ALL || COMPOUNDLITERALINITIALIZER
 // expected-warning@+4 {{initialization of an array of type 'int[5]' from a 
compound literal of type 'int[5]' is a GNU extension}}
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2870,7 +2870,8 @@
   // None of these cases should fall through with an invalid Result
   // unless they've already reported an error.
   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
-Diag(Tok, diag::ext_gnu_statement_expr);
+Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro
+  : diag::ext_gnu_statement_expr);
 
 checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin);
 
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -174,6 +174,9 @@
   "statement expression not allowed at file scope">;
 def ext_gnu_statement_expr : Extension<
   "use of GNU statement expression extension">, 
InGroup;
+def ext_gnu_statement_expr_macro : Extension<
+  "use of GNU statement expression extension from macro expansion">,
+  InGroup;
 def ext_gnu_conditional_expr : Extension<
   "use of GNU ?: conditional expression extension, omitting middle operand">, 
InGroup;
 def ext_gnu_empty_initializer : Extension<
Index: clang/include/clang/Basic/DiagnosticGroups.td
===
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -611,7 +611,11 @@
 def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
 def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
 def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
-def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
+// Allow differentiation between GNU statement expressions in a macro versus
+// written directly in source.
+def GNUStatementExpressionMacro : DiagGroup<"gnu-statement-expression-macro">;
+def GNUStatementExpression : DiagGroup<"gnu-statement-expression",
+   [GNUStatementExpressionMacro]>;
 def StringConcatation : DiagGroup<"string-concaten

[PATCH] D126522: Create specialization of `-Wgnu-statement-expression` for expressions found in macros.

2022-05-26 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 432471.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126522/new/

https://reviews.llvm.org/D126522

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseExpr.cpp
  clang/test/Sema/gnu-flags.c


Index: clang/test/Sema/gnu-flags.c
===
--- clang/test/Sema/gnu-flags.c
+++ clang/test/Sema/gnu-flags.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu
-// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu 
+// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-alignof-expression -Wgnu-case-range -Wgnu-complex-integer 
-Wgnu-conditional-omitted-operand \
 // RUN:   -Wgnu-empty-initializer -Wgnu-label-as-value 
-Wgnu-statement-expression \
@@ -20,6 +20,7 @@
 // %clang_cc1 -fsyntax-only -verify %s -DEMPTYINIT -Wno-gnu 
-Wgnu-empty-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DLABELVALUE -Wno-gnu 
-Wgnu-label-as-value
 // %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXP -Wno-gnu 
-Wgnu-statement-expression
+// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXPMACRO -Wno-gnu 
-Wgnu-statement-expression-from-macro-expansion
 // %clang_cc1 -fsyntax-only -verify %s -DCOMPOUNDLITERALINITIALIZER -Wno-gnu 
-Wgnu-compound-literal-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYINITIALIZER -Wno-gnu 
-Wgnu-flexible-array-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDENUM -Wno-gnu 
-Wgnu-redeclared-enum
@@ -95,6 +96,14 @@
int a = ({ 1; });
 }
 
+#if ALL || STATEMENTEXP || STATEMENTEXPMACRO
+// expected-warning@+5 {{use of GNU statement expression extension from macro 
expansion}}
+#endif
+
+#define STMT_EXPR_MACRO(a) ({ (a); })
+void statementexprmacro(void) {
+  int a = STMT_EXPR_MACRO(1);
+}
 
 #if ALL || COMPOUNDLITERALINITIALIZER
 // expected-warning@+4 {{initialization of an array of type 'int[5]' from a 
compound literal of type 'int[5]' is a GNU extension}}
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2870,7 +2870,8 @@
   // None of these cases should fall through with an invalid Result
   // unless they've already reported an error.
   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
-Diag(Tok, diag::ext_gnu_statement_expr);
+Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro
+  : diag::ext_gnu_statement_expr);
 
 checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin);
 
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -174,6 +174,9 @@
   "statement expression not allowed at file scope">;
 def ext_gnu_statement_expr : Extension<
   "use of GNU statement expression extension">, 
InGroup;
+def ext_gnu_statement_expr_macro : Extension<
+  "use of GNU statement expression extension from macro expansion">,
+  InGroup;
 def ext_gnu_conditional_expr : Extension<
   "use of GNU ?: conditional expression extension, omitting middle operand">, 
InGroup;
 def ext_gnu_empty_initializer : Extension<
Index: clang/include/clang/Basic/DiagnosticGroups.td
===
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -611,7 +611,12 @@
 def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
 def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
 def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
-def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
+// Allow differentiation between GNU statement expressions in a macro versus
+// written directly in source.
+def GNUStatementExpressionFromMacroExpansion :
+  DiagGroup<"gnu-statement-expression-from-macro-expansion">;
+def GNUStatementExpression : DiagGroup<"gnu-statement-expression",
+   
[GNUStatementExpressionFromMacroExpansion]>;
 def StringConcatation : DiagGroup<"string-concatenation">;
 def StringCompare : DiagGroup<"string-compare">;
 def StringPlusInt : DiagGroup<"string-plus-int">;


Index: clang/test/Sema/gnu-flags.c
===
--- clang/test/Sema/gnu-flags.c
+++ clang/test/Sema/gnu-flags.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu
-// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu 
+// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-alignof-expression -Wgnu-case-ra

[PATCH] D126522: Create specialization of `-Wgnu-statement-expression` for expressions found in macros.

2022-05-31 Thread Michael Wyman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7689c7fc9e08: Create specialization of 
-Wgnu-statement-expression for expressions found in… (authored by mwyman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126522/new/

https://reviews.llvm.org/D126522

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseExpr.cpp
  clang/test/Sema/gnu-flags.c


Index: clang/test/Sema/gnu-flags.c
===
--- clang/test/Sema/gnu-flags.c
+++ clang/test/Sema/gnu-flags.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu
-// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu 
+// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-alignof-expression -Wgnu-case-range -Wgnu-complex-integer 
-Wgnu-conditional-omitted-operand \
 // RUN:   -Wgnu-empty-initializer -Wgnu-label-as-value 
-Wgnu-statement-expression \
@@ -20,6 +20,7 @@
 // %clang_cc1 -fsyntax-only -verify %s -DEMPTYINIT -Wno-gnu 
-Wgnu-empty-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DLABELVALUE -Wno-gnu 
-Wgnu-label-as-value
 // %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXP -Wno-gnu 
-Wgnu-statement-expression
+// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXPMACRO -Wno-gnu 
-Wgnu-statement-expression-from-macro-expansion
 // %clang_cc1 -fsyntax-only -verify %s -DCOMPOUNDLITERALINITIALIZER -Wno-gnu 
-Wgnu-compound-literal-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYINITIALIZER -Wno-gnu 
-Wgnu-flexible-array-initializer
 // %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDENUM -Wno-gnu 
-Wgnu-redeclared-enum
@@ -95,6 +96,14 @@
int a = ({ 1; });
 }
 
+#if ALL || STATEMENTEXP || STATEMENTEXPMACRO
+// expected-warning@+5 {{use of GNU statement expression extension from macro 
expansion}}
+#endif
+
+#define STMT_EXPR_MACRO(a) ({ (a); })
+void statementexprmacro(void) {
+  int a = STMT_EXPR_MACRO(1);
+}
 
 #if ALL || COMPOUNDLITERALINITIALIZER
 // expected-warning@+4 {{initialization of an array of type 'int[5]' from a 
compound literal of type 'int[5]' is a GNU extension}}
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2870,7 +2870,8 @@
   // None of these cases should fall through with an invalid Result
   // unless they've already reported an error.
   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
-Diag(Tok, diag::ext_gnu_statement_expr);
+Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro
+  : diag::ext_gnu_statement_expr);
 
 checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin);
 
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -174,6 +174,9 @@
   "statement expression not allowed at file scope">;
 def ext_gnu_statement_expr : Extension<
   "use of GNU statement expression extension">, 
InGroup;
+def ext_gnu_statement_expr_macro : Extension<
+  "use of GNU statement expression extension from macro expansion">,
+  InGroup;
 def ext_gnu_conditional_expr : Extension<
   "use of GNU ?: conditional expression extension, omitting middle operand">, 
InGroup;
 def ext_gnu_empty_initializer : Extension<
Index: clang/include/clang/Basic/DiagnosticGroups.td
===
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -611,7 +611,12 @@
 def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
 def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
 def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
-def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
+// Allow differentiation between GNU statement expressions in a macro versus
+// written directly in source.
+def GNUStatementExpressionFromMacroExpansion :
+  DiagGroup<"gnu-statement-expression-from-macro-expansion">;
+def GNUStatementExpression : DiagGroup<"gnu-statement-expression",
+   
[GNUStatementExpressionFromMacroExpansion]>;
 def StringConcatation : DiagGroup<"string-concatenation">;
 def StringCompare : DiagGroup<"string-compare">;
 def StringPlusInt : DiagGroup<"string-plus-int">;


Index: clang/test/Sema/gnu-flags.c
===
--- clang/test/Sema/gnu-flags.c
+++ clang/test/Sema/gnu-flags.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu
-// RUN: %clang_cc1 -fsy

[PATCH] D75569: New ClangTidy check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-03 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Such method declarations don't provide any benefit, as even without the 
declaration the compiler would complain about calling the method as it doesn't 
exist.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,41 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override %t
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+- (instancetype)initWithInt:(int)anInt;
+
+- (void)methodA __attribute__((unavailable));
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodA' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+
+// Verify the check catches the unavailable attribute when a message is provided.
+- (void)methodB __attribute__((unavailable("use methodD")));
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodB' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+
+#define NS_UNAVAILABLE __attribute__((unavailable))
+
+// Verify the check works with macros declaring the unavailable attribute.
+- (void)methodC NS_UNAVAILABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodC' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+@end
+
+
+@implementation MyObject
+
+- (instancetype)initWithInt:(int)anInt {
+  return 0;
+}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
+
+// Verify that fixes exist to delete entire method declarations:
+// CHECK-FIXES: {{^\s*$}}
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with __attribute__((unavailable)) is overriding
+a method declaration from a superclass. That declaration can usually be
+deleted entirely.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
+
+Suggests a fix to remove the method declaration entirely.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-override `_, "Yes"
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
`objc-super-self `_, "Yes"
@@ -283,7 +284,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get `_, "Yes"
-   `readability-redundant-string-cstr `_,
+   `readability-redundant-string-cstr `_, "Yes"
`readability-redundant-string-init `_, "Yes"
`readability-simplify-boolean-expr `_, "Yes"
`readability-simplify-subscript-expr `_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -98,6 +98,12 @@
 
   Finds recursive functions and diagnoses them.
 
+- New :doc:`objc-method-unavailable-not-override
+  ` check.
+
+  Finds methods marked unavailable that do not override any method from a
+  superclass.
+
 New check aliases
 ^
 
@@ -115,7 +121,7 @@
 ^^
 
 - 

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-04 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 248396.
mwyman added a comment.

Updated to explicitly check for __attribute__((unavailable)), to avoid flagging 
methods marked based on platform availability. Updated test file to validate 
this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override -target x86_64-apple-macosx %t
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+
+// Define conditionally-available methods; when unavailable due to platform
+// availability, these methods should not warn.
+- (void)macMethod __attribute__((availability(macosx,introduced=10.10))) __attribute__((availability(ios,unavailable)));
+- (void)iosMethod __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(macosx,unavailable)));
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+
+// A new method that is not overriding, and is available, should not trigger.
+- (void)notOverridingMethod;
+
+// Test that marking methods unavailable, that were defined in a superclass but
+// conditionally unavailable based on target, don't warn.
+- (void)macMethod __attribute__((unavailable));
+- (void)iosMethod __attribute__((unavailable));
+
+- (void)methodA __attribute__((unavailable));
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodA' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+
+// Verify check when unavailable attribute has a message.
+- (void)methodB __attribute__((unavailable("use methodD")));
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodB' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+
+#define NS_UNAVAILABLE __attribute__((unavailable))
+
+// Verify check when using a macro that expands to the unavailable attribute.
+- (void)methodC NS_UNAVAILABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodC' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+@end
+
+
+@implementation MyObject
+
+- (void)notOverridingMethod {}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
+
+// Verify that fixes exist to delete entire method declarations:
+// CHECK-FIXES: {{^\s*$}}
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with __attribute__((unavailable)) is overriding
+a method declaration from a superclass. That declaration can usually be
+deleted entirely.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
+
+Suggests a fix to remove the method declaration entirely.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-override `_, "Yes"
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
`objc-super-self `_, "Yes"
@@ -283,7 +284,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get `_, "Yes"
-   `readability-redundant-string-cstr `_,
+   `readability-redundant-st

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-04 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 248399.
mwyman added a comment.

Updated documentation per review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,51 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override -target x86_64-apple-macosx %t
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+
+// Define conditionally-available methods; when unavailable due to platform
+// availability, these methods should not warn.
+- (void)macMethod __attribute__((availability(macosx,introduced=10.10))) __attribute__((availability(ios,unavailable)));
+- (void)iosMethod __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(macosx,unavailable)));
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+
+// A new method that is not overriding, and is available, should not trigger.
+- (void)notOverridingMethod;
+
+// Test that marking methods unavailable, that were defined in a superclass but
+// conditionally unavailable based on target, don't warn.
+- (void)macMethod __attribute__((unavailable));
+- (void)iosMethod __attribute__((unavailable));
+
+- (void)methodA __attribute__((unavailable));
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodA' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+
+// Verify check when unavailable attribute has a message.
+- (void)methodB __attribute__((unavailable("use methodD")));
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodB' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+
+#define NS_UNAVAILABLE __attribute__((unavailable))
+
+// Verify check when using a macro that expands to the unavailable attribute.
+- (void)methodC NS_UNAVAILABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodC' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+@end
+
+
+@implementation MyObject
+
+- (void)notOverridingMethod {}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
+
+// Verify that fixes exist to delete entire method declarations:
+// CHECK-FIXES: {{^\s*$}}
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with ``__attribute__((unavailable))`` is overriding
+a method declaration from a superclass. That declaration can usually be
+deleted entirely.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
+
+Suggests a fix to remove the method declaration entirely.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-override `_, "Yes"
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
`objc-super-self `_, "Yes"
@@ -283,7 +284,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get `_, "Yes"
-   `readability-redundant-string-cstr `_,
+   `readability-redundant-string-cstr `_, "Yes"
`readability-redundant-string-init `_, "Yes"
`readability-simplify-boolean-expr `_, "Yes"

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-05 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 6 inline comments as done.
mwyman added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m:34
+// Verify check when using a macro that expands to the unavailable attribute.
+- (void)methodC NS_UNAVAILABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodC' is marked 
unavailable but does not override a superclass method 
[objc-method-unavailable-not-override]

njames93 wrote:
> Generally we are cautious about modifying MACRO usages in clang_tidy as we 
> don't know if its definition can change based on configuration, perhaps its 
> safer to just warn instead of providing a fix it
Sounds reasonable; I made this the default behavior.

However for Objective-C, it's quite common for developers to use a macro from 
the Apple SDKs like NS_UNAVAILABLE that are unconditional in any situations I 
know of. I added a config option to allow whitelisting macros that should have 
fix-its provided.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m:51
+// Verify that fixes exist to delete entire method declarations:
+// CHECK-FIXES: {{^\s*$}}

njames93 wrote:
> This is not a satisfactory check, it will ensure at least one method has been 
> deleted but it wont ensure all methods have been deleted. Would probably be 
> safer putting a unique comment on the line and having a check fix that checks 
> for an empty line and the comment for each case.
Thanks for the suggestion! Done.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-05 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 2 inline comments as done.
mwyman added a comment.

I goofed on updating with Arcanist—the changes I marked done will be incoming 
shortly!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-05 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 248611.
mwyman added a comment.

Don't provide fix-it hints when the unavailable attribute is inside a macro, 
unless within a config-whitelisted macro.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,52 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: objc-method-unavailable-not-override.FixMacroNames, \
+// RUN:  value: "UNAVAILABLE_FIXIT"} \
+// RUN: ]}' --
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+
+// A new method that is not overriding, and is available, should not trigger.
+- (void)notOverridingMethod;
+
+- (void)methodA __attribute__((unavailable)); // methodA
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: method 'methodA' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodA{{$}}
+
+// Verify check when unavailable attribute has a message.
+- (void)methodB __attribute__((unavailable("use methodE"))); // methodB
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: method 'methodB' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodB{{$}}
+
+#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
+#define UNAVAILABLE_FIXIT UNAVAILABLE_ATTRIBUTE
+#define UNAVAILABLE_NO_FIXIT UNAVAILABLE_ATTRIBUTE
+
+// Verify check with fix-it when using an configured macro that expands to the unavailable attribute.
+- (void)methodC UNAVAILABLE_FIXIT; // methodC
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: method 'methodC' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodC{{$}}
+
+// Verify check without fix-it when using a non-configured macro that expands to the unavailable attribute.
+- (void)methodD UNAVAILABLE_NO_FIXIT; // methodD
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: method 'methodD' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES-NOT: {{^\s*}}// methodD{{$}}
+@end
+
+
+@implementation MyObject
+
+- (void)notOverridingMethod {}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with ``__attribute__((unavailable))`` is overriding
+a method declaration from a superclass. That declaration can usually be
+deleted entirely.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
+
+Suggests a fix to remove the method declaration entirely.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-override `_, "Yes"
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
`objc-super-self `_, "Yes"
@@ -283,7 +284,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-05 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked an inline comment as done.
mwyman added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp:80
+void MethodUnavailableNotOverrideCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().ObjC)
+return;

njames93 wrote:
> This check is surplus to requirements now that there is the 
> `isLanguageVersionSupported` check
Oops, forgot to delete it here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-05 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 248654.
mwyman marked 4 inline comments as done.
mwyman added a comment.

Updated per review feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,52 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: objc-method-unavailable-not-override.FixMacroNames, \
+// RUN:  value: "UNAVAILABLE_FIXIT"} \
+// RUN: ]}' --
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+
+// A new method that is not overriding, and is available, should not trigger.
+- (void)notOverridingMethod;
+
+- (void)methodA __attribute__((unavailable)); // methodA
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: method 'methodA' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodA{{$}}
+
+// Verify check when unavailable attribute has a message.
+- (void)methodB __attribute__((unavailable("use methodE"))); // methodB
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: method 'methodB' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodB{{$}}
+
+#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
+#define UNAVAILABLE_FIXIT UNAVAILABLE_ATTRIBUTE
+#define UNAVAILABLE_NO_FIXIT UNAVAILABLE_ATTRIBUTE
+
+// Verify check with fix-it when using an configured macro that expands to the unavailable attribute.
+- (void)methodC UNAVAILABLE_FIXIT; // methodC
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: method 'methodC' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodC{{$}}
+
+// Verify check without fix-it when using a non-configured macro that expands to the unavailable attribute.
+- (void)methodD UNAVAILABLE_NO_FIXIT; // methodD
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: method 'methodD' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES-NOT: {{^\s*}}// methodD{{$}}
+@end
+
+
+@implementation MyObject
+
+- (void)notOverridingMethod {}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with ``__attribute__((unavailable))`` is overriding
+a method declaration from a superclass. That declaration can usually be
+deleted entirely.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
+
+Suggests a fix to remove the method declaration entirely.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-override `_, "Yes"
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
`objc-super-self `_, "Yes"
@@ -283,7 +284,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get `_, "Yes"
-   `readability-redundant-string-cstr 

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 248788.
mwyman added a comment.

Update documentation to include description of the FixMacroNames config option.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,52 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: objc-method-unavailable-not-override.FixMacroNames, \
+// RUN:  value: "UNAVAILABLE_FIXIT"} \
+// RUN: ]}' --
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+
+// A new method that is not overriding, and is available, should not trigger.
+- (void)notOverridingMethod;
+
+- (void)methodA __attribute__((unavailable)); // methodA
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: method 'methodA' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodA{{$}}
+
+// Verify check when unavailable attribute has a message.
+- (void)methodB __attribute__((unavailable("use methodE"))); // methodB
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: method 'methodB' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodB{{$}}
+
+#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
+#define UNAVAILABLE_FIXIT UNAVAILABLE_ATTRIBUTE
+#define UNAVAILABLE_NO_FIXIT UNAVAILABLE_ATTRIBUTE
+
+// Verify check with fix-it when using an configured macro that expands to the unavailable attribute.
+- (void)methodC UNAVAILABLE_FIXIT; // methodC
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: method 'methodC' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES: {{^\s*}}// methodC{{$}}
+
+// Verify check without fix-it when using a non-configured macro that expands to the unavailable attribute.
+- (void)methodD UNAVAILABLE_NO_FIXIT; // methodD
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: method 'methodD' is marked unavailable but does not override a superclass method [objc-method-unavailable-not-override]
+// CHECK-FIXES-NOT: {{^\s*}}// methodD{{$}}
+@end
+
+
+@implementation MyObject
+
+- (void)notOverridingMethod {}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,30 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with ``__attribute__((unavailable))`` is overriding
+a method declaration from a superclass. That declaration can usually be
+deleted entirely.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
+
+Suggests a fix to remove the method declaration entirely, except if the
+attribute was expanded from a macro not listed in the option ``FixMacroNames``.
+
+
+Options
+---
+
+.. option:: FixMacroNames
+
+  Comma-separated list of names of macros that can define the unavailable
+  attribute for which fixes should be suggested. The default is an empty list.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-overrid

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-11 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 249709.
mwyman marked 5 inline comments as done.
mwyman added a comment.

After some discussion, have decided to remove the fix-it entirely and update 
the diagnostic message; removing the method altogether may not be the correct 
behavior, as previously deprecated methods that have since been removed may 
want to have an unavailable attribute attached with a message explaining what 
to use instead, even though they don't override a superclass method.

But in general still feel like non-overriding, non-messaged attributes are 
probably reasonable to flag.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp
  clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s objc-method-unavailable-not-override %t -- \
+// RUN: -config='{CheckOptions: [ \
+// RUN: {key: objc-method-unavailable-not-override.FixMacroNames, \
+// RUN:  value: "UNAVAILABLE_FIXIT"} \
+// RUN: ]}' --
+
+__attribute__((objc_root_class))
+@interface Object
+- (instancetype)init;
+@end
+
+@interface MyObject : Object
+- (instancetype)init __attribute__((unavailable));
+
+// A new method that is not overriding, and is available, should not trigger.
+- (void)notOverridingMethod;
+
+- (void)methodA __attribute__((unavailable)); // methodA
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: methods marked unavailable should either override a superclass method or explain why they are unavailable; consider adding a message to the unavailable attribute, or simply deleting 'methodA'. [objc-method-unavailable-not-override]
+
+// Verify check does NOT show when the unavailable attribute has a message.
+- (void)methodB __attribute__((unavailable("use methodE"))); // methodB
+
+#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
+#define UNAVAILABLE UNAVAILABLE_ATTRIBUTE
+
+// Verify check flags a macro that expands to the unavailable attribute.
+- (void)methodC UNAVAILABLE; // methodC
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: methods marked unavailable should either override a superclass method or explain why they are unavailable; consider adding a message to the unavailable attribute, or simply deleting 'methodC'. [objc-method-unavailable-not-override]
+
+@end
+
+
+@implementation MyObject
+
+- (void)notOverridingMethod {}
+
+// Should not flag implementations for methods declared unavailable; sometimes
+// implemementations are provided that assert, to catch such codepaths that
+// lead to those calls during development.
+- (void)methodA {}
+
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - objc-method-unavailable-not-override
+
+objc-method-unavailable-not-override
+
+
+Checks that a method marked with ``__attribute__((unavailable))`` is overriding
+a method declaration from a superclass, or has a message explaining why it's
+unavailable.
+
+.. code-block:: objc
+
+   @interface ClassA : NSObject
+   // Neither ClassA nor any superclasses define method -foo.
+   @end
+
+   @interface ClassB : ClassA
+   - (void)foo __attribute__((unavailable));
+   @end
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -236,6 +236,7 @@
`objc-avoid-nserror-init `_,
`objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
+   `objc-method-unavailable-not-override `_, "Yes"
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
`objc-super-self `_, "Yes"
@@ -283,7 +284,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get `_, "Yes"
-   `readability-redundant-string-cstr `_,
+   `readability-redundant-string-cstr `_, "Yes"
`readability-redundant-string-init `_, "Yes"
`reada

[PATCH] D75569: [clang-tidy] New check for methods marked __attribute__((unavailable)) that do not override a method from a superclass.

2020-03-11 Thread Michael Wyman via Phabricator via cfe-commits
mwyman marked 3 inline comments as done.
mwyman added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp:34
+// Matches Objective-C methods that are not overriding a superclass method.
+AST_MATCHER(ObjCMethodDecl, isNotOverriding) { return !Node.isOverriding(); }
+

njames93 wrote:
> Not a point for this patch, but maybe this should be made into an actual 
> matcher, though not complimented, or better yet the `CXXMethodDecl` 
> `isOverride` matcher be extended for `ObjCMethodDecl`
I agree, and also that it's probably best left to a later patch. Not sure how 
to deal with the making one that works for both `CXXMethodDecl` and 
`ObjCMethodDecl`.



Comment at: 
clang-tools-extra/clang-tidy/objc/MethodUnavailableNotOverrideCheck.cpp:63
+  }
+  return FixItHint::CreateRemoval(MD->getSourceRange());
+}

aaron.ballman wrote:
> I'm not an ObjC expert, so I apologize if this is a dumb question, but why is 
> the fix-it removing the entire method as opposed to just the attribute?
> 
> Also, are you sure that the source range for the method declaration is 
> sufficient to remove without breaking code? e.g., what about the definition 
> of the method? Or can there be any trailing bits after the method that are 
> not accounted for in the source range (such as trailing attributes, if those 
> are possible in ObjC)?
Removing the attribute is undesirable, as that would make the compiler allow 
calling the method, when it has explicitly been marked unavailable. In my 
experience the majority of the cases in Objective-C for using this attribute 
are to mark a superclass method unavailable (e.g. a designated initializer that 
shouldn't be called on the subclass, even just -init, favoring its own declared 
designated initializer instead), but it can also be used to mark a 
previously-deprecated-now-removed method with a message to point updaters what 
method to migrate to.

Which brings up an interesting point that if a message is provided, it could be 
that an API has finally finished allowing a deprecated method to be called and 
removed it entirely, and so if a message is provided it may be indicating that 
and telling what new API to use, rather than overriding the availability of a 
superclass method. But a method being marked unavailable without any message 
doesn't really provide much help on that versus the method just not existing. 
Perhaps if a message is provided this check shouldn't complain at all.

I've removed the fix-it entirely, and replaced it with a different warning 
message.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/objc-method-unavailable-not-override.rst:29
+
+  Comma-separated list of names of macros that can define the unavailable
+  attribute for which fixes should be suggested. The default is an empty list.

aaron.ballman wrote:
> This looks wrong to me -- it's a semicolon-delimited list, isn't it?
Obsolete, deleted.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/objc-method-unavailable-not-override.m:34
+// Verify check when using a macro that expands to the unavailable attribute.
+- (void)methodC NS_UNAVAILABLE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method 'methodC' is marked 
unavailable but does not override a superclass method 
[objc-method-unavailable-not-override]

aaron.ballman wrote:
> mwyman wrote:
> > njames93 wrote:
> > > Generally we are cautious about modifying MACRO usages in clang_tidy as 
> > > we don't know if its definition can change based on configuration, 
> > > perhaps its safer to just warn instead of providing a fix it
> > Sounds reasonable; I made this the default behavior.
> > 
> > However for Objective-C, it's quite common for developers to use a macro 
> > from the Apple SDKs like NS_UNAVAILABLE that are unconditional in any 
> > situations I know of. I added a config option to allow whitelisting macros 
> > that should have fix-its provided.
> If the common practice is to use macros like NS_UNAVAILABLE, should that be 
> on the default list of options (along with any other common-use macro names 
> that do the same thing)?
Obsolete, fix-it deleted.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75569/new/

https://reviews.llvm.org/D75569



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-02-04 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 242371.
mwyman added a comment.

Revert script-changed file.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72876/new/

https://reviews.llvm.org/D72876

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/DeallocInCategoryCheck.cpp
  clang-tools-extra/clang-tidy/objc/DeallocInCategoryCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
  clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s objc-dealloc-in-category %t
+
+@interface NSObject
+// Used to quash warning about missing base class.
+- (void)dealloc;
+@end
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+- (void)dealloc {
+  // No warning should be generated here.
+}
+@end
+
+@interface Bar : NSObject
+@end
+
+@interface Bar (BarCategory)
+@end
+
+@implementation Bar (BarCategory)
++ (void)dealloc {
+  // Should not trigger on class methods.
+}
+
+- (void)dealloc {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: category 'BarCategory' should not implement -dealloc [objc-dealloc-in-category]
+}
+@end
+
+@interface Baz : NSObject
+@end
+
+@implementation Baz
+- (void)dealloc {
+  // Should not trigger on implementation in the class itself, even with
+  // it declared in the category (below).
+}
+@end
+
+@interface Baz (BazCategory)
+// A declaration in a category @interface does not by itself provide an
+// overriding implementation, and should not generate a warning.
+- (void)dealloc;
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-dealloc-in-category
+
+objc-dealloc-in-category
+
+
+Finds implementations of ``-dealloc`` in Objective-C categories. The category
+implementation will override any ``-dealloc`` in the class implementation,
+potentially causing issues.
+
+Classes implement ``-dealloc`` to perform important actions to deallocate
+an object. If a category on the class implements ``-dealloc``, it will
+override the class's implementation and unexpected deallocation behavior
+may occur.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -232,6 +232,7 @@
`mpi-buffer-deref `_, "Yes"
`mpi-type-mismatch `_, "Yes"
`objc-avoid-nserror-init `_,
+   `objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -81,13 +81,18 @@
   ` check.
 
   Checks for usages of identifiers reserved for use by the implementation.
-  
+
 - New :doc:`cert-oop57-cpp
   ` check.
-  
+
   Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
   ``memcmp`` and similar derivatives on non-trivial types.
 
+- New :doc:`objc-dealloc-in-category
+  ` check.
+
+  Finds implementations of -dealloc in Objective-C categories.
+
 New check aliases
 ^
 
@@ -111,8 +116,8 @@
 
 - Improved :doc:`readability-redundant-string-init
   ` check now supports a
-  `StringNames` option enabling its application to custom string classes. The 
-  check now detects in class initializers and constructor initializers which 
+  `StringNames` option enabling its application to custom string classes. The
+  check now detects in class initializers and constructor initializers which
   are deemed to be redundant.
 
 Renamed checks
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
+++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidNSErrorInitCheck.h"
+#include "DeallocInCategoryCheck.h"
 #include "ForbiddenSubclassingCheck.h"
 #include "MissingHashCheck.h"
 #include "PropertyDeclarationCheck.h"
@@ -26,6 +27,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFact

[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-02-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 242947.
mwyman marked an inline comment as done.
mwyman added a comment.

Make check class `final`, based on feedback.`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72876/new/

https://reviews.llvm.org/D72876

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/DeallocInCategoryCheck.cpp
  clang-tools-extra/clang-tidy/objc/DeallocInCategoryCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
  clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s objc-dealloc-in-category %t
+
+@interface NSObject
+// Used to quash warning about missing base class.
+- (void)dealloc;
+@end
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+- (void)dealloc {
+  // No warning should be generated here.
+}
+@end
+
+@interface Bar : NSObject
+@end
+
+@interface Bar (BarCategory)
+@end
+
+@implementation Bar (BarCategory)
++ (void)dealloc {
+  // Should not trigger on class methods.
+}
+
+- (void)dealloc {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: category 'BarCategory' should not implement -dealloc [objc-dealloc-in-category]
+}
+@end
+
+@interface Baz : NSObject
+@end
+
+@implementation Baz
+- (void)dealloc {
+  // Should not trigger on implementation in the class itself, even with
+  // it declared in the category (below).
+}
+@end
+
+@interface Baz (BazCategory)
+// A declaration in a category @interface does not by itself provide an
+// overriding implementation, and should not generate a warning.
+- (void)dealloc;
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-dealloc-in-category
+
+objc-dealloc-in-category
+
+
+Finds implementations of ``-dealloc`` in Objective-C categories. The category
+implementation will override any ``-dealloc`` in the class implementation,
+potentially causing issues.
+
+Classes implement ``-dealloc`` to perform important actions to deallocate
+an object. If a category on the class implements ``-dealloc``, it will
+override the class's implementation and unexpected deallocation behavior
+may occur.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -232,6 +232,7 @@
`mpi-buffer-deref `_, "Yes"
`mpi-type-mismatch `_, "Yes"
`objc-avoid-nserror-init `_,
+   `objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -81,13 +81,18 @@
   ` check.
 
   Checks for usages of identifiers reserved for use by the implementation.
-  
+
 - New :doc:`cert-oop57-cpp
   ` check.
-  
+
   Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
   ``memcmp`` and similar derivatives on non-trivial types.
 
+- New :doc:`objc-dealloc-in-category
+  ` check.
+
+  Finds implementations of -dealloc in Objective-C categories.
+
 New check aliases
 ^
 
@@ -111,8 +116,8 @@
 
 - Improved :doc:`readability-redundant-string-init
   ` check now supports a
-  `StringNames` option enabling its application to custom string classes. The 
-  check now detects in class initializers and constructor initializers which 
+  `StringNames` option enabling its application to custom string classes. The
+  check now detects in class initializers and constructor initializers which
   are deemed to be redundant.
 
 Renamed checks
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
+++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidNSErrorInitCheck.h"
+#include "DeallocInCategoryCheck.h"
 #include "ForbiddenSubclassingCheck.h"
 #include "MissingHashCheck.h"
 #include "PropertyDeclarationCheck.h"
@@ -26,6 +27,8 @@
   void addCheckFactories(ClangTi

[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-02-06 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

Updated based on feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72876/new/

https://reviews.llvm.org/D72876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-01-16 Thread Michael Wyman via Phabricator via cfe-commits
mwyman created this revision.
mwyman added reviewers: stephanemoore, benhamilton.
mwyman added projects: clang-tools-extra, clang.
Herald added subscribers: cfe-commits, mgehre, mgorny.

Such implementations may override the class's own implementation, and even be a 
danger in case someone later comes and adds one to the class itself. Most times 
this has been encountered have been a mistake.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D72876

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.cpp
  clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-categories.rst
  clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-categories.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-categories.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-categories.m
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s objc-dealloc-in-categories %t
+
+@interface NSObject
+// Used to quash warning about missing base class.
+- (void)dealloc;
+@end
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+- (void)dealloc {
+  // No warning should be generated here.
+}
+@end
+
+@interface Bar : NSObject
+@end
+
+@interface Bar (Category)
+@end
+
+@implementation Bar (Category)
+- (void)dealloc {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method -dealloc should not be implemented in a category [objc-dealloc-in-categories]
+}
+@end
+
+@interface Baz : NSObject
+@end
+
+@interface Baz (Category)
+// A declaration in a category @interface does not by itself provide an
+// overriding implementation, and should not generate a warning.
+- (void)dealloc;
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-categories.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-categories.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-dealloc-in-categories
+
+objc-dealloc-in-categories
+==
+
+Finds implementations of ``-dealloc`` in Objective-C categories. The category
+implementation will override any dealloc in the class implementation,
+potentially causing issues.
+
+Classes implement ``-dealloc` to perform important actions just before an
+object is deallocated, but if a category on the class implements ``-dealloc``
+it will override the class's implementation and those important actions may
+not be handled by the overriding ``-dealloc``.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -230,6 +230,7 @@
`mpi-buffer-deref `_, "Yes"
`mpi-type-mismatch `_, "Yes"
`objc-avoid-nserror-init `_,
+   `objc-dealloc-in-categories `_,
`objc-forbidden-subclassing `_,
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -70,6 +70,10 @@
 New checks
 ^^
 
+- New :doc:`objc-dealloc-in-categories
+  ` check.
+
+  Finds implementations of -dealloc in Objective-C categories.
 
 New aliases
 ^^^
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
+++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidNSErrorInitCheck.h"
+#include "DeallocInCategoriesCheck.h"
 #include "ForbiddenSubclassingCheck.h"
 #include "MissingHashCheck.h"
 #include "PropertyDeclarationCheck.h"
@@ -26,6 +27,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck(
 "objc-avoid-nserror-init");
+CheckFactories.registerCheck(
+"objc-dealloc-in-categories");
 CheckFactories.registerCheck(
 "objc-forbidden-subclassing");
 CheckFactories.registerCheck(
Index: clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h
===
--- /dev/null
+++ clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h
@@ -0,0 +1,36 @@
+//===--- DeallocInCategoriesCheck.h - clang-tidy *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICEN

[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-01-16 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 238621.
mwyman added a comment.

Fixed missing end quote pointed out in review comment.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72876/new/

https://reviews.llvm.org/D72876

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.cpp
  clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-categories.rst
  clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-categories.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-categories.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-categories.m
@@ -0,0 +1,36 @@
+// RUN: %check_clang_tidy %s objc-dealloc-in-categories %t
+
+@interface NSObject
+// Used to quash warning about missing base class.
+- (void)dealloc;
+@end
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+- (void)dealloc {
+  // No warning should be generated here.
+}
+@end
+
+@interface Bar : NSObject
+@end
+
+@interface Bar (Category)
+@end
+
+@implementation Bar (Category)
+- (void)dealloc {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method -dealloc should not be implemented in a category [objc-dealloc-in-categories]
+}
+@end
+
+@interface Baz : NSObject
+@end
+
+@interface Baz (Category)
+// A declaration in a category @interface does not by itself provide an
+// overriding implementation, and should not generate a warning.
+- (void)dealloc;
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-categories.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-categories.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-dealloc-in-categories
+
+objc-dealloc-in-categories
+==
+
+Finds implementations of ``-dealloc`` in Objective-C categories. The category
+implementation will override any dealloc in the class implementation,
+potentially causing issues.
+
+Classes implement ``-dealloc`` to perform important actions just before an
+object is deallocated, but if a category on the class implements ``-dealloc``
+it will override the class's implementation and those important actions may
+not be handled by the overriding ``-dealloc``.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -230,6 +230,7 @@
`mpi-buffer-deref `_, "Yes"
`mpi-type-mismatch `_, "Yes"
`objc-avoid-nserror-init `_,
+   `objc-dealloc-in-categories `_,
`objc-forbidden-subclassing `_,
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -70,6 +70,10 @@
 New checks
 ^^
 
+- New :doc:`objc-dealloc-in-categories
+  ` check.
+
+  Finds implementations of -dealloc in Objective-C categories.
 
 New aliases
 ^^^
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
+++ clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidNSErrorInitCheck.h"
+#include "DeallocInCategoriesCheck.h"
 #include "ForbiddenSubclassingCheck.h"
 #include "MissingHashCheck.h"
 #include "PropertyDeclarationCheck.h"
@@ -26,6 +27,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
 CheckFactories.registerCheck(
 "objc-avoid-nserror-init");
+CheckFactories.registerCheck(
+"objc-dealloc-in-categories");
 CheckFactories.registerCheck(
 "objc-forbidden-subclassing");
 CheckFactories.registerCheck(
Index: clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h
===
--- /dev/null
+++ clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h
@@ -0,0 +1,36 @@
+//===--- DeallocInCategoriesCheck.h - clang-tidy *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_DEALLOCINCATEG

[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-01-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman updated this revision to Diff 240716.
mwyman marked 7 inline comments as done.
mwyman added a comment.

Addresses reviewer feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72876/new/

https://reviews.llvm.org/D72876

Files:
  clang-tools-extra/clang-tidy/objc/CMakeLists.txt
  clang-tools-extra/clang-tidy/objc/DeallocInCategoryCheck.cpp
  clang-tools-extra/clang-tidy/objc/DeallocInCategoryCheck.h
  clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
  clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m

Index: clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/objc-dealloc-in-category.m
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s objc-dealloc-in-category %t
+
+@interface NSObject
+// Used to quash warning about missing base class.
+- (void)dealloc;
+@end
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+- (void)dealloc {
+  // No warning should be generated here.
+}
+@end
+
+@interface Bar : NSObject
+@end
+
+@interface Bar (Category)
+@end
+
+@implementation Bar (Category)
++ (void)dealloc {
+  // Should not trigger on class methods.
+}
+
+- (void)dealloc {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: method -dealloc should not be implemented in a category [objc-dealloc-in-category]
+}
+@end
+
+@interface Baz : NSObject
+@end
+
+@implementation Baz
+- (void)dealloc {
+  // Should not trigger on implementation in the class itself, even with
+  // it declared in the category (below).
+}
+@end
+
+@interface Baz (Category)
+// A declaration in a category @interface does not by itself provide an
+// overriding implementation, and should not generate a warning.
+- (void)dealloc;
+@end
Index: clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/objc-dealloc-in-category.rst
@@ -0,0 +1,13 @@
+.. title:: clang-tidy - objc-dealloc-in-category
+
+objc-dealloc-in-category
+
+
+Finds implementations of ``-dealloc`` in Objective-C categories. The category
+implementation will override any dealloc in the class implementation,
+potentially causing issues.
+
+Classes implement ``-dealloc`` to perform important actions just before an
+object is deallocated, but if a category on the class implements ``-dealloc``
+it will override the class's implementation and those important actions may
+not be handled by the overriding ``-dealloc``.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -232,6 +232,7 @@
`mpi-buffer-deref `_, "Yes"
`mpi-type-mismatch `_, "Yes"
`objc-avoid-nserror-init `_,
+   `objc-dealloc-in-category `_,
`objc-forbidden-subclassing `_,
`objc-missing-hash `_,
`objc-property-declaration `_, "Yes"
@@ -280,7 +281,7 @@
`readability-redundant-member-init `_, "Yes"
`readability-redundant-preprocessor `_,
`readability-redundant-smartptr-get `_, "Yes"
-   `readability-redundant-string-cstr `_,
+   `readability-redundant-string-cstr `_, "Yes"
`readability-redundant-string-init `_, "Yes"
`readability-simplify-boolean-expr `_, "Yes"
`readability-simplify-subscript-expr `_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -81,13 +81,18 @@
   ` check.
 
   Checks for usages of identifiers reserved for use by the implementation.
-  
+
 - New :doc:`cert-oop57-cpp
   ` check.
-  
+
   Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
   ``memcmp`` and similar derivatives on non-trivial types.
 
+- New :doc:`objc-dealloc-in-category
+  ` check.
+
+  Finds implementations of -dealloc in Objective-C categories.
+
 New aliases
 ^^^
 
@@ -106,8 +111,8 @@
 
 - Improved :doc:`readability-redundant-string-init
   ` check now supports a
-  `StringNames` option enabling its application to custom string classes. The 
-  check now detects in class initializers and constructor initializers which 
+  `StringNames` option enabling its application to custom string classes. The
+  check now detects in class initializers and constructor initializers which
   are deemed to be redundant.
 
 Renamed checks
Index: clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp
===
--- clang-tools-extra/clang-t

[PATCH] D72876: Create a clang-tidy check to warn when -dealloc is implemented inside an ObjC class category.

2020-01-27 Thread Michael Wyman via Phabricator via cfe-commits
mwyman added a comment.

Updated the diff based on review feedback.




Comment at: clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.cpp:21
+  Finder->addMatcher(
+  objcMethodDecl(hasName("dealloc"), 
hasDeclContext(objcCategoryImplDecl()))
+  .bind("dealloc"),

stephanemoore wrote:
> stephanemoore wrote:
> > Add `isInstanceMethod()` within the `objcMethodDecl`?
> Technically, isn't `-dealloc` specific to certain classes, e.g., 
> [`NSObject`](https://developer.apple.com/documentation/objectivec/nsobject/1571947-dealloc?language=objc))
>  and 
> [NSProxy](https://developer.apple.com/documentation/foundation/nsproxy/1589830-dealloc?language=objc)?
>  If that is true, we should technically check that the category is on a class 
> that is or is derived from a relevant class like `NSObject` or `NSProxy`.
Technically true, but given the prevalence of extant ObjC documentation talking 
about the -dealloc method in terms of deallocation, it seems highly unlikely 
any non-NSObject/NSProxy-rooted class hierarchies are going to use -dealloc in 
any other context, and want to allow implementations in a category.



Comment at: clang-tools-extra/clang-tidy/objc/DeallocInCategoriesCheck.h:24
+/// 
http://clang.llvm.org/extra/clang-tidy/checks/objc-dealloc-in-categories.html
+class DeallocInCategoriesCheck : public ClangTidyCheck {
+public:

stephanemoore wrote:
> What do you think of the name `DeallocInCategoryCheck`?
Much better.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72876/new/

https://reviews.llvm.org/D72876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   >