1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\ 2 // RUN: -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\ 3 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 4 // RUN: -std=c++11 -verify %s 5 6 #include "Inputs/system-header-simulator-cxx.h" 7 8 void clang_analyzer_warnIfReached(); 9 void clang_analyzer_numTimesReached(); 10 void clang_analyzer_eval(bool); 11 void clang_analyzer_warnOnDeadSymbol(int *); 12 13 void derefAfterMove(std::unique_ptr<int> P) { 14 std::unique_ptr<int> Q = std::move(P); 15 if (Q) 16 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 17 *Q.get() = 1; // expected-warning {{Dereference of null pointer [core.NullDereference]}} 18 if (P) 19 clang_analyzer_warnIfReached(); // no-warning 20 // TODO: Report a null dereference (instead). 21 *P.get() = 1; // expected-warning {{Method called on moved-from object 'P' [cplusplus.Move]}} 22 // expected-warning@-1 {{Dereference of null pointer [core.NullDereference]}} 23 } 24 25 // Don't crash when attempting to model a call with unknown callee. 26 namespace testUnknownCallee { 27 struct S { 28 void foo(); 29 }; 30 void bar(S *s, void (S::*func)(void)) { 31 (s->*func)(); // no-crash 32 } 33 } // namespace testUnknownCallee 34 35 class A { 36 public: 37 A(){}; 38 void foo(); 39 }; 40 41 A *return_null() { 42 return nullptr; 43 } 44 45 void derefAfterValidCtr() { 46 std::unique_ptr<A> P(new A()); 47 clang_analyzer_numTimesReached(); // expected-warning {{1}} 48 P->foo(); // No warning. 49 } 50 51 void derefOfUnknown(std::unique_ptr<A> P) { 52 P->foo(); // No warning. 53 } 54 55 void derefAfterDefaultCtr() { 56 std::unique_ptr<A> P; 57 clang_analyzer_numTimesReached(); // expected-warning {{1}} 58 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 59 } 60 61 void derefAfterCtrWithNull() { 62 std::unique_ptr<A> P(nullptr); 63 clang_analyzer_numTimesReached(); // expected-warning {{1}} 64 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 65 } 66 67 void derefAfterCtrWithNullVariable() { 68 A *InnerPtr = nullptr; 69 std::unique_ptr<A> P(InnerPtr); 70 clang_analyzer_numTimesReached(); // expected-warning {{1}} 71 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 72 } 73 74 void derefAfterRelease() { 75 std::unique_ptr<A> P(new A()); 76 P.release(); 77 clang_analyzer_numTimesReached(); // expected-warning {{1}} 78 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 79 } 80 81 void derefAfterReset() { 82 std::unique_ptr<A> P(new A()); 83 P.reset(); 84 clang_analyzer_numTimesReached(); // expected-warning {{1}} 85 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 86 } 87 88 void derefAfterResetWithNull() { 89 std::unique_ptr<A> P(new A()); 90 P.reset(nullptr); 91 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 92 } 93 94 void derefAfterResetWithNonNull() { 95 std::unique_ptr<A> P; 96 P.reset(new A()); 97 clang_analyzer_numTimesReached(); // expected-warning {{1}} 98 P->foo(); // No warning. 99 } 100 101 void derefAfterReleaseAndResetWithNonNull() { 102 std::unique_ptr<A> P(new A()); 103 P.release(); 104 P.reset(new A()); 105 P->foo(); // No warning. 106 } 107 108 void derefOnReleasedNullRawPtr() { 109 std::unique_ptr<A> P; 110 A *AP = P.release(); 111 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 112 } 113 114 void derefOnReleasedValidRawPtr() { 115 std::unique_ptr<A> P(new A()); 116 A *AP = P.release(); 117 AP->foo(); // No warning. 118 } 119 120 void pass_smart_ptr_by_ref(std::unique_ptr<A> &a); 121 void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a); 122 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a); 123 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a); 124 void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a); 125 void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a); 126 127 void regioninvalidationWithPassByRef() { 128 std::unique_ptr<A> P; 129 pass_smart_ptr_by_ref(P); 130 P->foo(); // no-warning 131 } 132 133 void regioninvalidationWithPassByCostRef() { 134 std::unique_ptr<A> P; 135 pass_smart_ptr_by_const_ref(P); 136 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 137 } 138 139 void regioninvalidationWithPassByRValueRef() { 140 std::unique_ptr<A> P; 141 pass_smart_ptr_by_rvalue_ref(std::move(P)); 142 P->foo(); // no-warning 143 } 144 145 void regioninvalidationWithPassByConstRValueRef() { 146 std::unique_ptr<A> P; 147 pass_smart_ptr_by_const_rvalue_ref(std::move(P)); 148 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 149 } 150 151 void regioninvalidationWithPassByPtr() { 152 std::unique_ptr<A> P; 153 pass_smart_ptr_by_ptr(&P); 154 P->foo(); 155 } 156 157 void regioninvalidationWithPassByConstPtr() { 158 std::unique_ptr<A> P; 159 pass_smart_ptr_by_const_ptr(&P); 160 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 161 } 162 163 struct StructWithSmartPtr { 164 std::unique_ptr<A> P; 165 }; 166 167 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a); 168 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a); 169 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a); 170 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a); 171 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a); 172 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a); 173 174 void regioninvalidationWithinStructPassByRef() { 175 StructWithSmartPtr S; 176 pass_struct_with_smart_ptr_by_ref(S); 177 S.P->foo(); // no-warning 178 } 179 180 void regioninvalidationWithinStructPassByConstRef() { 181 StructWithSmartPtr S; 182 pass_struct_with_smart_ptr_by_const_ref(S); 183 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 184 } 185 186 void regioninvalidationWithinStructPassByRValueRef() { 187 StructWithSmartPtr S; 188 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S)); 189 S.P->foo(); // no-warning 190 } 191 192 void regioninvalidationWithinStructPassByConstRValueRef() { 193 StructWithSmartPtr S; 194 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S)); 195 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 196 } 197 198 void regioninvalidationWithinStructPassByPtr() { 199 StructWithSmartPtr S; 200 pass_struct_with_smart_ptr_by_ptr(&S); 201 S.P->foo(); // no-warning 202 } 203 204 void regioninvalidationWithinStructPassByConstPtr() { 205 StructWithSmartPtr S; 206 pass_struct_with_smart_ptr_by_const_ptr(&S); 207 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 208 } 209 210 void derefAfterAssignment() { 211 { 212 std::unique_ptr<A> P(new A()); 213 std::unique_ptr<A> Q; 214 Q = std::move(P); 215 Q->foo(); // no-warning 216 } 217 { 218 std::unique_ptr<A> P; 219 std::unique_ptr<A> Q; 220 Q = std::move(P); 221 Q->foo(); // expected-warning {{Dereference of null smart pointer 'Q' [alpha.cplusplus.SmartPtr]}} 222 } 223 } 224 225 void derefOnSwappedNullPtr() { 226 std::unique_ptr<A> P(new A()); 227 std::unique_ptr<A> PNull; 228 P.swap(PNull); 229 PNull->foo(); // No warning. 230 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 231 } 232 233 void derefOnFirstStdSwappedNullPtr() { 234 std::unique_ptr<A> P; 235 std::unique_ptr<A> PNull; 236 std::swap(P, PNull); 237 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 238 } 239 240 void derefOnSecondStdSwappedNullPtr() { 241 std::unique_ptr<A> P; 242 std::unique_ptr<A> PNull; 243 std::swap(P, PNull); 244 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 245 } 246 247 void derefOnSwappedValidPtr() { 248 std::unique_ptr<A> P(new A()); 249 std::unique_ptr<A> PValid(new A()); 250 P.swap(PValid); 251 (*P).foo(); // No warning. 252 PValid->foo(); // No warning. 253 std::swap(P, PValid); 254 P->foo(); // No warning. 255 PValid->foo(); // No warning. 256 } 257 258 void derefOnRawPtrFromGetOnNullPtr() { 259 std::unique_ptr<A> P; 260 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 261 } 262 263 void derefOnRawPtrFromGetOnValidPtr() { 264 std::unique_ptr<A> P(new A()); 265 P.get()->foo(); // No warning. 266 } 267 268 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { 269 P.get()->foo(); // No warning. 270 } 271 272 void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P) { 273 A *X = P.get(); 274 A *Y = P.get(); 275 clang_analyzer_eval(X == Y); // expected-warning{{TRUE}} 276 if (!X) { 277 Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 278 } 279 } 280 281 void derefOnMovedFromValidPtr() { 282 std::unique_ptr<A> PToMove(new A()); 283 std::unique_ptr<A> P; 284 P = std::move(PToMove); 285 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 286 } 287 288 void derefOnMovedToNullPtr() { 289 std::unique_ptr<A> PToMove(new A()); 290 std::unique_ptr<A> P; 291 P = std::move(PToMove); // No note. 292 P->foo(); // No warning. 293 } 294 295 void derefOnNullPtrGotMovedFromValidPtr() { 296 std::unique_ptr<A> P(new A()); 297 std::unique_ptr<A> PToMove; 298 P = std::move(PToMove); 299 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 300 } 301 302 void derefOnMovedFromUnknownPtr(std::unique_ptr<A> PToMove) { 303 std::unique_ptr<A> P; 304 P = std::move(PToMove); 305 P->foo(); // No warning. 306 } 307 308 void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) { 309 std::unique_ptr<A> P; 310 P = std::move(PToMove); 311 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 312 } 313 314 void derefOnAssignedNullPtrToNullSmartPtr() { 315 std::unique_ptr<A> P; 316 P = nullptr; 317 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 318 } 319 320 void derefOnAssignedZeroToNullSmartPtr() { 321 std::unique_ptr<A> P(new A()); 322 P = 0; 323 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 324 } 325 326 void derefOnAssignedNullToUnknowSmartPtr(std::unique_ptr<A> P) { 327 P = nullptr; 328 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 329 } 330 331 std::unique_ptr<A> &&returnRValRefOfUniquePtr(); 332 333 void drefOnAssignedNullFromMethodPtrValidSmartPtr() { 334 std::unique_ptr<A> P(new A()); 335 P = returnRValRefOfUniquePtr(); 336 P->foo(); // No warning. 337 } 338 339 void derefMoveConstructedWithValidPtr() { 340 std::unique_ptr<A> PToMove(new A()); 341 std::unique_ptr<A> P(std::move(PToMove)); 342 P->foo(); // No warning. 343 } 344 345 void derefMoveConstructedWithNullPtr() { 346 std::unique_ptr<A> PToMove; 347 std::unique_ptr<A> P(std::move(PToMove)); 348 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 349 } 350 351 void derefMoveConstructedWithUnknownPtr(std::unique_ptr<A> PToMove) { 352 std::unique_ptr<A> P(std::move(PToMove)); 353 P->foo(); // No warning. 354 } 355 356 void derefValidPtrMovedToConstruct() { 357 std::unique_ptr<A> PToMove(new A()); 358 std::unique_ptr<A> P(std::move(PToMove)); 359 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 360 } 361 362 void derefNullPtrMovedToConstruct() { 363 std::unique_ptr<A> PToMove; 364 std::unique_ptr<A> P(std::move(PToMove)); 365 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 366 } 367 368 void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) { 369 std::unique_ptr<A> P(std::move(PToMove)); 370 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 371 } 372 373 std::unique_ptr<A> &&functionReturnsRValueRef(); 374 375 void derefMoveConstructedWithRValueRefReturn() { 376 std::unique_ptr<A> P(functionReturnsRValueRef()); 377 P->foo(); // No warning. 378 } 379 380 void derefConditionOnNullPtr() { 381 std::unique_ptr<A> P; 382 if (P) 383 P->foo(); // No warning. 384 else 385 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 386 } 387 388 void derefConditionOnNotNullPtr() { 389 std::unique_ptr<A> P; 390 if (!P) 391 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 392 } 393 394 void derefConditionOnValidPtr() { 395 std::unique_ptr<A> P(new A()); 396 std::unique_ptr<A> PNull; 397 if (P) 398 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 399 } 400 401 void derefConditionOnNotValidPtr() { 402 std::unique_ptr<A> P(new A()); 403 std::unique_ptr<A> PNull; 404 if (!P) 405 PNull->foo(); // No warning. 406 } 407 408 void derefConditionOnUnKnownPtr(std::unique_ptr<A> P) { 409 if (P) 410 P->foo(); // No warning. 411 else 412 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 413 } 414 415 void derefOnValidPtrAfterReset(std::unique_ptr<A> P) { 416 P.reset(new A()); 417 if (!P) 418 P->foo(); // No warning. 419 else 420 P->foo(); // No warning. 421 } 422 423 void innerPointerSymbolLiveness() { 424 std::unique_ptr<int> P(new int()); 425 clang_analyzer_warnOnDeadSymbol(P.get()); 426 int *RP = P.release(); 427 } // expected-warning{{SYMBOL DEAD}} 428 429 void boolOpCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) { 430 if (P) { 431 int *X = P.get(); 432 clang_analyzer_warnOnDeadSymbol(X); 433 } 434 } // expected-warning{{SYMBOL DEAD}} 435 436 void getCreatedConjuredSymbolLiveness(std::unique_ptr<int> P) { 437 int *X = P.get(); 438 clang_analyzer_warnOnDeadSymbol(X); 439 int Y; 440 if (!P) { 441 Y = *P.get(); // expected-warning {{Dereference of null pointer [core.NullDereference]}} 442 // expected-warning@-1 {{SYMBOL DEAD}} 443 } 444 } 445 446 int derefConditionOnUnKnownPtr(int *q) { 447 std::unique_ptr<int> P(q); 448 if (P) 449 return *P; // No warning. 450 else 451 return *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 452 } 453 454 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) { 455 A *RP = P.get(); 456 if (!RP) { 457 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 458 } 459 } 460