brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.9 KiB · 1c0ac38 Raw
1242 lines · cpp
1// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\2// RUN:     -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\3// RUN:     -analyzer-config eagerly-assume=false -verify %s\4// RUN:     -std=c++03 -analyzer-config cfg-temporary-dtors=false5 6// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\7// RUN:     -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\8// RUN:     -analyzer-config eagerly-assume=false -verify %s\9// RUN:     -std=c++11 -analyzer-config cfg-temporary-dtors=false10 11// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\12// RUN:     -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\13// RUN:     -analyzer-config eagerly-assume=false -verify %s\14// RUN:     -std=c++11 -analyzer-config cfg-temporary-dtors=true\15// RUN:     -DTEMPORARY_DTORS16 17// RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\18// RUN:     -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\19// RUN:     -analyzer-config eagerly-assume=false -verify %s\20// RUN:     -std=c++17 -analyzer-config cfg-temporary-dtors=true\21// RUN:     -DTEMPORARY_DTORS22 23 24extern bool clang_analyzer_eval(bool);25extern bool clang_analyzer_warnIfReached();26void clang_analyzer_checkInlined(bool);27 28#include "Inputs/system-header-simulator-cxx.h"29 30struct Trivial {31  Trivial(int x) : value(x) {}32  int value;33};34 35struct NonTrivial : public Trivial {36  NonTrivial(int x) : Trivial(x) {}37  ~NonTrivial();38};39 40 41Trivial getTrivial() {42  return Trivial(42); // no-warning43}44 45const Trivial &getTrivialRef() {46  return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}47}48 49 50NonTrivial getNonTrivial() {51  return NonTrivial(42); // no-warning52}53 54const NonTrivial &getNonTrivialRef() {55  return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}56}57 58namespace rdar13265460 {59  struct TrivialSubclass : public Trivial {60    TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}61    int anotherValue;62  };63 64  TrivialSubclass getTrivialSub() {65    TrivialSubclass obj(1);66    obj.value = 42;67    obj.anotherValue = -42;68    return obj;69  }70 71  void testImmediate() {72    TrivialSubclass obj = getTrivialSub();73 74    clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}75    clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}76 77    clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}78    clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}79  }80 81  void testMaterializeTemporaryExpr() {82    const TrivialSubclass &ref = getTrivialSub();83    clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}84 85    const Trivial &baseRef = getTrivialSub();86    clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}87  }88}89 90namespace rdar13281951 {91  struct Derived : public Trivial {92    Derived(int value) : Trivial(value), value2(-value) {}93    int value2;94  };95 96  void test() {97    Derived obj(1);98    obj.value = 42;99    const Trivial * const &pointerRef = &obj;100    clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}101  }102}103 104namespace compound_literals {105  struct POD {106    int x, y;107  };108  struct HasCtor {109    HasCtor(int x, int y) : x(x), y(y) {}110    int x, y;111  };112  struct HasDtor {113    int x, y;114    ~HasDtor();115  };116  struct HasCtorDtor {117    HasCtorDtor(int x, int y) : x(x), y(y) {}118    ~HasCtorDtor();119    int x, y;120  };121 122  void test() {123    clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}124    clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}125 126#if __cplusplus >= 201103L127    clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}128 129    // FIXME: should be TRUE, but we don't inline the constructors of130    // temporaries because we can't model their destructors yet.131    clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}132#endif133  }134}135 136namespace destructors {137  struct Dtor {138    ~Dtor();139  };140  extern bool coin();141  extern bool check(const Dtor &);142 143  void testPR16664andPR18159Crash() {144    // Regression test: we used to assert here when tmp dtors are enabled.145    // PR16664 and PR18159146    if (coin() && (coin() || coin() || check(Dtor()))) {147      Dtor();148    }149  }150 151#ifdef TEMPORARY_DTORS152  struct NoReturnDtor {153    ~NoReturnDtor() __attribute__((noreturn));154  };155 156  void noReturnTemp(int *x) {157    if (! x) NoReturnDtor();158    *x = 47; // no warning159  }160 161  void noReturnInline(int **x) {162    NoReturnDtor();163  }164 165  void callNoReturn() {166    int *x;167    noReturnInline(&x);168    *x = 47; // no warning169  }170 171  extern bool check(const NoReturnDtor &);172 173  void testConsistencyIf(int i) {174    if (i != 5)175      return;176    if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {177      clang_analyzer_eval(true); // no warning, unreachable code178    }179  }180 181  void testConsistencyTernary(int i) {182    (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;183 184    clang_analyzer_eval(true);  // expected-warning{{TRUE}}185 186    if (i != 5)187      return;188 189    (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;190 191    clang_analyzer_eval(true); // no warning, unreachable code192  }193 194  // Regression test: we used to assert here.195  // PR16664 and PR18159196  void testConsistencyNested(int i) {197    extern bool compute(bool);198 199    if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))200      clang_analyzer_eval(true);  // expected-warning{{TRUE}}201 202    if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))203      clang_analyzer_eval(true);  // expected-warning{{TRUE}}204 205    if (i != 5)206      return;207 208    if (compute(i == 5 &&209                (i == 4 || compute(true) ||210                 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||211        i != 4) {212      clang_analyzer_eval(true);  // expected-warning{{TRUE}}213    }214 215    if (compute(i == 5 &&216                (i == 4 || i == 4 ||217                 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||218        i != 4) {219      clang_analyzer_eval(true);  // no warning, unreachable code220    }221  }222 223  // PR16664 and PR18159224  void testConsistencyNestedSimple(bool value) {225    if (value) {226      if (!value || check(NoReturnDtor())) {227        clang_analyzer_eval(true); // no warning, unreachable code228      }229    }230  }231 232  // PR16664 and PR18159233  void testConsistencyNestedComplex(bool value) {234    if (value) {235      if (!value || !value || check(NoReturnDtor())) {236        clang_analyzer_eval(true);  // no warning, unreachable code237      }238    }239  }240 241  // PR16664 and PR18159242  void testConsistencyNestedWarning(bool value) {243    if (value) {244      if (!value || value || check(NoReturnDtor())) {245        clang_analyzer_eval(true); // expected-warning{{TRUE}}246      }247    }248  }249  // PR16664 and PR18159250  void testConsistencyNestedComplexMidBranch(bool value) {251    if (value) {252      if (!value || !value || check(NoReturnDtor()) || value) {253        clang_analyzer_eval(true);  // no warning, unreachable code254      }255    }256  }257 258  // PR16664 and PR18159259  void testConsistencyNestedComplexNestedBranch(bool value) {260    if (value) {261      if (!value || (!value || check(NoReturnDtor()) || value)) {262        clang_analyzer_eval(true);  // no warning, unreachable code263      }264    }265  }266 267  // PR16664 and PR18159268  void testConsistencyNestedVariableModification(bool value) {269    bool other = true;270    if (value) {271      if (!other || !value || (other = false) || check(NoReturnDtor()) ||272          !other) {273        clang_analyzer_eval(true);  // no warning, unreachable code274      }275    }276  }277 278  void testTernaryNoReturnTrueBranch(bool value) {279    if (value) {280      bool b = value && (value ? check(NoReturnDtor()) : true);281      clang_analyzer_eval(true);  // no warning, unreachable code282    }283  }284  void testTernaryNoReturnFalseBranch(bool value) {285    if (value) {286      bool b = !value && !value ? true : check(NoReturnDtor());287      clang_analyzer_eval(true);  // no warning, unreachable code288    }289  }290  void testTernaryIgnoreNoreturnBranch(bool value) {291    if (value) {292      bool b = !value && !value ? check(NoReturnDtor()) : true;293      clang_analyzer_eval(true);  // expected-warning{{TRUE}}294    }295  }296  void testTernaryTrueBranchReached(bool value) {297    value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}}298            check(NoReturnDtor());299  }300  void testTernaryFalseBranchReached(bool value) {301    value ? check(NoReturnDtor()) :302            clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}303  }304 305  void testLoop() {306    for (int i = 0; i < 10; ++i) {307      if (i < 3 && (i >= 2 || check(NoReturnDtor()))) {308        clang_analyzer_eval(true);  // no warning, unreachable code309      }310    }311  }312 313  bool testRecursiveFrames(bool isInner) {314    if (isInner ||315        (clang_analyzer_warnIfReached(), false) || // expected-warning{{REACHABLE}}316        check(NoReturnDtor()) ||317        testRecursiveFrames(true)) {318      clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}319    }320  }321  void testRecursiveFramesStart() { testRecursiveFrames(false); }322 323  void testLambdas() {324    []() { check(NoReturnDtor()); } != nullptr || check(Dtor());325  }326 327  void testGnuExpressionStatements(int v) {328    ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23;329    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}330 331    ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23;332    clang_analyzer_warnIfReached();  // no warning, unreachable code333  }334 335  void testGnuExpressionStatementsDestructionPoint(int v) {336    // In normal context, the temporary destructor runs at the end of the full337    // statement, thus the last statement is reached.338    (++v, check(NoReturnDtor()), v == 42),339        clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}340 341    // GNU expression statements execute temporary destructors within the342    // blocks, thus the last statement is not reached.343    ({ ++v; check(NoReturnDtor()); v == 42; }),344        clang_analyzer_warnIfReached();  // no warning, unreachable code345  }346 347  void testMultipleTemporaries(bool value) {348    if (value) {349      // FIXME: Find a way to verify construction order.350      // ~Dtor should run before ~NoReturnDtor() because construction order is351      // guaranteed by comma operator.352      if (!value || check((NoReturnDtor(), Dtor())) || value) {353        clang_analyzer_eval(true);  // no warning, unreachable code354      }355    }356  }357 358  void testBinaryOperatorShortcut(bool value) {359    if (value) {360      if (false && false && check(NoReturnDtor()) && true) {361        clang_analyzer_eval(true);362      }363    }364  }365 366  void testIfAtEndOfLoop() {367    int y = 0;368    while (true) {369      if (y > 0) {370        clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}371      }372      ++y;373      // Test that the CFG gets hooked up correctly when temporary destructors374      // are handled after a statically known branch condition.375      if (true) (void)0; else (void)check(NoReturnDtor());376    }377  }378 379  void testTernaryAtEndOfLoop() {380    int y = 0;381    while (true) {382      if (y > 0) {383        clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}384      }385      ++y;386      // Test that the CFG gets hooked up correctly when temporary destructors387      // are handled after a statically known branch condition.388      true ? (void)0 : (void)check(NoReturnDtor());389    }390  }391 392  void testNoReturnInComplexCondition() {393    check(Dtor()) &&394        (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());395    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}396  }397 398  void testSequencingOfConditionalTempDtors(bool b) {399    b || (check(Dtor()), check(NoReturnDtor()));400    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}401  }402 403  void testSequencingOfConditionalTempDtors2(bool b) {404    (b || check(Dtor())), check(NoReturnDtor());405    clang_analyzer_warnIfReached();  // no warning, unreachable code406  }407 408  void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) {409    b || (check(Dtor()) + check(NoReturnDtor()));410    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}411  }412 413  void f(Dtor d = Dtor());414  void testDefaultParameters() {415    f();416  }417 418  struct DefaultParam {419    DefaultParam(int, const Dtor& d = Dtor());420    ~DefaultParam();421  };422  void testDefaultParamConstructorsInLoops() {423    while (true) {424      // FIXME: This exact pattern triggers the temporary cleanup logic425      // to fail when adding a 'clean' state.426      DefaultParam(42);427      DefaultParam(42);428    }429  }430  void testDefaultParamConstructorsInTernariesInLoops(bool value) {431    while (true) {432      // FIXME: This exact pattern triggers the temporary cleanup logic433      // to visit the bind-temporary logic with a state that already has that434      // temporary marked as executed.435      value ? DefaultParam(42) : DefaultParam(42);436    }437  }438#else // !TEMPORARY_DTORS439 440// Test for fallback logic that conservatively stops exploration after441// executing a temporary constructor for a class with a no-return destructor442// when temporary destructors are not enabled in the CFG.443 444  struct CtorWithNoReturnDtor {445    CtorWithNoReturnDtor() = default;446 447    CtorWithNoReturnDtor(int x) {448      clang_analyzer_checkInlined(false); // no-warning449    }450 451    ~CtorWithNoReturnDtor() __attribute__((noreturn));452  };453 454  void testDefaultContructorWithNoReturnDtor() {455    CtorWithNoReturnDtor();456    clang_analyzer_warnIfReached();  // no-warning457  }458 459  void testLifeExtensionWithNoReturnDtor() {460    const CtorWithNoReturnDtor &c = CtorWithNoReturnDtor();461 462    // This represents an (expected) loss of coverage, since the destructor463    // of the lifetime-exended temporary is executed at the end of464    // scope.465    clang_analyzer_warnIfReached();  // no-warning466  }467 468#if __cplusplus >= 201103L469  struct CtorWithNoReturnDtor2 {470    CtorWithNoReturnDtor2() = default;471 472    CtorWithNoReturnDtor2(int x) {473      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}474    }475 476    ~CtorWithNoReturnDtor2() __attribute__((noreturn));477  };478  CtorWithNoReturnDtor2 returnNoReturnDtor() {479    return {1}; // no-crash480  }481#endif482 483#endif // TEMPORARY_DTORS484}485 486namespace default_param_elided_destructors {487struct a {488  ~a();489};490struct F {491  a d;492  F(char *, a = a());493};494void g() {495  char h[1];496  for (int i = 0;;)497    F j(i ? j : h);498}499} // namespace default_param_elided_destructors500 501void testStaticMaterializeTemporaryExpr() {502  static const Trivial &ref = getTrivial();503  clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}504 505  static const Trivial &directRef = Trivial(42);506  clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}507 508#if __has_feature(cxx_thread_local)509  thread_local static const Trivial &threadRef = getTrivial();510  clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}511 512  thread_local static const Trivial &threadDirectRef = Trivial(42);513  clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}514#endif515}516 517namespace PR16629 {518  struct A {519    explicit A(int* p_) : p(p_) {}520    int* p;521  };522 523  extern void escape(const A*[]);524  extern void check(int);525 526  void callEscape(const A& a) {527    const A* args[] = { &a };528    escape(args);529  }530 531  void testNoWarning() {532    int x;533    callEscape(A(&x));534    check(x); // Analyzer used to give a "x is uninitialized warning" here535  }536 537  void set(const A*a[]) {538    *a[0]->p = 47;539  }540 541  void callSet(const A& a) {542    const A* args[] = { &a };543    set(args);544  }545 546  void testConsistency() {547    int x;548    callSet(A(&x));549    clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}550  }551}552 553namespace PR32088 {554  void testReturnFromStmtExprInitializer() {555    // We shouldn't try to destroy the object pointed to by `obj' upon return.556    const NonTrivial &obj = ({557      return; // no-crash558      NonTrivial(42);559    });560  }561}562 563namespace CopyToTemporaryCorrectly {564class Super {565public:566  void m() {567    mImpl();568  }569  virtual void mImpl() = 0;570};571class Sub : public Super {572public:573  Sub(const int &p) : j(p) {}574  virtual void mImpl() override {575    // Used to be undefined pointer dereference because we didn't copy576    // the subclass data (j) to the temporary object properly.577    (void)(j + 1); // no-warning578    if (j != 22) {579      clang_analyzer_warnIfReached(); // no-warning580    }581  }582  const int &j;583};584void run() {585  int i = 22;586  Sub(i).m();587}588}589 590namespace test_return_temporary {591class C {592  int x, y;593 594public:595  C(int x, int y) : x(x), y(y) {}596  int getX() const { return x; }597  int getY() const { return y; }598  ~C() {}599};600 601class D: public C {602public:603  D() : C(1, 2) {}604  D(const D &d): C(d.getX(), d.getY()) {}605};606 607C returnTemporaryWithVariable() { C c(1, 2); return c; }608C returnTemporaryWithAnotherFunctionWithVariable() {609  return returnTemporaryWithVariable();610}611C returnTemporaryWithCopyConstructionWithVariable() {612  return C(returnTemporaryWithVariable());613}614 615C returnTemporaryWithConstruction() { return C(1, 2); }616C returnTemporaryWithAnotherFunctionWithConstruction() {617  return returnTemporaryWithConstruction();618}619C returnTemporaryWithCopyConstructionWithConstruction() {620  return C(returnTemporaryWithConstruction());621}622 623D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }624D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {625  return returnTemporaryWithVariableAndNonTrivialCopy();626}627D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {628  return D(returnTemporaryWithVariableAndNonTrivialCopy());629}630 631#if __cplusplus >= 201103L632C returnTemporaryWithBraces() { return {1, 2}; }633C returnTemporaryWithAnotherFunctionWithBraces() {634  return returnTemporaryWithBraces();635}636C returnTemporaryWithCopyConstructionWithBraces() {637  return C(returnTemporaryWithBraces());638}639#endif // C++11640 641void test() {642  C c1 = returnTemporaryWithVariable();643  clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}}644  clang_analyzer_eval(c1.getY() == 2); // expected-warning{{TRUE}}645 646  C c2 = returnTemporaryWithAnotherFunctionWithVariable();647  clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}648  clang_analyzer_eval(c2.getY() == 2); // expected-warning{{TRUE}}649 650  C c3 = returnTemporaryWithCopyConstructionWithVariable();651  clang_analyzer_eval(c3.getX() == 1); // expected-warning{{TRUE}}652  clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}653 654  C c4 = returnTemporaryWithConstruction();655  clang_analyzer_eval(c4.getX() == 1); // expected-warning{{TRUE}}656  clang_analyzer_eval(c4.getY() == 2); // expected-warning{{TRUE}}657 658  C c5 = returnTemporaryWithAnotherFunctionWithConstruction();659  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}660  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}661 662  C c6 = returnTemporaryWithCopyConstructionWithConstruction();663  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}664  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}665 666#if __cplusplus >= 201103L667 668  C c7 = returnTemporaryWithBraces();669  clang_analyzer_eval(c7.getX() == 1); // expected-warning{{TRUE}}670  clang_analyzer_eval(c7.getY() == 2); // expected-warning{{TRUE}}671 672  C c8 = returnTemporaryWithAnotherFunctionWithBraces();673  clang_analyzer_eval(c8.getX() == 1); // expected-warning{{TRUE}}674  clang_analyzer_eval(c8.getY() == 2); // expected-warning{{TRUE}}675 676  C c9 = returnTemporaryWithCopyConstructionWithBraces();677  clang_analyzer_eval(c9.getX() == 1); // expected-warning{{TRUE}}678  clang_analyzer_eval(c9.getY() == 2); // expected-warning{{TRUE}}679 680#endif // C++11681 682  D d1 = returnTemporaryWithVariableAndNonTrivialCopy();683  clang_analyzer_eval(d1.getX() == 1); // expected-warning{{TRUE}}684  clang_analyzer_eval(d1.getY() == 2); // expected-warning{{TRUE}}685 686  D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy();687  clang_analyzer_eval(d2.getX() == 1); // expected-warning{{TRUE}}688  clang_analyzer_eval(d2.getY() == 2); // expected-warning{{TRUE}}689 690  D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();691  clang_analyzer_eval(d3.getX() == 1); // expected-warning{{TRUE}}692  clang_analyzer_eval(d3.getY() == 2); // expected-warning{{TRUE}}693}694} // namespace test_return_temporary695 696 697namespace test_temporary_object_expr_without_dtor {698class C {699  int x;700public:701  C(int x) : x(x) {}702  int getX() const { return x; }703};704 705void test() {706  clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}707};708}709 710namespace test_temporary_object_expr_with_dtor {711class C {712  int x;713 714public:715  C(int x) : x(x) {}716  ~C() {}717  int getX() const { return x; }718};719 720void test(int coin) {721  clang_analyzer_eval(C(3).getX() == 3);722#ifdef TEMPORARY_DTORS723  // expected-warning@-2{{TRUE}}724#else725  // expected-warning@-4{{UNKNOWN}}726#endif727 728  const C &c1 = coin ? C(1) : C(2);729  if (coin) {730    clang_analyzer_eval(c1.getX() == 1);731#ifdef TEMPORARY_DTORS732  // expected-warning@-2{{TRUE}}733#else734  // expected-warning@-4{{UNKNOWN}}735#endif736  } else {737    clang_analyzer_eval(c1.getX() == 2);738#ifdef TEMPORARY_DTORS739  // expected-warning@-2{{TRUE}}740#else741  // expected-warning@-4{{UNKNOWN}}742#endif743  }744 745  C c2 = coin ? C(1) : C(2);746  if (coin) {747    clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}748  } else {749    clang_analyzer_eval(c2.getX() == 2); // expected-warning{{TRUE}}750  }751}752 753} // namespace test_temporary_object_expr754 755namespace test_match_constructors_and_destructors {756class C {757public:758  int &x, &y;759  C(int &_x, int &_y) : x(_x), y(_y) { ++x; }760  C(const C &c): x(c.x), y(c.y) { ++x; }761  ~C() { ++y; }762};763 764void test_simple_temporary() {765  int x = 0, y = 0;766  {767    const C &c = C(x, y);768  }769  // One constructor and one destructor.770  clang_analyzer_eval(x == 1);771  clang_analyzer_eval(y == 1);772#ifdef TEMPORARY_DTORS773  // expected-warning@-3{{TRUE}}774  // expected-warning@-3{{TRUE}}775#else776  // expected-warning@-6{{UNKNOWN}}777  // expected-warning@-6{{UNKNOWN}}778#endif779}780 781void test_simple_temporary_with_copy() {782  int x = 0, y = 0;783  {784    C c = C(x, y);785  }786  // Only one constructor directly into the variable, and one destructor.787  clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}788  clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}789}790 791void test_ternary_temporary(int coin) {792  int x = 0, y = 0, z = 0, w = 0;793  {794    const C &c = coin ? C(x, y) : C(z, w);795  }796  // Only one constructor on every branch, and one automatic destructor.797  if (coin) {798    clang_analyzer_eval(x == 1);799    clang_analyzer_eval(y == 1);800#ifdef TEMPORARY_DTORS801    // expected-warning@-3{{TRUE}}802    // expected-warning@-3{{TRUE}}803#else804    // expected-warning@-6{{UNKNOWN}}805    // expected-warning@-6{{UNKNOWN}}806#endif807    clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}808    clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}809 810  } else {811    clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}812    clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}813    clang_analyzer_eval(z == 1);814    clang_analyzer_eval(w == 1);815#ifdef TEMPORARY_DTORS816    // expected-warning@-3{{TRUE}}817    // expected-warning@-3{{TRUE}}818#else819    // expected-warning@-6{{UNKNOWN}}820    // expected-warning@-6{{UNKNOWN}}821#endif822  }823}824 825void test_ternary_temporary_with_copy(int coin) {826  int x = 0, y = 0, z = 0, w = 0;827  {828    C c = coin ? C(x, y) : C(z, w);829  }830  // On each branch the variable is constructed directly.831  if (coin) {832    clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}833    clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}834    clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}835    clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}836 837  } else {838    clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}839    clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}840    clang_analyzer_eval(z == 1); // expected-warning{{TRUE}}841    clang_analyzer_eval(w == 1); // expected-warning{{TRUE}}842  }843}844} // namespace test_match_constructors_and_destructors845 846namespace destructors_for_return_values {847 848class C {849public:850  ~C() {851    1 / 0; // expected-warning{{Division by zero}}852  }853};854 855C make();856 857void testFloatingCall() {858  make();859  // Should have divided by zero in the destructor.860  clang_analyzer_warnIfReached();861#ifndef TEMPORARY_DTORS862    // expected-warning@-2{{REACHABLE}}863#endif864}865 866void testLifetimeExtendedCall() {867  {868    const C &c = make();869    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}870  }871  // Should have divided by zero in the destructor.872  clang_analyzer_warnIfReached(); // no-warning873}874 875void testCopiedCall() {876  {877    C c = make();878    // Should have elided the constructor/destructor for the temporary879    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}880  }881  // Should have divided by zero in the destructor.882  clang_analyzer_warnIfReached(); // no-warning883}884} // namespace destructors_for_return_values885 886namespace dont_forget_destructor_around_logical_op {887int glob;888 889class C {890public:891  ~C() {892    glob = 1;893    clang_analyzer_checkInlined(true);894#ifdef TEMPORARY_DTORS895    // expected-warning@-2{{TRUE}}896#endif897  }898};899 900C get();901 902bool is(C);903 904 905void test(int coin) {906  // Here temporaries are being cleaned up after && is evaluated. There are two907  // temporaries: the return value of get() and the elidable copy constructor908  // of that return value into is(). According to the CFG, we need to cleanup909  // both of them depending on whether the temporary corresponding to the910  // return value of get() was initialized. However, we didn't track911  // temporaries returned from functions, so we took the wrong branch.912  coin && is(get()); // no-crash913  if (coin) {914    clang_analyzer_eval(glob);915#ifdef TEMPORARY_DTORS916    // expected-warning@-2{{TRUE}}917#else918    // expected-warning@-4{{UNKNOWN}}919#endif920  } else {921    // The destructor is not called on this branch.922    clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}923  }924}925} // namespace dont_forget_destructor_around_logical_op926 927#if __cplusplus >= 201103L928namespace temporary_list_crash {929class C {930public:931  C() {}932  ~C() {}933};934 935void test() {936  std::initializer_list<C>{C(), C()}; // no-crash937}938} // namespace temporary_list_crash939#endif // C++11940 941namespace implicit_constructor_conversion {942struct S {943  int x;944  S(int x) : x(x) {}945  ~S() {}946};947 948class C {949  int x;950 951public:952  C(const S &s) : x(s.x) {}953  ~C() {}954  int getX() const { return x; }955};956 957void test() {958  const C &c1 = S(10);959  clang_analyzer_eval(c1.getX() == 10);960#ifdef TEMPORARY_DTORS961  // expected-warning@-2{{TRUE}}962#else963  // expected-warning@-4{{UNKNOWN}}964#endif965 966  S s = 20;967  clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}}968 969  C c2 = s;970  clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}}971}972} // end namespace implicit_constructor_conversion973 974namespace pass_references_through {975class C {976public:977  ~C() {}978};979 980const C &foo1();981C &&foo2();982 983// In these examples the foo() expression has record type, not reference type.984// Don't try to figure out how to perform construction of the record here.985const C &bar1() { return foo1(); } // no-crash986C &&bar2() { return foo2(); } // no-crash987} // end namespace pass_references_through988 989 990namespace arguments {991int glob;992 993struct S {994  int x;995  S(int x): x(x) {}996  S(const S &s) : x(s.x) {}997  ~S() {}998 999  S &operator+(S s) {1000    glob = s.x;1001    x += s.x;1002    return *this;1003  }1004};1005 1006class C {1007public:1008  virtual void bar3(S s) {}1009};1010 1011class D: public C {1012public:1013  D() {}1014  virtual void bar3(S s) override { glob = s.x; }1015};1016 1017void bar1(S s) {1018  glob = s.x;1019}1020 1021// Record-typed calls are a different CFGStmt, let's see if we handle that1022// as well.1023S bar2(S s) {1024  glob = s.x;1025  return S(3);1026}1027 1028void bar5(int, ...);1029 1030void foo(void (*bar4)(S)) {1031  bar1(S(1));1032  clang_analyzer_eval(glob == 1);1033#ifdef TEMPORARY_DTORS1034  // expected-warning@-2{{TRUE}}1035#else1036  // expected-warning@-4{{UNKNOWN}}1037#endif1038 1039  bar2(S(2));1040  clang_analyzer_eval(glob == 2);1041#ifdef TEMPORARY_DTORS1042  // expected-warning@-2{{TRUE}}1043#else1044  // expected-warning@-4{{UNKNOWN}}1045#endif1046 1047  C *c = new D();1048  c->bar3(S(3));1049  // FIXME: Should be TRUE.1050  clang_analyzer_eval(glob == 3); // expected-warning{{UNKNOWN}}1051  delete c;1052 1053  // What if we've no idea what we're calling?1054  bar4(S(4)); // no-crash1055 1056  S(5) + S(6);1057  clang_analyzer_eval(glob == 6);1058#ifdef TEMPORARY_DTORS1059  // expected-warning@-2{{TRUE}}1060#else1061  // expected-warning@-4{{UNKNOWN}}1062#endif1063 1064  // Variadic functions. This will __builtin_trap() because you cannot pass1065  // an object as a variadic argument.1066  bar5(7, S(7)); // no-crash1067  clang_analyzer_warnIfReached(); // no-warning1068}1069} // namespace arguments1070 1071namespace ctor_argument {1072// Stripped down unique_ptr<int>1073struct IntPtr {1074  IntPtr(): i(new int) {}1075  IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }1076  ~IntPtr() { delete i; }1077 1078  int *i;1079};1080 1081struct Foo {1082  Foo(IntPtr);1083  void bar();1084 1085  IntPtr i;1086};1087 1088void bar() {1089  IntPtr ptr;1090  int *i = ptr.i;1091  Foo f(static_cast<IntPtr &&>(ptr));1092  *i = 99; // no-warning1093}1094} // namespace ctor_argument1095 1096namespace operator_implicit_argument {1097struct S {1098  bool x;1099  S(bool x): x(x) {}1100  operator bool() const { return x; }1101};1102 1103void foo() {1104  if (S(false)) {1105    clang_analyzer_warnIfReached(); // no-warning1106  }1107  if (S(true)) {1108    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}1109  }1110}1111} // namespace operator_implicit_argument1112 1113 1114#if __cplusplus >= 201103L1115namespace argument_lazy_bindings {1116int glob;1117 1118struct S {1119  int x, y, z;1120};1121 1122struct T {1123  S s;1124  int w;1125  T(int w): s{5, 6, 7}, w(w) {}1126};1127 1128void foo(T t) {1129  t.s = {1, 2, 3};1130  glob = t.w;1131}1132 1133void bar() {1134  foo(T(4));1135  clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}1136}1137} // namespace argument_lazy_bindings1138#endif1139 1140namespace operator_argument_cleanup {1141struct S {1142  S();1143};1144 1145class C {1146public:1147  void operator=(S);1148};1149 1150void foo() {1151  C c;1152  c = S(); // no-crash1153}1154} // namespace operator_argument_cleanup1155 1156namespace argument_decl_lookup {1157class C {};1158int foo(C);1159int bar(C c) { foo(c); }1160int foo(C c) {}1161} // namespace argument_decl_lookup1162 1163namespace argument_virtual_decl_lookup {1164class C {};1165 1166struct T  {1167  virtual void foo(C);1168};1169 1170void run() {1171  T *t;1172  t->foo(C()); // no-crash // expected-warning{{Called C++ object pointer is uninitialized}}1173}1174 1175// This is after run() because the test is about picking the correct decl1176// for the parameter region, which should belong to the correct function decl,1177// and the non-definition decl should be found by direct lookup.1178void T::foo(C) {}1179} // namespace argument_virtual_decl_lookup1180 1181namespace union_indirect_field_crash {1182union U {1183  struct {1184    int x;1185  };1186};1187 1188template <typename T> class C {1189public:1190  void foo() const {1191    (void)(true ? U().x : 0);1192  }1193};1194 1195void test() {1196  C<int> c;1197  c.foo();1198}1199} // namespace union_indirect_field_crash1200 1201namespace return_from_top_frame {1202struct S {1203  int *p;1204  S() { p = new int; }1205  S(S &&s) : p(s.p) { s.p = 0; }1206  ~S();  // Presumably releases 'p'.1207};1208 1209S foo() {1210  S s;1211  return s;1212}1213 1214S bar1() {1215  return foo(); // no-warning1216}1217 1218S bar2() {1219  return S();1220}1221 1222S bar3(int coin) {1223  return coin ? S() : foo(); // no-warning1224}1225} // namespace return_from_top_frame1226 1227#if __cplusplus >= 201103L1228namespace arguments_of_operators {1229struct S {1230  S() {}1231  S(const S &) {}1232};1233 1234void test() {1235  int x = 0;1236  auto foo = [](S s, int &y) { y = 1; };1237  foo(S(), x);1238  clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}1239}1240} // namespace arguments_of_operators1241#endif // __cplusplus >= 201103L1242