380 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=destructors -verify -std=c++11 %s2// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=destructors -verify -std=c++17 %s3 4using size_t = __typeof(sizeof(int));5 6void clang_analyzer_eval(bool);7void clang_analyzer_checkInlined(bool);8void clang_analyzer_warnIfReached();9void clang_analyzer_explain(int);10 11int a, b, c, d;12 13struct InlineDtor {14 static int cnt;15 static int dtorCalled;16 ~InlineDtor() {17 switch (dtorCalled % 4) {18 case 0:19 a = cnt++;20 break;21 case 1:22 b = cnt++;23 break;24 case 2:25 c = cnt++;26 break;27 case 3:28 d = cnt++;29 break;30 }31 32 ++dtorCalled;33 }34};35 36int InlineDtor::cnt = 0;37int InlineDtor::dtorCalled = 0;38 39void foo() {40 InlineDtor::cnt = 0;41 InlineDtor::dtorCalled = 0;42 InlineDtor arr[4];43}44 45void testAutoDtor() {46 foo();47 48 clang_analyzer_eval(a == 0); // expected-warning {{TRUE}}49 clang_analyzer_eval(b == 1); // expected-warning {{TRUE}}50 clang_analyzer_eval(c == 2); // expected-warning {{TRUE}}51 clang_analyzer_eval(d == 3); // expected-warning {{TRUE}}52}53 54void testDeleteDtor() {55 InlineDtor::cnt = 10;56 InlineDtor::dtorCalled = 0;57 58 InlineDtor *arr = new InlineDtor[4];59 delete[] arr;60 61 clang_analyzer_eval(a == 10); // expected-warning {{TRUE}}62 clang_analyzer_eval(b == 11); // expected-warning {{TRUE}}63 clang_analyzer_eval(c == 12); // expected-warning {{TRUE}}64 clang_analyzer_eval(d == 13); // expected-warning {{TRUE}}65}66 67struct MemberDtor {68 InlineDtor arr[4];69};70 71void testMemberDtor() {72 InlineDtor::cnt = 5;73 InlineDtor::dtorCalled = 0;74 75 MemberDtor *MD = new MemberDtor{};76 delete MD;77 78 clang_analyzer_eval(a == 5); // expected-warning {{TRUE}}79 clang_analyzer_eval(b == 6); // expected-warning {{TRUE}}80 clang_analyzer_eval(c == 7); // expected-warning {{TRUE}}81 clang_analyzer_eval(d == 8); // expected-warning {{TRUE}}82}83 84struct MultipleMemberDtor85{86 InlineDtor arr[4];87 InlineDtor arr2[4];88};89 90void testMultipleMemberDtor() {91 InlineDtor::cnt = 30;92 InlineDtor::dtorCalled = 0;93 94 MultipleMemberDtor *MD = new MultipleMemberDtor{};95 delete MD;96 97 clang_analyzer_eval(a == 34); // expected-warning {{TRUE}}98 clang_analyzer_eval(b == 35); // expected-warning {{TRUE}}99 clang_analyzer_eval(c == 36); // expected-warning {{TRUE}}100 clang_analyzer_eval(d == 37); // expected-warning {{TRUE}}101}102 103int EvalOrderArr[4];104 105struct EvalOrder106{107 int ctor = 0;108 static int dtorCalled;109 static int ctorCalled;110 111 EvalOrder() { ctor = ctorCalled++; };112 113 ~EvalOrder() { EvalOrderArr[ctor] = dtorCalled++; }114};115 116int EvalOrder::ctorCalled = 0;117int EvalOrder::dtorCalled = 0;118 119void dtorEvaluationOrder() {120 EvalOrder::ctorCalled = 0;121 EvalOrder::dtorCalled = 0;122 123 EvalOrder* eptr = new EvalOrder[4];124 delete[] eptr;125 126 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}127 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}128 129 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}130 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}131 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}132 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}133}134 135struct EmptyDtor {136 ~EmptyDtor(){};137};138 139struct DefaultDtor {140 ~DefaultDtor() = default;141};142 143// This function used to fail on an assertion.144void no_crash() {145 EmptyDtor* eptr = new EmptyDtor[4];146 delete[] eptr;147 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}148 149 DefaultDtor* dptr = new DefaultDtor[4];150 delete[] dptr;151 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}152}153 154// This snippet used to crash.155namespace crash2156{157 template <class _Tp> class unique_ptr {158 typedef _Tp *pointer;159 pointer __ptr_;160 161public:162 unique_ptr(pointer __p) : __ptr_(__p) {}163 ~unique_ptr() { reset(); }164 pointer get() { return __ptr_;}165 void reset() {}166};167 168struct S;169 170S *makeS();171int bar(S *x, S *y);172 173void foo() {174 unique_ptr<S> x(makeS()), y(makeS());175 bar(x.get(), y.get());176}177 178void bar() {179 foo();180 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}181}182 183} // namespace crash2184 185// This snippet used to crash.186namespace crash3187{188struct InlineDtor {189 ~InlineDtor() {}190};191struct MultipleMemberDtor192{193 InlineDtor arr[4];194 InlineDtor arr2[4];195};196 197void foo(){198 auto *arr = new MultipleMemberDtor[4];199 delete[] arr;200 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}201}202} // namespace crash3203 204namespace crash4 {205struct a {206 a *b;207};208struct c {209 a d;210 c();211 ~c() {212 for (a e = d;; e = *e.b)213 ;214 }215};216void f() { 217 c g; 218 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}219}220 221} // namespace crash4222 223namespace crash5 {224namespace std {225template <class _Tp> class unique_ptr {226 _Tp *__ptr_;227public:228 unique_ptr(_Tp *__p) : __ptr_(__p) {}229 ~unique_ptr() {}230};231} // namespace std232 233int SSL_use_certificate(int *arg) {234 std::unique_ptr<int> free_x509(arg);235 {236 if (SSL_use_certificate(arg)) {237 return 0;238 }239 }240 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}241 return 1;242}243 244} // namespace crash5245 246void zeroLength(){247 InlineDtor::dtorCalled = 0;248 249 auto *arr = new InlineDtor[0];250 delete[] arr;251 252 auto *arr2 = new InlineDtor[2][0][2];253 delete[] arr2;254 255 auto *arr3 = new InlineDtor[0][2][2];256 delete[] arr3;257 258 auto *arr4 = new InlineDtor[2][2][0];259 delete[] arr4;260 261 clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}}262}263 264 265void evalOrderPrep() {266 EvalOrderArr[0] = 0;267 EvalOrderArr[1] = 0;268 EvalOrderArr[2] = 0;269 EvalOrderArr[3] = 0;270 271 EvalOrder::ctorCalled = 0;272 EvalOrder::dtorCalled = 0;273}274 275void multidimensionalPrep(){276 EvalOrder::ctorCalled = 0;277 EvalOrder::dtorCalled = 0;278 279 EvalOrder arr[2][2];280}281 282void multidimensional(){283 evalOrderPrep();284 multidimensionalPrep();285 286 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}287 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}288 289 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}290 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}291 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}292 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}293}294 295void multidimensionalHeap() {296 evalOrderPrep();297 298 auto* eptr = new EvalOrder[2][2];299 delete[] eptr;300 301 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}302 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}303 304 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}305 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}306 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}307 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}308}309 310struct MultiWrapper{311 EvalOrder arr[2][2];312};313 314void multidimensionalMember(){315 evalOrderPrep();316 317 auto* mptr = new MultiWrapper;318 delete mptr;319 320 clang_analyzer_eval(EvalOrder::dtorCalled == 4); // expected-warning {{TRUE}}321 clang_analyzer_eval(EvalOrder::dtorCalled == EvalOrder::ctorCalled); // expected-warning {{TRUE}}322 323 clang_analyzer_eval(EvalOrderArr[0] == 3); // expected-warning {{TRUE}}324 clang_analyzer_eval(EvalOrderArr[1] == 2); // expected-warning {{TRUE}}325 clang_analyzer_eval(EvalOrderArr[2] == 1); // expected-warning {{TRUE}}326 clang_analyzer_eval(EvalOrderArr[3] == 0); // expected-warning {{TRUE}}327}328 329void *memset(void *, int, size_t);330void clang_analyzer_dumpElementCount(InlineDtor *);331 332void nonConstantRegionExtent(){333 334 InlineDtor::dtorCalled = 0;335 336 int x = 3;337 memset(&x, 1, sizeof(x));338 339 InlineDtor *arr = new InlineDtor[x];340 clang_analyzer_dumpElementCount(arr); // expected-warning {{conj_$0}}341 delete [] arr;342 343 //FIXME: This should be TRUE but memset also sets this344 // region to a conjured symbol.345 clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}} expected-warning {{FALSE}}346}347 348namespace crash6 {349 350struct NonTrivialItem {351 ~NonTrivialItem();352};353 354struct WeirdVec {355 void clear() {356 delete[] data;357 size = 0;358 }359 NonTrivialItem *data;360 unsigned size;361};362 363void top(int j) {364 WeirdVec *p = new WeirdVec;365 366 p[j].size = 0;367 delete[] p->data; // no-crash368}369 370template <typename T>371T make_unknown() {372 return reinterpret_cast<T>(static_cast<int>(0.404));373}374 375void directUnknownSymbol() {376 delete[] make_unknown<NonTrivialItem*>(); // no-crash377}378 379}380