378 lines · cpp
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=expected5 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=expected10 11#include "Inputs/system-header-simulator-cxx.h"12 13void clang_analyzer_eval(bool);14 15class A {16public:17 A(){};18 void foo();19};20 21A *return_null() {22 return nullptr;23}24 25void 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 31void 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 38void 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 45void 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 there48 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 53void 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 60void 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 pointer69// and mark the smart pointer as interesting based on that and add tags.70void 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 77void 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 86void 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 94struct StructWithSmartPtr { // expected-note {{Default constructed smart pointer 'S.P' is null}}95 std::unique_ptr<A> P;96};97 98void 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 105void 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 116void 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 122void derefOnRawPtrFromGetOnValidPtr() {123 std::unique_ptr<A> P(new A());124 P.get()->foo(); // No warning.125}126 127void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) {128 P.get()->foo(); // No warning.129}130 131void 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 140void 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 147void 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 156void 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 163void 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 170void 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 178void 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 185void 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 193void 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 201void 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 207void 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 217void 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 225void 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 warning233 }234}235 236void 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 warning241 } 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 247void 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 254void 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 263void 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 272void derefOnValidPtrAfterReset(std::unique_ptr<A> P) {273 P.reset(new A());274 if (!P)275 P->foo(); // No warning.276 else277 P->foo(); // No warning.278}279 280struct S {281 std::unique_ptr<int> P;282 283 void foo() {284 if (!P) { // No-note because foo() is pruned285 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 312void 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 321void 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 impossible325 }326 P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}327 // Now P is null328 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 >= 202002L336 337void 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 impossible341 }342 P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}}343 // Now P is null344 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#endif352 353struct G {354 int *p;355 G(int *p): p(p) {}356 ~G() { *p = 0; }357};358 359void 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 are373 // properly modelled. This includes modelling the call to374 // the destructor of the inner pointer type.375 clang_analyzer_eval(x == 0); // expected-warning {{FALSE}}376 // expected-note@-1 {{FALSE}}377}378