xref: /llvm-project/clang/test/Analysis/incorrect-checker-names.mm (revision dd7233bc67e45106c4625df7d20391798f31d4a7)
1// RUN: %clang_analyze_cc1 -fblocks -fobjc-arc -verify %s -Wno-objc-root-class \
2// RUN:   -analyzer-checker=core \
3// RUN:   -analyzer-checker=alpha.core.StackAddressAsyncEscape \
4// RUN:   -analyzer-checker=nullability \
5// RUN:   -analyzer-checker=osx
6
7#include "Inputs/system-header-simulator-for-nullability.h"
8#include "os_object_base.h"
9
10struct OSIterator : public OSObject {
11  static const OSMetaClass * const metaClass;
12};
13
14@interface TestObject : NSObject
15- (int *_Nonnull)returnsNonnull;
16- (int *_Nullable)returnsNullable;
17- (int *)returnsUnspecified;
18- (void)takesNonnull:(int *_Nonnull)p;
19- (void)takesNullable:(int *_Nullable)p;
20- (void)takesUnspecified:(int *)p;
21@property(readonly, strong) NSString *stuff;
22@end
23
24TestObject * getUnspecifiedTestObject();
25TestObject *_Nonnull getNonnullTestObject();
26TestObject *_Nullable getNullableTestObject();
27
28int getRandom();
29
30typedef struct Dummy { int val; } Dummy;
31
32void takesNullable(Dummy *_Nullable);
33void takesNonnull(Dummy *_Nonnull);
34void takesUnspecified(Dummy *);
35
36Dummy *_Nullable returnsNullable();
37Dummy *_Nonnull returnsNonnull();
38Dummy *returnsUnspecified();
39int *_Nullable returnsNullableInt();
40
41template <typename T> T *eraseNullab(T *p) { return p; }
42
43void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
44
45void testBasicRules() {
46  // FIXME: None of these should be tied to a modeling checker.
47  Dummy *p = returnsNullable();
48  int *ptr = returnsNullableInt();
49  // Make every dereference a different path to avoid sinks after errors.
50  switch (getRandom()) {
51  case 0: {
52    Dummy &r = *p; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}}
53  } break;
54  case 1: {
55    int b = p->val; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}}
56  } break;
57  case 2: {
58    int stuff = *ptr; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}}
59  } break;
60  case 3:
61    takesNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter [nullability.NullablePassedToNonnull]}}
62    break;
63  case 4: {
64    Dummy d;
65    takesNullable(&d);
66    Dummy dd(d);
67    break;
68  }
69  case 5:
70    takesAttrNonnull(p); // expected-warning {{Nullable pointer is passed to a callee that requires a non-null [nullability.NullableDereferenced]}}
71    break;
72  default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced [nullability.NullableDereferenced]}}
73  }
74  if (p) {
75    takesNonnull(p);
76    if (getRandom()) {
77      Dummy &r = *p;
78    } else {
79      int b = p->val;
80    }
81  }
82  Dummy *q = 0;
83  if (getRandom()) {
84    takesNullable(q);
85  // FIXME: This shouldn't be tied to a modeling checker.
86    takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter [nullability.NullPassedToNonnull]}}
87  }
88  Dummy a;
89  Dummy *_Nonnull nonnull = &a;
90  // FIXME: This shouldn't be tied to a modeling checker.
91  nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value [nullability.NullPassedToNonnull]}}
92  q = &a;
93  takesNullable(q);
94  takesNonnull(q);
95}
96
97typedef int NSInteger;
98typedef struct _NSZone NSZone;
99@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
100@class NSDictionary;
101@interface NSError : NSObject <NSCopying, NSCoding> {}
102+ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict;
103@end
104
105struct __CFError {};
106typedef struct __CFError* CFErrorRef;
107
108void foo(CFErrorRef* error) { // expected-warning{{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occurred [osx.coreFoundation.CFError]}}
109  // FIXME: This shouldn't be tied to a modeling checker.
110  *error = 0; // expected-warning {{Potential null dereference. According to coding standards documented in CoreFoundation/CFError.h the parameter may be null [osx.coreFoundation.CFError]}}
111}
112
113@interface A
114- (void)myMethodWhichMayFail:(NSError **)error;
115@end
116
117@implementation A
118- (void)myMethodWhichMayFail:(NSError **)error {                  // expected-warning {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occurred [osx.cocoa.NSError]}}
119  *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning {{Potential null dereference. According to coding standards in 'Creating and Returning NSError Objects' the parameter may be null [osx.cocoa.NSError]}}
120}
121@end
122
123bool write_into_out_param_on_success(OS_RETURNS_RETAINED OSObject **obj);
124
125void use_out_param_leak() {
126  OSObject *obj;
127  // FIXME: This shouldn't be tied to a modeling checker.
128  write_into_out_param_on_success(&obj); // expected-warning{{Potential leak of an object stored into 'obj' [osx.cocoa.RetainCount]}}
129}
130
131typedef struct dispatch_queue_s *dispatch_queue_t;
132typedef void (^dispatch_block_t)(void);
133void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
134typedef long dispatch_once_t;
135void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
136typedef long dispatch_time_t;
137void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
138void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);
139
140extern dispatch_queue_t queue;
141extern dispatch_once_t *predicate;
142extern dispatch_time_t when;
143
144dispatch_block_t get_leaking_block() {
145  int leaked_x = 791;
146  int *p = &leaked_x;
147  return ^void(void) {
148    *p = 1;
149  };
150  // expected-warning@-3 {{Address of stack memory associated with local variable 'leaked_x' \
151is captured by a returned block [core.StackAddressEscape]}}
152}
153
154void test_returned_from_func_block_async() {
155  dispatch_async(queue, get_leaking_block());
156  // expected-warning@-1 {{Address of stack memory associated with local variable 'leaked_x' \
157is captured by an asynchronously-executed block [alpha.core.StackAddressAsyncEscape]}}
158}
159