1 // RUN: %clang_analyze_cc1\ 2 // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\ 3 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 4 // RUN: -analyzer-output=text -std=c++20 %s -verify=expected 5 6 // RUN: %clang_analyze_cc1\ 7 // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\ 8 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 9 // RUN: -analyzer-output=text -std=c++11 %s -verify=expected 10 11 #include "Inputs/system-header-simulator-cxx.h" 12 13 void clang_analyzer_eval(bool); 14 15 class A { 16 public: 17 A(){}; 18 void foo(); 19 }; 20 21 A *return_null() { 22 return nullptr; 23 } 24 25 void derefAfterDefaultCtr() { 26 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 27 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 28 // expected-note@-1{{Dereference of null smart pointer 'P'}} 29 } 30 31 void derefAfterCtrWithNull() { 32 A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} 33 std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}} 34 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 35 // expected-note@-1{{Dereference of null smart pointer 'P'}} 36 } 37 38 void derefAfterCtrWithNullVariable() { 39 A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} 40 std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}} 41 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 42 // expected-note@-1{{Dereference of null smart pointer 'P'}} 43 } 44 45 void derefAfterRelease() { 46 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 47 // FIXME: should mark region as uninteresting after release, so above note will not be there 48 P.release(); // expected-note {{Smart pointer 'P' is released and set to null}} 49 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 50 // expected-note@-1{{Dereference of null smart pointer 'P'}} 51 } 52 53 void derefAfterReset() { 54 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 55 P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} 56 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 57 // expected-note@-1{{Dereference of null smart pointer 'P'}} 58 } 59 60 void derefAfterResetWithNull() { 61 A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} 62 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 63 P.reset(NullInnerPtr); // expected-note {{Smart pointer 'P' reset using a null value}} 64 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 65 // expected-note@-1{{Dereference of null smart pointer 'P'}} 66 } 67 68 // FIXME: Fix this test when support is added for tracking raw pointer 69 // and mark the smart pointer as interesting based on that and add tags. 70 void derefOnReleasedNullRawPtr() { 71 std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null" 72 A *AP = P.release(); // expected-note {{'AP' initialized to a null pointer value}} 73 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 74 // expected-note@-1{{Called C++ object pointer is null}} 75 } 76 77 void derefOnSwappedNullPtr() { 78 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 79 std::unique_ptr<A> PNull; 80 P.swap(PNull); 81 PNull->foo(); // No warning. 82 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 83 // expected-note@-1{{Dereference of null smart pointer 'P'}} 84 } 85 86 void derefOnStdSwappedNullPtr() { 87 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 88 std::unique_ptr<A> PNull; 89 std::swap(P, PNull); 90 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 91 // expected-note@-1{{Dereference of null smart pointer 'P'}} 92 } 93 94 struct StructWithSmartPtr { // expected-note {{Default constructed smart pointer 'S.P' is null}} 95 std::unique_ptr<A> P; 96 }; 97 98 void derefAfterDefaultCtrInsideStruct() { 99 StructWithSmartPtr S; // expected-note {{Calling implicit default constructor for 'StructWithSmartPtr'}} 100 // expected-note@-1 {{Returning from default constructor for 'StructWithSmartPtr'}} 101 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 102 // expected-note@-1{{Dereference of null smart pointer 'S.P'}} 103 } 104 105 void noNoteTagsForNonInterestingRegion() { 106 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 107 std::unique_ptr<A> P1; // No note. 108 std::unique_ptr<A> P2; // No note. 109 P1.release(); // No note. 110 P1.reset(); // No note. 111 P1.swap(P2); // No note. 112 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 113 // expected-note@-1{{Dereference of null smart pointer 'P'}} 114 } 115 116 void derefOnRawPtrFromGetOnNullPtr() { 117 std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null" 118 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 119 // expected-note@-1 {{Called C++ object pointer is null}} 120 } 121 122 void derefOnRawPtrFromGetOnValidPtr() { 123 std::unique_ptr<A> P(new A()); 124 P.get()->foo(); // No warning. 125 } 126 127 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { 128 P.get()->foo(); // No warning. 129 } 130 131 void derefOnMovedFromValidPtr() { 132 std::unique_ptr<A> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}} 133 // FIXME: above note should go away once we fix marking region not interested. 134 std::unique_ptr<A> P; 135 P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} 136 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 137 // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}} 138 } 139 140 void derefOnMovedToNullPtr() { 141 std::unique_ptr<A> PToMove(new A()); 142 std::unique_ptr<A> P; 143 P = std::move(PToMove); // No note. 144 P->foo(); // No warning. 145 } 146 147 void derefOnNullPtrGotMovedFromValidPtr() { 148 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 149 // FIXME: above note should go away once we fix marking region not interested. 150 std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} 151 P = std::move(PToMove); // expected-note {{A null pointer value is moved to 'P'}} 152 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 153 // expected-note@-1 {{Dereference of null smart pointer 'P'}} 154 } 155 156 void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) { 157 std::unique_ptr<A> P; 158 P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}} 159 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 160 // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}} 161 } 162 163 void derefOnAssignedNullPtrToNullSmartPtr() { 164 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 165 P = nullptr; // expected-note {{Smart pointer 'P' is assigned to null}} 166 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 167 // expected-note@-1 {{Dereference of null smart pointer 'P'}} 168 } 169 170 void derefOnAssignedZeroToNullSmartPtr() { 171 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 172 // FIXME: above note should go away once we fix marking region not interested. 173 P = 0; // expected-note {{Smart pointer 'P' is assigned to null}} 174 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 175 // expected-note@-1 {{Dereference of null smart pointer 'P'}} 176 } 177 178 void derefMoveConstructedWithNullPtr() { 179 std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} 180 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{A null pointer value is moved to 'P'}} 181 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 182 // expected-note@-1{{Dereference of null smart pointer 'P'}} 183 } 184 185 void derefValidPtrMovedToConstruct() { 186 std::unique_ptr<A> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}} 187 // FIXME: above note should go away once we fix marking region not interested. 188 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} 189 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 190 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} 191 } 192 193 void derefNullPtrMovedToConstruct() { 194 std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} 195 // FIXME: above note should go away once we fix marking region not interested. 196 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} 197 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 198 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} 199 } 200 201 void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) { 202 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}} 203 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 204 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} 205 } 206 207 void derefConditionOnNullPtrFalseBranch() { 208 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 209 if (P) { // expected-note {{Taking false branch}} 210 P->foo(); // No warning. 211 } else { 212 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 213 // expected-note@-1{{Dereference of null smart pointer 'P'}} 214 } 215 } 216 217 void derefConditionOnNullPtrTrueBranch() { 218 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 219 if (!P) { // expected-note {{Taking true branch}} 220 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 221 // expected-note@-1{{Dereference of null smart pointer 'P'}} 222 } 223 } 224 225 void derefConditionOnValidPtrTrueBranch() { 226 std::unique_ptr<A> P(new A()); 227 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 228 if (P) { // expected-note {{Taking true branch}} 229 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 230 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 231 } else { 232 PNull->foo(); // No warning 233 } 234 } 235 236 void derefConditionOnValidPtrFalseBranch() { 237 std::unique_ptr<A> P(new A()); 238 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 239 if (!P) { // expected-note {{Taking false branch}} 240 PNull->foo(); // No warning 241 } else { 242 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 243 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 244 } 245 } 246 247 void derefConditionOnNotValidPtr() { 248 std::unique_ptr<A> P(new A()); 249 std::unique_ptr<A> PNull; 250 if (!P) 251 PNull->foo(); // No warning. 252 } 253 254 void derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr<A> P) { 255 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 256 if (!P) { // expected-note {{Taking true branch}} 257 // expected-note@-1{{Assuming smart pointer 'P' is null}} 258 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 259 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 260 } 261 } 262 263 void derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr<A> P) { 264 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 265 if (P) { // expected-note {{Taking true branch}} 266 // expected-note@-1{{Assuming smart pointer 'P' is non-null}} 267 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 268 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 269 } 270 } 271 272 void derefOnValidPtrAfterReset(std::unique_ptr<A> P) { 273 P.reset(new A()); 274 if (!P) 275 P->foo(); // No warning. 276 else 277 P->foo(); // No warning. 278 } 279 280 struct S { 281 std::unique_ptr<int> P; 282 283 void foo() { 284 if (!P) { // No-note because foo() is pruned 285 return; 286 } 287 } 288 289 int callingFooWithNullPointer() { 290 foo(); // No note on Calling 'S::foo' 291 P.reset(new int(0)); // expected-note {{Assigning 0}} 292 return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} 293 // expected-note@-1 {{Division by zero}} 294 } 295 296 int callingFooWithValidPointer() { 297 P.reset(new int(0)); // expected-note {{Assigning 0}} 298 foo(); // No note on Calling 'S::foo' 299 return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} 300 // expected-note@-1 {{Division by zero}} 301 } 302 303 int callingFooWithUnknownPointer(std::unique_ptr<int> PUnknown) { 304 P.swap(PUnknown); 305 foo(); // No note on Calling 'S::foo' 306 P.reset(new int(0)); // expected-note {{Assigning 0}} 307 return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} 308 // expected-note@-1 {{Division by zero}} 309 } 310 }; 311 312 void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) { 313 A *RP = P.get(); 314 if (!RP) { // expected-note {{Assuming 'RP' is null}} 315 // expected-note@-1 {{Taking true branch}} 316 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 317 // expected-note@-1{{Dereference of null smart pointer 'P'}} 318 } 319 } 320 321 void makeUniqueReturnsNonNullUniquePtr() { 322 auto P = std::make_unique<A>(); 323 if (!P) { // expected-note {{Taking false branch}} 324 P->foo(); // should have no warning here, path is impossible 325 } 326 P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} 327 // Now P is null 328 if (!P) { 329 // expected-note@-1 {{Taking true branch}} 330 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 331 // expected-note@-1{{Dereference of null smart pointer 'P'}} 332 } 333 } 334 335 #if __cplusplus >= 202002L 336 337 void makeUniqueForOverwriteReturnsNullUniquePtr() { 338 auto P = std::make_unique_for_overwrite<A>(); 339 if (!P) { // expected-note {{Taking false branch}} 340 P->foo(); // should have no warning here, path is impossible 341 } 342 P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} 343 // Now P is null 344 if (!P) { 345 // expected-note@-1 {{Taking true branch}} 346 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 347 // expected-note@-1{{Dereference of null smart pointer 'P'}} 348 } 349 } 350 351 #endif 352 353 struct G { 354 int *p; 355 G(int *p): p(p) {} 356 ~G() { *p = 0; } 357 }; 358 359 void foo() { 360 int x = 1; 361 { 362 auto P = std::make_unique<G>(&x); 363 // FIXME: There should not be a state split here, it should take the true path. 364 clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}} 365 // expected-warning@-1 {{FALSE}} 366 // expected-note@-2 {{Assuming the condition is true}} 367 // expected-note@-3 {{Assuming the condition is false}} 368 // expected-note@-4 {{TRUE}} 369 // expected-note@-5 {{FALSE}} 370 // expected-note@-6 {{Assuming the condition is false}} 371 } 372 // FIXME: Should be fixed when unique_ptr desctructors are 373 // properly modelled. This includes modelling the call to 374 // the destructor of the inner pointer type. 375 clang_analyzer_eval(x == 0); // expected-warning {{FALSE}} 376 // expected-note@-1 {{FALSE}} 377 } 378