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()30void 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()37void 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)54T &&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()187int &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()202void 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)209int 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)219void 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()233void 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()241void 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)253const 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)268int 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)272int 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