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 12 void derefAfterMove(std::unique_ptr<int> P) { 13 std::unique_ptr<int> Q = std::move(P); 14 if (Q) 15 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} 16 *Q.get() = 1; // no-warning 17 if (P) 18 clang_analyzer_warnIfReached(); // no-warning 19 // TODO: Report a null dereference (instead). 20 *P.get() = 1; // expected-warning {{Method called on moved-from object 'P'}} 21 } 22 23 // Don't crash when attempting to model a call with unknown callee. 24 namespace testUnknownCallee { 25 struct S { 26 void foo(); 27 }; 28 void bar(S *s, void (S::*func)(void)) { 29 (s->*func)(); // no-crash 30 } 31 } // namespace testUnknownCallee 32 33 class A { 34 public: 35 A(){}; 36 void foo(); 37 }; 38 39 A *return_null() { 40 return nullptr; 41 } 42 43 void derefAfterValidCtr() { 44 std::unique_ptr<A> P(new A()); 45 clang_analyzer_numTimesReached(); // expected-warning {{1}} 46 P->foo(); // No warning. 47 } 48 49 void derefOfUnknown(std::unique_ptr<A> P) { 50 P->foo(); // No warning. 51 } 52 53 void derefAfterDefaultCtr() { 54 std::unique_ptr<A> P; 55 clang_analyzer_numTimesReached(); // expected-warning {{1}} 56 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 57 } 58 59 void derefAfterCtrWithNull() { 60 std::unique_ptr<A> P(nullptr); 61 clang_analyzer_numTimesReached(); // expected-warning {{1}} 62 *P; // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 63 } 64 65 void derefAfterCtrWithNullVariable() { 66 A *InnerPtr = nullptr; 67 std::unique_ptr<A> P(InnerPtr); 68 clang_analyzer_numTimesReached(); // expected-warning {{1}} 69 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 70 } 71 72 void derefAfterRelease() { 73 std::unique_ptr<A> P(new A()); 74 P.release(); 75 clang_analyzer_numTimesReached(); // expected-warning {{1}} 76 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 77 } 78 79 void derefAfterReset() { 80 std::unique_ptr<A> P(new A()); 81 P.reset(); 82 clang_analyzer_numTimesReached(); // expected-warning {{1}} 83 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 84 } 85 86 void derefAfterResetWithNull() { 87 std::unique_ptr<A> P(new A()); 88 P.reset(nullptr); 89 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 90 } 91 92 void derefAfterResetWithNonNull() { 93 std::unique_ptr<A> P; 94 P.reset(new A()); 95 clang_analyzer_numTimesReached(); // expected-warning {{1}} 96 P->foo(); // No warning. 97 } 98 99 void derefAfterReleaseAndResetWithNonNull() { 100 std::unique_ptr<A> P(new A()); 101 P.release(); 102 P.reset(new A()); 103 P->foo(); // No warning. 104 } 105 106 void derefOnReleasedNullRawPtr() { 107 std::unique_ptr<A> P; 108 A *AP = P.release(); 109 AP->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 110 } 111 112 void derefOnReleasedValidRawPtr() { 113 std::unique_ptr<A> P(new A()); 114 A *AP = P.release(); 115 AP->foo(); // No warning. 116 } 117 118 void pass_smart_ptr_by_ref(std::unique_ptr<A> &a); 119 void pass_smart_ptr_by_const_ref(const std::unique_ptr<A> &a); 120 void pass_smart_ptr_by_rvalue_ref(std::unique_ptr<A> &&a); 121 void pass_smart_ptr_by_const_rvalue_ref(const std::unique_ptr<A> &&a); 122 void pass_smart_ptr_by_ptr(std::unique_ptr<A> *a); 123 void pass_smart_ptr_by_const_ptr(const std::unique_ptr<A> *a); 124 125 void regioninvalidationWithPassByRef() { 126 std::unique_ptr<A> P; 127 pass_smart_ptr_by_ref(P); 128 P->foo(); // no-warning 129 } 130 131 void regioninvalidationWithPassByCostRef() { 132 std::unique_ptr<A> P; 133 pass_smart_ptr_by_const_ref(P); 134 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 135 } 136 137 void regioninvalidationWithPassByRValueRef() { 138 std::unique_ptr<A> P; 139 pass_smart_ptr_by_rvalue_ref(std::move(P)); 140 P->foo(); // no-warning 141 } 142 143 void regioninvalidationWithPassByConstRValueRef() { 144 std::unique_ptr<A> P; 145 pass_smart_ptr_by_const_rvalue_ref(std::move(P)); 146 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 147 } 148 149 void regioninvalidationWithPassByPtr() { 150 std::unique_ptr<A> P; 151 pass_smart_ptr_by_ptr(&P); 152 P->foo(); 153 } 154 155 void regioninvalidationWithPassByConstPtr() { 156 std::unique_ptr<A> P; 157 pass_smart_ptr_by_const_ptr(&P); 158 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 159 } 160 161 struct StructWithSmartPtr { 162 std::unique_ptr<A> P; 163 }; 164 165 void pass_struct_with_smart_ptr_by_ref(StructWithSmartPtr &a); 166 void pass_struct_with_smart_ptr_by_const_ref(const StructWithSmartPtr &a); 167 void pass_struct_with_smart_ptr_by_rvalue_ref(StructWithSmartPtr &&a); 168 void pass_struct_with_smart_ptr_by_const_rvalue_ref(const StructWithSmartPtr &&a); 169 void pass_struct_with_smart_ptr_by_ptr(StructWithSmartPtr *a); 170 void pass_struct_with_smart_ptr_by_const_ptr(const StructWithSmartPtr *a); 171 172 void regioninvalidationWithinStructPassByRef() { 173 StructWithSmartPtr S; 174 pass_struct_with_smart_ptr_by_ref(S); 175 S.P->foo(); // no-warning 176 } 177 178 void regioninvalidationWithinStructPassByConstRef() { 179 StructWithSmartPtr S; 180 pass_struct_with_smart_ptr_by_const_ref(S); 181 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 182 } 183 184 void regioninvalidationWithinStructPassByRValueRef() { 185 StructWithSmartPtr S; 186 pass_struct_with_smart_ptr_by_rvalue_ref(std::move(S)); 187 S.P->foo(); // no-warning 188 } 189 190 void regioninvalidationWithinStructPassByConstRValueRef() { 191 StructWithSmartPtr S; 192 pass_struct_with_smart_ptr_by_const_rvalue_ref(std::move(S)); 193 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 194 } 195 196 void regioninvalidationWithinStructPassByPtr() { 197 StructWithSmartPtr S; 198 pass_struct_with_smart_ptr_by_ptr(&S); 199 S.P->foo(); // no-warning 200 } 201 202 void regioninvalidationWithinStructPassByConstPtr() { 203 StructWithSmartPtr S; 204 pass_struct_with_smart_ptr_by_const_ptr(&S); 205 S.P->foo(); // expected-warning {{Dereference of null smart pointer 'S.P' [alpha.cplusplus.SmartPtr]}} 206 } 207 208 void derefAfterAssignment() { 209 { 210 std::unique_ptr<A> P(new A()); 211 std::unique_ptr<A> Q; 212 Q = std::move(P); 213 Q->foo(); // no-warning 214 } 215 { 216 std::unique_ptr<A> P; 217 std::unique_ptr<A> Q; 218 Q = std::move(P); 219 // TODO: Fix test with expecting warning after '=' operator overloading modeling. 220 Q->foo(); // no-warning 221 } 222 } 223 224 void derefOnSwappedNullPtr() { 225 std::unique_ptr<A> P(new A()); 226 std::unique_ptr<A> PNull; 227 P.swap(PNull); 228 PNull->foo(); // No warning. 229 (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 230 } 231 232 void derefOnFirstStdSwappedNullPtr() { 233 std::unique_ptr<A> P; 234 std::unique_ptr<A> PNull; 235 std::swap(P, PNull); 236 P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} 237 } 238 239 void derefOnSecondStdSwappedNullPtr() { 240 std::unique_ptr<A> P; 241 std::unique_ptr<A> PNull; 242 std::swap(P, PNull); 243 PNull->foo(); // expected-warning {{Dereference of null smart pointer 'PNull' [alpha.cplusplus.SmartPtr]}} 244 } 245 246 void derefOnSwappedValidPtr() { 247 std::unique_ptr<A> P(new A()); 248 std::unique_ptr<A> PValid(new A()); 249 P.swap(PValid); 250 (*P).foo(); // No warning. 251 PValid->foo(); // No warning. 252 std::swap(P, PValid); 253 P->foo(); // No warning. 254 PValid->foo(); // No warning. 255 } 256 257 void derefOnRawPtrFromGetOnNullPtr() { 258 std::unique_ptr<A> P; 259 P.get()->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 260 } 261 262 void derefOnRawPtrFromGetOnValidPtr() { 263 std::unique_ptr<A> P(new A()); 264 P.get()->foo(); // No warning. 265 } 266 267 void derefOnRawPtrFromGetOnUnknownPtr(std::unique_ptr<A> P) { 268 P.get()->foo(); // No warning. 269 } 270 271 void derefOnRawPtrFromMultipleGetOnUnknownPtr(std::unique_ptr<A> P) { 272 A *X = P.get(); 273 A *Y = P.get(); 274 clang_analyzer_eval(X == Y); // expected-warning{{TRUE}} 275 if (!X) { 276 Y->foo(); // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 277 } 278 } 279