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)(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
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

source code of clang-tools-extra/test/clang-tidy/checkers/objc/nsinvocation-argument-lifetime.m