1 // RUN: %clang_analyze_cc1\ 2 // RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\ 3 // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ 4 // RUN: -analyzer-output=text -std=c++11 %s -verify=expected 5 6 #include "Inputs/system-header-simulator-cxx.h" 7 8 class A { 9 public: A()10 A(){}; 11 void foo(); 12 }; 13 return_null()14A *return_null() { 15 return nullptr; 16 } 17 derefAfterDefaultCtr()18void derefAfterDefaultCtr() { 19 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 20 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 21 // expected-note@-1{{Dereference of null smart pointer 'P'}} 22 } 23 derefAfterCtrWithNull()24void derefAfterCtrWithNull() { 25 A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} 26 std::unique_ptr<A> P(NullInnerPtr); // expected-note {{Smart pointer 'P' is constructed using a null value}} 27 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 28 // expected-note@-1{{Dereference of null smart pointer 'P'}} 29 } 30 derefAfterCtrWithNullVariable()31void derefAfterCtrWithNullVariable() { 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->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 35 // expected-note@-1{{Dereference of null smart pointer 'P'}} 36 } 37 derefAfterRelease()38void derefAfterRelease() { 39 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 40 // FIXME: should mark region as uninteresting after release, so above note will not be there 41 P.release(); // expected-note {{Smart pointer 'P' is released and set to null}} 42 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 43 // expected-note@-1{{Dereference of null smart pointer 'P'}} 44 } 45 derefAfterReset()46void derefAfterReset() { 47 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 48 P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} 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 derefAfterResetWithNull()53void derefAfterResetWithNull() { 54 A *NullInnerPtr = nullptr; // expected-note {{'NullInnerPtr' initialized to a null pointer value}} 55 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 56 P.reset(NullInnerPtr); // expected-note {{Smart pointer 'P' reset using a null value}} 57 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 58 // expected-note@-1{{Dereference of null smart pointer 'P'}} 59 } 60 61 // FIXME: Fix this test when support is added for tracking raw pointer 62 // and mark the smart pointer as interesting based on that and add tags. derefOnReleasedNullRawPtr()63void derefOnReleasedNullRawPtr() { 64 std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null" 65 A *AP = P.release(); // expected-note {{'AP' initialized to a null pointer value}} 66 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 67 // expected-note@-1{{Called C++ object pointer is null}} 68 } 69 derefOnSwappedNullPtr()70void derefOnSwappedNullPtr() { 71 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 72 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 73 P.swap(PNull); // expected-note {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} 74 PNull->foo(); // No warning. 75 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 76 // expected-note@-1{{Dereference of null smart pointer 'P'}} 77 } 78 79 // FIXME: Fix this test when "std::swap" is modeled seperately. derefOnStdSwappedNullPtr()80void derefOnStdSwappedNullPtr() { 81 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 82 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 83 std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:979 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} 84 // expected-note@-1 {{Calling 'swap<A>'}} 85 // expected-note@-2 {{Returning from 'swap<A>'}} 86 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 87 // expected-note@-1{{Dereference of null smart pointer 'P'}} 88 } 89 90 struct StructWithSmartPtr { // expected-note {{Default constructed smart pointer 'S.P' is null}} 91 std::unique_ptr<A> P; 92 }; 93 derefAfterDefaultCtrInsideStruct()94void derefAfterDefaultCtrInsideStruct() { 95 StructWithSmartPtr S; // expected-note {{Calling implicit default constructor for 'StructWithSmartPtr'}} 96 // expected-note@-1 {{Returning from default constructor for 'StructWithSmartPtr'}} 97 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 98 // expected-note@-1{{Dereference of null smart pointer 'S.P'}} 99 } 100 noNoteTagsForNonInterestingRegion()101void noNoteTagsForNonInterestingRegion() { 102 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 103 std::unique_ptr<A> P1; // No note. 104 std::unique_ptr<A> P2; // No note. 105 P1.release(); // No note. 106 P1.reset(); // No note. 107 P1.swap(P2); // No note. 108 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 109 // expected-note@-1{{Dereference of null smart pointer 'P'}} 110 } 111 derefOnRawPtrFromGetOnNullPtr()112void derefOnRawPtrFromGetOnNullPtr() { 113 std::unique_ptr<A> P; // FIXME: add note "Default constructed smart pointer 'P' is null" 114 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 115 // expected-note@-1 {{Called C++ object pointer is null}} 116 } 117 derefOnRawPtrFromGetOnValidPtr()118void derefOnRawPtrFromGetOnValidPtr() { 119 std::unique_ptr<A> P(new A()); 120 P.get()->foo(); // No warning. 121 } 122 derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P)123void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { 124 P.get()->foo(); // No warning. 125 } 126 derefOnMovedFromValidPtr()127void derefOnMovedFromValidPtr() { 128 std::unique_ptr<A> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}} 129 // FIXME: above note should go away once we fix marking region not interested. 130 std::unique_ptr<A> P; 131 P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} 132 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 133 // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}} 134 } 135 derefOnMovedToNullPtr()136void derefOnMovedToNullPtr() { 137 std::unique_ptr<A> PToMove(new A()); 138 std::unique_ptr<A> P; 139 P = std::move(PToMove); // No note. 140 P->foo(); // No warning. 141 } 142 derefOnNullPtrGotMovedFromValidPtr()143void derefOnNullPtrGotMovedFromValidPtr() { 144 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 145 // FIXME: above note should go away once we fix marking region not interested. 146 std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} 147 P = std::move(PToMove); // expected-note {{A null pointer value is moved to 'P'}} 148 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 149 // expected-note@-1 {{Dereference of null smart pointer 'P'}} 150 } 151 derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove)152void derefOnMovedUnknownPtr(std::unique_ptr<A> PToMove) { 153 std::unique_ptr<A> P; 154 P = std::move(PToMove); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}} 155 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 156 // expected-note@-1 {{Dereference of null smart pointer 'PToMove'}} 157 } 158 derefOnAssignedNullPtrToNullSmartPtr()159void derefOnAssignedNullPtrToNullSmartPtr() { 160 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 161 P = nullptr; // expected-note {{Smart pointer 'P' is assigned to null}} 162 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 163 // expected-note@-1 {{Dereference of null smart pointer 'P'}} 164 } 165 derefOnAssignedZeroToNullSmartPtr()166void derefOnAssignedZeroToNullSmartPtr() { 167 std::unique_ptr<A> P(new A()); // expected-note {{Smart pointer 'P' is constructed}} 168 // FIXME: above note should go away once we fix marking region not interested. 169 P = 0; // expected-note {{Smart pointer 'P' is assigned to null}} 170 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 171 // expected-note@-1 {{Dereference of null smart pointer 'P'}} 172 } 173 derefMoveConstructedWithNullPtr()174void derefMoveConstructedWithNullPtr() { 175 std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} 176 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{A null pointer value is moved to 'P'}} 177 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 178 // expected-note@-1{{Dereference of null smart pointer 'P'}} 179 } 180 derefValidPtrMovedToConstruct()181void derefValidPtrMovedToConstruct() { 182 std::unique_ptr<A> PToMove(new A()); // expected-note {{Smart pointer 'PToMove' is constructed}} 183 // FIXME: above note should go away once we fix marking region not interested. 184 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} 185 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 186 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} 187 } 188 derefNullPtrMovedToConstruct()189void derefNullPtrMovedToConstruct() { 190 std::unique_ptr<A> PToMove; // expected-note {{Default constructed smart pointer 'PToMove' is null}} 191 // FIXME: above note should go away once we fix marking region not interested. 192 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after being moved to 'P'}} 193 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 194 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} 195 } 196 derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove)197void derefUnknownPtrMovedToConstruct(std::unique_ptr<A> PToMove) { 198 std::unique_ptr<A> P(std::move(PToMove)); // expected-note {{Smart pointer 'PToMove' is null after; previous value moved to 'P'}} 199 PToMove->foo(); // expected-warning {{Dereference of null smart pointer 'PToMove' [alpha.cplusplus.SmartPtr]}} 200 // expected-note@-1{{Dereference of null smart pointer 'PToMove'}} 201 } 202 derefConditionOnNullPtrFalseBranch()203void derefConditionOnNullPtrFalseBranch() { 204 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 205 if (P) { // expected-note {{Taking false branch}} 206 P->foo(); // No warning. 207 } else { 208 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 209 // expected-note@-1{{Dereference of null smart pointer 'P'}} 210 } 211 } 212 derefConditionOnNullPtrTrueBranch()213void derefConditionOnNullPtrTrueBranch() { 214 std::unique_ptr<A> P; // expected-note {{Default constructed smart pointer 'P' is null}} 215 if (!P) { // expected-note {{Taking true branch}} 216 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 217 // expected-note@-1{{Dereference of null smart pointer 'P'}} 218 } 219 } 220 derefConditionOnValidPtrTrueBranch()221void derefConditionOnValidPtrTrueBranch() { 222 std::unique_ptr<A> P(new A()); 223 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 224 if (P) { // expected-note {{Taking true branch}} 225 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 226 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 227 } else { 228 PNull->foo(); // No warning 229 } 230 } 231 derefConditionOnValidPtrFalseBranch()232void derefConditionOnValidPtrFalseBranch() { 233 std::unique_ptr<A> P(new A()); 234 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 235 if (!P) { // expected-note {{Taking false branch}} 236 PNull->foo(); // No warning 237 } else { 238 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 239 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 240 } 241 } 242 derefConditionOnNotValidPtr()243void derefConditionOnNotValidPtr() { 244 std::unique_ptr<A> P(new A()); 245 std::unique_ptr<A> PNull; 246 if (!P) 247 PNull->foo(); // No warning. 248 } 249 derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr<A> P)250void derefConditionOnUnKnownPtrAssumeNull(std::unique_ptr<A> P) { 251 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 252 if (!P) { // expected-note {{Taking true branch}} 253 // expected-note@-1{{Assuming smart pointer 'P' is null}} 254 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 255 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 256 } 257 } 258 derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr<A> P)259void derefConditionOnUnKnownPtrAssumeNonNull(std::unique_ptr<A> P) { 260 std::unique_ptr<A> PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} 261 if (P) { // expected-note {{Taking true branch}} 262 // expected-note@-1{{Assuming smart pointer 'P' is non-null}} 263 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 264 // expected-note@-1{{Dereference of null smart pointer 'PNull'}} 265 } 266 } 267 derefOnValidPtrAfterReset(std::unique_ptr<A> P)268void derefOnValidPtrAfterReset(std::unique_ptr<A> P) { 269 P.reset(new A()); 270 if (!P) 271 P->foo(); // No warning. 272 else 273 P->foo(); // No warning. 274 } 275 276 struct S { 277 std::unique_ptr<int> P; 278 fooS279 void foo() { 280 if (!P) { // No-note because foo() is pruned 281 return; 282 } 283 } 284 callingFooWithNullPointerS285 int callingFooWithNullPointer() { 286 foo(); // No note on Calling 'S::foo' 287 P.reset(new int(0)); // expected-note {{Assigning 0}} 288 return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} 289 // expected-note@-1 {{Division by zero}} 290 } 291 callingFooWithValidPointerS292 int callingFooWithValidPointer() { 293 P.reset(new int(0)); // expected-note {{Assigning 0}} 294 foo(); // No note on Calling 'S::foo' 295 return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} 296 // expected-note@-1 {{Division by zero}} 297 } 298 callingFooWithUnknownPointerS299 int callingFooWithUnknownPointer(std::unique_ptr<int> PUnknown) { 300 P.swap(PUnknown); 301 foo(); // No note on Calling 'S::foo' 302 P.reset(new int(0)); // expected-note {{Assigning 0}} 303 return 1 / *(P.get()); // expected-warning {{Division by zero [core.DivideZero]}} 304 // expected-note@-1 {{Division by zero}} 305 } 306 }; 307 derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P)308void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr<A> P) { 309 A *RP = P.get(); 310 if (!RP) { // expected-note {{Assuming 'RP' is null}} 311 // expected-note@-1 {{Taking true branch}} 312 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 313 // expected-note@-1{{Dereference of null smart pointer 'P'}} 314 } 315 } 316