1 // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -analyzer-config c++-inlining=destructors -std=c++11 -verify -Wno-tautological-undefined-compare %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config c++-inlining=destructors -std=c++11 %s -o %t.plist -Wno-tautological-undefined-compare
3 // RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/path-notes.cpp.plist -
4 
5 class Foo {
6 public:
use(int * p)7   static void use(int *p) {
8     *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
9     // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
10   }
11 
Foo(int * p)12   Foo(int *p) {
13     use(p);
14     // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}}
15     // expected-note@-2 {{Calling 'Foo::use'}}
16   }
17 };
18 
19 static int *globalPtr;
20 
21 class Bar {
22 public:
~Bar()23   ~Bar() {
24     Foo f(globalPtr);
25     // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}}
26     // expected-note@-2 {{Calling constructor for 'Foo'}}
27   }
28 };
29 
test()30 void test() {
31   Bar b;
32   globalPtr = 0;
33   // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
34 } // expected-note {{Calling '~Bar'}}
35 
36 
testAnonymous()37 void testAnonymous() {
38   class {
39   public:
40     void method(int *p) {
41       *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
42       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
43     }
44   } anonymous;
45 
46   anonymous.method(0);
47   // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}}
48   // expected-note@-2 {{Calling 'method'}}
49 }
50 
51 
52 // A simplified version of std::move.
53 template <typename T>
move(T & obj)54 T &&move(T &obj) {
55   return static_cast<T &&>(obj);
56 }
57 
58 
59 namespace defaulted {
60   class Dereferencer {
61   public:
Dereferencer()62     Dereferencer() {
63       *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}}
64       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}}
65     }
66 
Dereferencer(const Dereferencer & Other)67     Dereferencer(const Dereferencer &Other) {
68       *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}}
69       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}}
70     }
71 
Dereferencer(Dereferencer && Other)72     Dereferencer(Dereferencer &&Other) {
73       *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}}
74       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}}
75     }
76 
operator =(const Dereferencer & Other)77     void operator=(const Dereferencer &Other) {
78       *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}}
79       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}}
80     }
81 
operator =(Dereferencer && Other)82     void operator=(Dereferencer &&Other) {
83       *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}}
84       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}}
85     }
86 
~Dereferencer()87     ~Dereferencer() {
88       *globalPtr = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'globalPtr')}}
89       // expected-note@-1 {{Dereference of null pointer (loaded from variable 'globalPtr')}}
90     }
91   };
92 
93   class Wrapper {
94     Dereferencer d;
95   };
96 
97   class MovableWrapper {
98     Dereferencer d;
99   public:
100     MovableWrapper() = default;
101 
102     MovableWrapper(MovableWrapper &&Other) = default;
103     // expected-note@-1 {{Calling move constructor for 'Dereferencer'}}
104 
105     MovableWrapper &operator=(MovableWrapper &&Other) = default;
106     // expected-note@-1 {{Calling move assignment operator for 'Dereferencer'}}
107   };
108 
testDefaultConstruction()109   void testDefaultConstruction() {
110     globalPtr = 0;
111     // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
112     Wrapper w;
113     // expected-note@-1 {{Calling implicit default constructor for 'Wrapper'}}
114     // expected-note@-2 {{Calling default constructor for 'Dereferencer'}}
115   }
116 
testCopyConstruction(const Wrapper & input)117   void testCopyConstruction(const Wrapper &input) {
118     globalPtr = 0;
119     // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
120     Wrapper w{input};
121     // expected-note@-1 {{Calling implicit copy constructor for 'Wrapper'}}
122     // expected-note@-2 {{Calling copy constructor for 'Dereferencer'}}
123   }
124 
testMoveConstruction(MovableWrapper && input)125   void testMoveConstruction(MovableWrapper &&input) {
126     globalPtr = 0;
127     // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
128     MovableWrapper w{move(input)};
129     // expected-note@-1 {{Calling defaulted move constructor for 'MovableWrapper'}}
130   }
131 
testCopyAssignment(const Wrapper & input)132   void testCopyAssignment(const Wrapper &input) {
133     Wrapper w;
134     globalPtr = 0;
135     // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
136     w = input;
137     // expected-note@-1 {{Calling implicit copy assignment operator for 'Wrapper'}}
138     // expected-note@-2 {{Calling copy assignment operator for 'Dereferencer'}}
139   }
140 
testMoveAssignment(MovableWrapper && input)141   void testMoveAssignment(MovableWrapper &&input) {
142     MovableWrapper w;
143     globalPtr = 0;
144     // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
145     w = move(input);
146     // expected-note@-1 {{Calling defaulted move assignment operator for 'MovableWrapper'}}
147   }
148 
testDestruction()149   void testDestruction() {
150     Wrapper w;
151     globalPtr = 0;
152     // expected-note@-1 {{Null pointer value stored to 'globalPtr'}}
153   }
154   // expected-note@-1 {{Calling implicit destructor for 'Wrapper'}}
155   // expected-note@-2 {{Calling '~Dereferencer'}}
156 }
157 
158 namespace ReturnZeroNote {
getZero()159   int getZero() {
160     return 0;
161     // expected-note@-1 {{Returning zero}}
162   }
163 
getZeroByRef()164   const int &getZeroByRef() {
165     static int zeroVar;
166     zeroVar = 0;
167     // expected-note@-1 {{The value 0 is assigned to 'zeroVar'}}
168     return zeroVar;
169     // expected-note@-1 {{Returning zero (reference to 'zeroVar')}}
170   }
171 
test()172   void test() {
173     int problem = 1 / getZero(); // expected-warning {{Division by zero}}
174     // expected-note@-1 {{Calling 'getZero'}}
175     // expected-note@-2 {{Returning from 'getZero'}}
176     // expected-note@-3 {{Division by zero}}
177   }
178 
testRef()179   void testRef() {
180     int problem = 1 / getZeroByRef(); // expected-warning {{Division by zero}}
181     // expected-note@-1 {{Calling 'getZeroByRef'}}
182     // expected-note@-2 {{Returning from 'getZeroByRef'}}
183     // expected-note@-3 {{Division by zero}}
184   }
185 }
186 
returnNullReference()187 int &returnNullReference() {
188   int *x = 0;
189   // expected-note@-1 {{'x' initialized to a null pointer value}}
190   return *x; // expected-warning{{Returning null reference}}
191   // expected-note@-1 {{Returning null reference}}
192 }
193 
194 struct FooWithInitializer {
195 	int *ptr;
FooWithInitializerFooWithInitializer196 	FooWithInitializer(int *p) : ptr(p) { // expected-note {{Null pointer value stored to 'f.ptr'}}
197 		*ptr = 1; // expected-note {{Dereference of null pointer (loaded from field 'ptr')}}
198     // expected-warning@-1 {{Dereference of null pointer (loaded from field 'ptr')}}
199 	}
200 };
201 
testPathNoteOnInitializer()202 void testPathNoteOnInitializer() {
203 	int *p = 0; // expected-note {{'p' initialized to a null pointer value}}
204 
205 	FooWithInitializer f(p); // expected-note {{Passing null pointer value via 1st parameter 'p'}}
206   // expected-note@-1 {{Calling constructor for 'FooWithInitializer'}}
207 }
208 
testNonPrintableAssignment(int ** p)209 int testNonPrintableAssignment(int **p) {
210   int *&y = *p; // expected-note {{'y' initialized here}}
211   y = 0;        // expected-note {{Storing null pointer value}}
212   return *y; // expected-warning {{Dereference of null pointer (loaded from variable 'y')}}
213              // expected-note@-1 {{Dereference of null pointer (loaded from variable 'y')}}
214 }
215 
216 struct Base { int *x; };
217 struct Derived : public Base {};
218 
test(Derived d)219 void test(Derived d) {
220   d.x = 0; //expected-note {{Null pointer value stored to 'd.x'}}
221   *d.x = 1; // expected-warning {{Dereference of null pointer (loaded from field 'x')}}
222             // expected-note@-1 {{Dereference of null pointer (loaded from field 'x')}}
223 }
224 
225 struct Owner {
226 	struct Wrapper {
227 		int x;
228 	};
229 	Wrapper *arr;
230 	void testGetDerefExprOnMemberExprWithADot();
231 };
232 
testGetDerefExprOnMemberExprWithADot()233 void Owner::testGetDerefExprOnMemberExprWithADot() {
234 	if (arr)  // expected-note {{Assuming field 'arr' is null}}
235             // expected-note@-1 {{Taking false branch}}
236 	  ;
237 	arr[1].x = 1; //expected-warning {{Dereference of null pointer}}
238                 //expected-note@-1 {{Dereference of null pointer}}
239 }
240 
testGetDerefExprOnMemberExprWithADot()241 void testGetDerefExprOnMemberExprWithADot() {
242   Owner::Wrapper *arr; // expected-note {{'arr' declared without an initial value}}
243 	arr[2].x = 1; // expected-warning {{Dereference of undefined pointer value}}
244                 // expected-note@-1 {{Dereference of undefined pointer value}}
245 }
246 
247 
248 
249 class A {
250 public:
bar() const251   void bar() const {}
252 };
testDeclRefExprToReferenceInGetDerefExpr(const A * ptr)253 const A& testDeclRefExprToReferenceInGetDerefExpr(const A *ptr) {
254   const A& val = *ptr; //expected-note {{'val' initialized here}}
255 
256   // This is not valid C++; if 'ptr' were null, creating 'ref' would be illegal.
257   // However, this is not checked at runtime, so this branch is actually
258   // possible.
259   if (&val == 0) { //expected-note {{Assuming pointer value is null}}
260                    // expected-note@-1 {{Taking true branch}}
261     val.bar(); // expected-warning {{Called C++ object pointer is null}}
262                // expected-note@-1 {{Called C++ object pointer is null}}
263   }
264 
265   return val;
266 }
267 
generateNoteOnDefaultArgument(int one,int two=0)268 int generateNoteOnDefaultArgument(int one, int two = 0) {
269   return one/two; // expected-warning {{Division by zero}}
270                   // expected-note@-1 {{Division by zero}}
271 }
callGenerateNoteOnDefaultArgument(int o)272 int callGenerateNoteOnDefaultArgument(int o) {
273   return generateNoteOnDefaultArgument(o); //expected-note{{Calling 'generateNoteOnDefaultArgument'}}
274                                            //expected-note@-1 {{Passing the value 0 via 2nd parameter 'two'}}
275 }
276 
277 namespace PR17746 {
278   class Inner {
279   public:
~Inner()280     ~Inner() {
281       *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}}
282       // expected-note@-1 {{Dereference of null pointer}}
283     }
284   };
285 
286   class Outer {
287   public:
288     Inner *inner;
~Outer()289     ~Outer() {
290       delete inner;
291       // expected-note@-1 {{Calling '~Inner'}}
292     }
293   };
294 
test(Outer * outer)295   void test(Outer *outer) {
296     delete outer;
297     // expected-note@-1 {{Calling '~Outer'}}
298   }
299 }
300 
301