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
16struct Foo {
17  __unsafe_unretained id Field1;
18  id Field2;
19  int IntField;
20};
21
22void 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)();
33  // CHECK-FIXES: __unsafe_unretained void (^BlockArg1)();
34  __unsafe_unretained void (^BlockArg2)();
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
66void 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
99void 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