1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s |
2 | // RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -DSUPPRESSED=1 %s |
3 | |
4 | namespace rdar12676053 { |
5 | // Delta-reduced from a preprocessed file. |
6 | template<class T> |
7 | class RefCount { |
8 | T *ref; |
9 | public: |
10 | T *operator->() const { |
11 | return ref ? ref : 0; |
12 | } |
13 | }; |
14 | |
15 | class string {}; |
16 | |
17 | class ParserInputState { |
18 | public: |
19 | string filename; |
20 | }; |
21 | |
22 | class Parser { |
23 | void setFilename(const string& f) { |
24 | inputState->filename = f; |
25 | #ifndef SUPPRESSED |
26 | // expected-warning@-2 {{Called C++ object pointer is null}} |
27 | #endif |
28 | } |
29 | protected: |
30 | RefCount<ParserInputState> inputState; |
31 | }; |
32 | } |
33 | |
34 | |
35 | // This is the standard placement new. |
36 | inline void* operator new(__typeof__(sizeof(int)), void* __p) throw() |
37 | { |
38 | return __p; |
39 | } |
40 | |
41 | extern bool coin(); |
42 | |
43 | class SomeClass { |
44 | public: |
45 | void doSomething(); |
46 | }; |
47 | |
48 | namespace References { |
49 | class Map { |
50 | int *&getNewBox(); |
51 | int *firstBox; |
52 | |
53 | public: |
54 | int *&getValue(int key) { |
55 | if (coin()) { |
56 | return firstBox; |
57 | } else { |
58 | int *&newBox = getNewBox(); |
59 | newBox = 0; |
60 | return newBox; |
61 | } |
62 | } |
63 | |
64 | int *&getValueIndirectly(int key) { |
65 | int *&valueBox = getValue(key); |
66 | return valueBox; |
67 | } |
68 | }; |
69 | |
70 | void testMap(Map &m, int i) { |
71 | *m.getValue(i) = 1; |
72 | #ifndef SUPPRESSED |
73 | // expected-warning@-2 {{Dereference of null pointer}} |
74 | #endif |
75 | |
76 | *m.getValueIndirectly(i) = 1; |
77 | #ifndef SUPPRESSED |
78 | // expected-warning@-2 {{Dereference of null pointer}} |
79 | #endif |
80 | |
81 | int *&box = m.getValue(i); |
82 | extern int *getPointer(); |
83 | box = getPointer(); |
84 | *box = 1; // no-warning |
85 | |
86 | int *&box2 = m.getValue(i); |
87 | box2 = 0; |
88 | *box2 = 1; // expected-warning {{Dereference of null pointer}} |
89 | } |
90 | |
91 | SomeClass *&getSomeClass() { |
92 | if (coin()) { |
93 | extern SomeClass *&opaqueClass(); |
94 | return opaqueClass(); |
95 | } else { |
96 | static SomeClass *sharedClass; |
97 | sharedClass = 0; |
98 | return sharedClass; |
99 | } |
100 | } |
101 | |
102 | void testClass() { |
103 | getSomeClass()->doSomething(); |
104 | #ifndef SUPPRESSED |
105 | // expected-warning@-2 {{Called C++ object pointer is null}} |
106 | #endif |
107 | |
108 | // Separate the lvalue-to-rvalue conversion from the subsequent dereference. |
109 | SomeClass *object = getSomeClass(); |
110 | object->doSomething(); |
111 | #ifndef SUPPRESSED |
112 | // expected-warning@-2 {{Called C++ object pointer is null}} |
113 | #endif |
114 | } |
115 | |
116 | SomeClass *getNull() { |
117 | return 0; |
118 | } |
119 | |
120 | SomeClass &returnNullReference() { |
121 | SomeClass *x = getNull(); |
122 | return *x; |
123 | #ifndef SUPPRESSED |
124 | // expected-warning@-2 {{Returning null reference}} |
125 | #endif |
126 | } |
127 | } |
128 | |
129 | class X{ |
130 | public: |
131 | void get(); |
132 | }; |
133 | |
134 | X *getNull() { |
135 | return 0; |
136 | } |
137 | |
138 | void deref1(X *const &p) { |
139 | return p->get(); |
140 | #ifndef SUPPRESSED |
141 | // expected-warning@-2 {{Called C++ object pointer is null}} |
142 | #endif |
143 | } |
144 | |
145 | void test1() { |
146 | return deref1(getNull()); |
147 | } |
148 | |
149 | void deref2(X *p3) { |
150 | p3->get(); |
151 | #ifndef SUPPRESSED |
152 | // expected-warning@-2 {{Called C++ object pointer is null}} |
153 | #endif |
154 | } |
155 | |
156 | void pass2(X *const &p2) { |
157 | deref2(p2); |
158 | } |
159 | |
160 | void test2() { |
161 | pass2(getNull()); |
162 | } |
163 | |
164 | void deref3(X *const &p2) { |
165 | X *p3 = p2; |
166 | p3->get(); |
167 | #ifndef SUPPRESSED |
168 | // expected-warning@-2 {{Called C++ object pointer is null}} |
169 | #endif |
170 | } |
171 | |
172 | void test3() { |
173 | deref3(getNull()); |
174 | } |
175 | |
176 | |
177 | namespace Cleanups { |
178 | class NonTrivial { |
179 | public: |
180 | ~NonTrivial(); |
181 | |
182 | SomeClass *getNull() { |
183 | return 0; |
184 | } |
185 | }; |
186 | |
187 | void testImmediate() { |
188 | NonTrivial().getNull()->doSomething(); |
189 | #ifndef SUPPRESSED |
190 | // expected-warning@-2 {{Called C++ object pointer is null}} |
191 | #endif |
192 | } |
193 | |
194 | void testAssignment() { |
195 | SomeClass *ptr = NonTrivial().getNull(); |
196 | ptr->doSomething(); |
197 | #ifndef SUPPRESSED |
198 | // expected-warning@-2 {{Called C++ object pointer is null}} |
199 | #endif |
200 | } |
201 | |
202 | void testArgumentHelper(SomeClass *arg) { |
203 | arg->doSomething(); |
204 | #ifndef SUPPRESSED |
205 | // expected-warning@-2 {{Called C++ object pointer is null}} |
206 | #endif |
207 | } |
208 | |
209 | void testArgument() { |
210 | testArgumentHelper(NonTrivial().getNull()); |
211 | } |
212 | } |
213 | |