| 1 | // RUN: %check_clang_tidy %s objc-nsinvocation-argument-lifetime %t |
| 2 | |
| 3 | __attribute__((objc_root_class)) |
| 4 | @interface NSObject |
| 5 | @end |
| 6 | |
| 7 | @interface NSInvocation : NSObject |
| 8 | - (void)getArgument:(void *)Arg atIndex:(int)Index; |
| 9 | - (void)getReturnValue:(void *)ReturnValue; |
| 10 | @end |
| 11 | |
| 12 | @interface OtherClass : NSObject |
| 13 | - (void)getArgument:(void *)Arg atIndex:(int)Index; |
| 14 | @end |
| 15 | |
| 16 | struct Foo { |
| 17 | __unsafe_unretained id Field1; |
| 18 | id Field2; |
| 19 | int IntField; |
| 20 | }; |
| 21 | |
| 22 | void foo(NSInvocation *Invocation) { |
| 23 | __unsafe_unretained id Arg2; |
| 24 | id Arg3; |
| 25 | // CHECK-FIXES: __unsafe_unretained id Arg3; |
| 26 | NSObject __strong *Arg4; |
| 27 | // CHECK-FIXES: NSObject __unsafe_unretained *Arg4; |
| 28 | __weak id Arg5; |
| 29 | // CHECK-FIXES: __unsafe_unretained id Arg5; |
| 30 | id ReturnValue; |
| 31 | // CHECK-FIXES: __unsafe_unretained id ReturnValue; |
| 32 | void (^BlockArg1)(void); |
| 33 | // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)(void); |
| 34 | __unsafe_unretained void (^BlockArg2)(void); |
| 35 | int IntVar; |
| 36 | struct Foo Bar; |
| 37 | |
| 38 | [Invocation getArgument:&Arg2 atIndex:2]; |
| 39 | [Invocation getArgument:&IntVar atIndex:2]; |
| 40 | |
| 41 | [Invocation getArgument:&Arg3 atIndex:3]; |
| 42 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 43 | |
| 44 | [Invocation getArgument:&Arg4 atIndex:4]; |
| 45 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 46 | |
| 47 | [Invocation getArgument:&Arg5 atIndex:5]; |
| 48 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 49 | |
| 50 | [Invocation getArgument:&BlockArg1 atIndex:6]; |
| 51 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 52 | |
| 53 | [Invocation getArgument:&BlockArg2 atIndex:6]; |
| 54 | |
| 55 | [Invocation getReturnValue:&ReturnValue]; |
| 56 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 57 | |
| 58 | [Invocation getArgument:(void *)0 atIndex:6]; |
| 59 | |
| 60 | [Invocation getArgument:&Bar.Field1 atIndex:2]; |
| 61 | [Invocation getArgument:&Bar.Field2 atIndex:2]; |
| 62 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 63 | [Invocation getArgument:&Bar.IntField atIndex:2]; |
| 64 | } |
| 65 | |
| 66 | void bar(OtherClass *OC) { |
| 67 | id Arg; |
| 68 | [OC getArgument:&Arg atIndex:2]; |
| 69 | } |
| 70 | |
| 71 | @interface TestClass : NSObject { |
| 72 | @public |
| 73 | id Argument1; |
| 74 | __unsafe_unretained id Argument2; |
| 75 | struct Foo Bar; |
| 76 | int IntIvar; |
| 77 | } |
| 78 | @end |
| 79 | |
| 80 | @implementation TestClass |
| 81 | |
| 82 | - (void)processInvocation:(NSInvocation *)Invocation { |
| 83 | [Invocation getArgument:&Argument1 atIndex:2]; |
| 84 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 85 | [Invocation getArgument:&self->Argument1 atIndex:2]; |
| 86 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 87 | [Invocation getArgument:&Argument2 atIndex:2]; |
| 88 | [Invocation getArgument:&self->Argument2 atIndex:2]; |
| 89 | [Invocation getArgument:&self->IntIvar atIndex:2]; |
| 90 | |
| 91 | [Invocation getReturnValue:&(self->Bar.Field1)]; |
| 92 | [Invocation getReturnValue:&(self->Bar.Field2)]; |
| 93 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: NSInvocation '-getReturnValue:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 94 | [Invocation getReturnValue:&(self->Bar.IntField)]; |
| 95 | } |
| 96 | |
| 97 | @end |
| 98 | |
| 99 | void baz(NSInvocation *Invocation, TestClass *Obj) { |
| 100 | [Invocation getArgument:&Obj->Argument1 atIndex:2]; |
| 101 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: NSInvocation '-getArgument:atIndex:' should only pass pointers to objects with ownership __unsafe_unretained [objc-nsinvocation-argument-lifetime] |
| 102 | [Invocation getArgument:&Obj->Argument2 atIndex:2]; |
| 103 | } |
| 104 | |