temporaries.cpp revision a4de17562d13d7a8188108243c4cfbd52f33229a
16376703eb3325fe41233aed234fde81164af42a1Jordan Rose// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
299b3cc6ec4fbcd887b632dcb7147ef472d83fc37Pavel Labath// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
3176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s -std=c++11
473212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
59f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Roseextern bool clang_analyzer_eval(bool);
6176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesextern bool clang_analyzer_warnIfReached();
79f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose
873212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rosestruct Trivial {
973212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose  Trivial(int x) : value(x) {}
1073212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose  int value;
1173212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose};
1273212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
1373212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rosestruct NonTrivial : public Trivial {
1473212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose  NonTrivial(int x) : Trivial(x) {}
1573212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose  ~NonTrivial();
1673212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose};
1773212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
1873212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
1973212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan RoseTrivial getTrivial() {
2073212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose  return Trivial(42); // no-warning
2173212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose}
2273212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
2373212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Roseconst Trivial &getTrivialRef() {
24a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose  return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
2573212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose}
2673212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
2773212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
2873212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan RoseNonTrivial getNonTrivial() {
2973212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose  return NonTrivial(42); // no-warning
3073212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose}
3173212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
3273212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Roseconst NonTrivial &getNonTrivialRef() {
33a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose  return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
3473212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose}
3573212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose
369f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rosenamespace rdar13265460 {
379f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose  struct TrivialSubclass : public Trivial {
389f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
399f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    int anotherValue;
409f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose  };
419f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose
429f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose  TrivialSubclass getTrivialSub() {
439f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    TrivialSubclass obj(1);
449f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    obj.value = 42;
459f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    obj.anotherValue = -42;
469f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    return obj;
479f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose  }
489f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose
495e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose  void testImmediate() {
509f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    TrivialSubclass obj = getTrivialSub();
519f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose
529f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
539f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
549f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose
559f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
569f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose    clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
579f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose  }
585e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose
595e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose  void testMaterializeTemporaryExpr() {
605e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose    const TrivialSubclass &ref = getTrivialSub();
615e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose    clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
625e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose
635e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose    const Trivial &baseRef = getTrivialSub();
645e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose    clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
655e5440ba9c135f523f72e7e7c5da59d390d697c5Jordan Rose  }
669f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose}
679f1d541ef1aca8f953e5bb4e7177969f0a2062d5Jordan Rose
68eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rosenamespace rdar13281951 {
69eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose  struct Derived : public Trivial {
70eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose    Derived(int value) : Trivial(value), value2(-value) {}
71eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose    int value2;
72eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose  };
73eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose
74eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose  void test() {
75eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose    Derived obj(1);
76eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose    obj.value = 42;
77eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose    const Trivial * const &pointerRef = &obj;
78eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose    clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}
79eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose  }
80eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose}
81eafb5c694cc5d165149fcb9453bc9355fb0d44a5Jordan Rose
826376703eb3325fe41233aed234fde81164af42a1Jordan Rosenamespace compound_literals {
836376703eb3325fe41233aed234fde81164af42a1Jordan Rose  struct POD {
846376703eb3325fe41233aed234fde81164af42a1Jordan Rose    int x, y;
856376703eb3325fe41233aed234fde81164af42a1Jordan Rose  };
866376703eb3325fe41233aed234fde81164af42a1Jordan Rose  struct HasCtor {
876376703eb3325fe41233aed234fde81164af42a1Jordan Rose    HasCtor(int x, int y) : x(x), y(y) {}
886376703eb3325fe41233aed234fde81164af42a1Jordan Rose    int x, y;
896376703eb3325fe41233aed234fde81164af42a1Jordan Rose  };
906376703eb3325fe41233aed234fde81164af42a1Jordan Rose  struct HasDtor {
916376703eb3325fe41233aed234fde81164af42a1Jordan Rose    int x, y;
926376703eb3325fe41233aed234fde81164af42a1Jordan Rose    ~HasDtor();
936376703eb3325fe41233aed234fde81164af42a1Jordan Rose  };
946376703eb3325fe41233aed234fde81164af42a1Jordan Rose  struct HasCtorDtor {
956376703eb3325fe41233aed234fde81164af42a1Jordan Rose    HasCtorDtor(int x, int y) : x(x), y(y) {}
966376703eb3325fe41233aed234fde81164af42a1Jordan Rose    ~HasCtorDtor();
976376703eb3325fe41233aed234fde81164af42a1Jordan Rose    int x, y;
986376703eb3325fe41233aed234fde81164af42a1Jordan Rose  };
996376703eb3325fe41233aed234fde81164af42a1Jordan Rose
1006376703eb3325fe41233aed234fde81164af42a1Jordan Rose  void test() {
1016376703eb3325fe41233aed234fde81164af42a1Jordan Rose    clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
1026376703eb3325fe41233aed234fde81164af42a1Jordan Rose    clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
1036376703eb3325fe41233aed234fde81164af42a1Jordan Rose
1046376703eb3325fe41233aed234fde81164af42a1Jordan Rose#if __cplusplus >= 201103L
1056376703eb3325fe41233aed234fde81164af42a1Jordan Rose    clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
1066376703eb3325fe41233aed234fde81164af42a1Jordan Rose
1076376703eb3325fe41233aed234fde81164af42a1Jordan Rose    // FIXME: should be TRUE, but we don't inline the constructors of
1086376703eb3325fe41233aed234fde81164af42a1Jordan Rose    // temporaries because we can't model their destructors yet.
1096376703eb3325fe41233aed234fde81164af42a1Jordan Rose    clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
1106376703eb3325fe41233aed234fde81164af42a1Jordan Rose#endif
1116376703eb3325fe41233aed234fde81164af42a1Jordan Rose  }
1126376703eb3325fe41233aed234fde81164af42a1Jordan Rose}
1136376703eb3325fe41233aed234fde81164af42a1Jordan Rose
114062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rosenamespace destructors {
115176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  struct Dtor {
116176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ~Dtor();
117176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  };
118176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  extern bool coin();
119176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  extern bool check(const Dtor &);
120062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose
121176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testPR16664andPR18159Crash() {
1226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Regression test: we used to assert here when tmp dtors are enabled.
123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // PR16664 and PR18159
124062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose    if (coin() && (coin() || coin() || check(Dtor()))) {
125062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose      Dtor();
126062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose    }
127062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose  }
128062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose
12995ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath#ifdef TEMPORARY_DTORS
13095ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  struct NoReturnDtor {
13195ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    ~NoReturnDtor() __attribute__((noreturn));
13295ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  };
13395ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
13495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  void noReturnTemp(int *x) {
13595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    if (! x) NoReturnDtor();
13695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    *x = 47; // no warning
13795ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  }
13895ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
13995ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  void noReturnInline(int **x) {
14095ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    NoReturnDtor();
14195ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  }
14295ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
14395ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  void callNoReturn() {
14495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    int *x;
14595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    noReturnInline(&x);
14695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    *x = 47; // no warning
14795ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  }
14895ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
14995ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  extern bool check(const NoReturnDtor &);
15095ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
15195ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  void testConsistencyIf(int i) {
152062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose    if (i != 5)
153062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose      return;
154062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose    if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
15595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath      clang_analyzer_eval(true); // no warning, unreachable code
15695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    }
15795ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  }
15895ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
15995ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  void testConsistencyTernary(int i) {
16095ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
16195ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
16295ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    clang_analyzer_eval(true);  // expected-warning{{TRUE}}
16395ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
16495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    if (i != 5)
16595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath      return;
16695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
16795ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
16895ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
16995ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    clang_analyzer_eval(true); // no warning, unreachable code
17095ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  }
17195ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
1726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Regression test: we used to assert here.
173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // PR16664 and PR18159
17495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath  void testConsistencyNested(int i) {
17595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    extern bool compute(bool);
1766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
177dd9e9cec6f863afa15dd91b34fbf15c66c678c02Bill Wendling    if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
1786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      clang_analyzer_eval(true);  // expected-warning{{TRUE}}
1796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
18095ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
1816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      clang_analyzer_eval(true);  // expected-warning{{TRUE}}
18295ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
18395ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    if (i != 5)
18495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath      return;
18595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
18695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    if (compute(i == 5 &&
18795ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath                (i == 4 || compute(true) ||
18895ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath                 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
18995ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath        i != 4) {
1906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      clang_analyzer_eval(true);  // expected-warning{{TRUE}}
191062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose    }
19295ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath
19395ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    if (compute(i == 5 &&
19495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath                (i == 4 || i == 4 ||
19595ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath                 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
19695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath        i != 4) {
197176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      clang_analyzer_eval(true);  // no warning, unreachable code
19895ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath    }
1996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // PR16664 and PR18159
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void testConsistencyNestedSimple(bool value) {
203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (value) {
204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!value || check(NoReturnDtor())) {
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        clang_analyzer_eval(true); // no warning, unreachable code
206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // PR16664 and PR18159
211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void testConsistencyNestedComplex(bool value) {
212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (value) {
213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!value || !value || check(NoReturnDtor())) {
214176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_eval(true);  // no warning, unreachable code
215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // PR16664 and PR18159
220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void testConsistencyNestedWarning(bool value) {
221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (value) {
222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!value || value || check(NoReturnDtor())) {
223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        clang_analyzer_eval(true); // expected-warning{{TRUE}}
224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // PR16664 and PR18159
228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testConsistencyNestedComplexMidBranch(bool value) {
229176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!value || !value || check(NoReturnDtor()) || value) {
231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_eval(true);  // no warning, unreachable code
232176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
233176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
234176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
235176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
236176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // PR16664 and PR18159
237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testConsistencyNestedComplexNestedBranch(bool value) {
238176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
239176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!value || (!value || check(NoReturnDtor()) || value)) {
240176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_eval(true);  // no warning, unreachable code
241176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
245176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // PR16664 and PR18159
246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testConsistencyNestedVariableModification(bool value) {
247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    bool other = true;
248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
249176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!other || !value || (other = false) || check(NoReturnDtor()) ||
250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          !other) {
251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_eval(true);  // no warning, unreachable code
252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
253176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
254176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
255176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
256176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testTernaryNoReturnTrueBranch(bool value) {
257176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      bool b = value && (value ? check(NoReturnDtor()) : true);
259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      clang_analyzer_eval(true);  // no warning, unreachable code
260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
262176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testTernaryNoReturnFalseBranch(bool value) {
263176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      bool b = !value && !value ? true : check(NoReturnDtor());
265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      clang_analyzer_eval(true);  // no warning, unreachable code
266176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
268176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testTernaryIgnoreNoreturnBranch(bool value) {
269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      bool b = !value && !value ? check(NoReturnDtor()) : true;
271176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      clang_analyzer_eval(true);  // expected-warning{{TRUE}}
272176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testTernaryTrueBranchReached(bool value) {
275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}}
276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines            check(NoReturnDtor());
277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testTernaryFalseBranchReached(bool value) {
279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    value ? check(NoReturnDtor()) :
280176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines            clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
281176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
283176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testLoop() {
284176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    for (int i = 0; i < 10; ++i) {
285176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (i < 3 && (i >= 2 || check(NoReturnDtor()))) {
286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_eval(true);  // no warning, unreachable code
287176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
288176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
289176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
290176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
291176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  bool testRecursiveFrames(bool isInner) {
292176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (isInner ||
293176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        (clang_analyzer_warnIfReached(), false) || // expected-warning{{REACHABLE}}
294176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        check(NoReturnDtor()) ||
295176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        testRecursiveFrames(true)) {
296176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
297176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
298176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
299176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testRecursiveFramesStart() { testRecursiveFrames(false); }
300176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
301176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testLambdas() {
302a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    []() { check(NoReturnDtor()); } != nullptr || check(Dtor());
303176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
304176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
305176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testGnuExpressionStatements(int v) {
306176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23;
307176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
308176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
309176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23;
310176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    clang_analyzer_warnIfReached();  // no warning, unreachable code
311176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
312176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
313176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testGnuExpressionStatementsDestructionPoint(int v) {
314176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // In normal context, the temporary destructor runs at the end of the full
315176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // statement, thus the last statement is reached.
316176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    (++v, check(NoReturnDtor()), v == 42),
317176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
318176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
319176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // GNU expression statements execute temporary destructors within the
320176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // blocks, thus the last statement is not reached.
321176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ({ ++v; check(NoReturnDtor()); v == 42; }),
322176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_warnIfReached();  // no warning, unreachable code
323176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
324176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
325176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testMultipleTemporaries(bool value) {
326176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (value) {
327176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // FIXME: Find a way to verify construction order.
328176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // ~Dtor should run before ~NoReturnDtor() because construction order is
329176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // guaranteed by comma operator.
330176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!value || check((NoReturnDtor(), Dtor())) || value) {
331176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_eval(true);  // no warning, unreachable code
332176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
333176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
334176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
3366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void testBinaryOperatorShortcut(bool value) {
3376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (value) {
3386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (false && false && check(NoReturnDtor()) && true) {
3396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        clang_analyzer_eval(true);
3406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
3416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
3426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
3436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
344176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testIfAtEndOfLoop() {
345176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    int y = 0;
346176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    while (true) {
347176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (y > 0) {
348176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
349176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
350176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ++y;
351176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Test that the CFG gets hooked up correctly when temporary destructors
352176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // are handled after a statically known branch condition.
353176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (true) (void)0; else (void)check(NoReturnDtor());
354176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
355176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
356176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
357176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testTernaryAtEndOfLoop() {
358176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    int y = 0;
359176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    while (true) {
360176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (y > 0) {
361176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
362176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      }
363176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      ++y;
364176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // Test that the CFG gets hooked up correctly when temporary destructors
365176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // are handled after a statically known branch condition.
366176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      true ? (void)0 : (void)check(NoReturnDtor());
367176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
368176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
369176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
370176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testNoReturnInComplexCondition() {
371176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    check(Dtor()) &&
372176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());
373176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
374176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
375176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
376176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testSequencingOfConditionalTempDtors(bool b) {
377176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    b || (check(Dtor()), check(NoReturnDtor()));
378176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
379176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
380176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
381176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testSequencingOfConditionalTempDtors2(bool b) {
382176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    (b || check(Dtor())), check(NoReturnDtor());
383176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    clang_analyzer_warnIfReached();  // no warning, unreachable code
384176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
385176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
386176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) {
387176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    b || (check(Dtor()) + check(NoReturnDtor()));
388176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
389176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
390176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
391176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void f(Dtor d = Dtor());
392176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testDefaultParameters() {
393176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    f();
394176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
395176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
396176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  struct DefaultParam {
397176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    DefaultParam(int, const Dtor& d = Dtor());
398176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    ~DefaultParam();
399176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  };
400176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testDefaultParamConstructorsInLoops() {
401176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    while (true) {
402176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // FIXME: This exact pattern triggers the temporary cleanup logic
403176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // to fail when adding a 'clean' state.
404176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      DefaultParam(42);
405176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      DefaultParam(42);
406176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
407176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
408176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  void testDefaultParamConstructorsInTernariesInLoops(bool value) {
409176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    while (true) {
410176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // FIXME: This exact pattern triggers the temporary cleanup logic
411176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // to visit the bind-temporary logic with a state that already has that
412176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // temporary marked as executed.
413176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      value ? DefaultParam(42) : DefaultParam(42);
414176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
415176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
41695ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath#endif // TEMPORARY_DTORS
417062ef6e6d956b8873e33fe84574c7630d2829d3dJordan Rose}
41876b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath
41976b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labathvoid testStaticMaterializeTemporaryExpr() {
42076b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  static const Trivial &ref = getTrivial();
42176b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
42276b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath
42376b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  static const Trivial &directRef = Trivial(42);
42476b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
42576b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath
42699b3cc6ec4fbcd887b632dcb7147ef472d83fc37Pavel Labath#if __has_feature(cxx_thread_local)
42776b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  thread_local static const Trivial &threadRef = getTrivial();
42876b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
42976b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath
43076b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  thread_local static const Trivial &threadDirectRef = Trivial(42);
43176b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath  clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
43276b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath#endif
43376b5dd48c9dbf2ed3e5830060ea55b81b7d1cca0Pavel Labath}
4346ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4356ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labathnamespace PR16629 {
4366ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  struct A {
4376ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    explicit A(int* p_) : p(p_) {}
4386ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    int* p;
4396ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  };
4406ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4416ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  extern void escape(const A*[]);
4426ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  extern void check(int);
4436ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4446ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  void callEscape(const A& a) {
4456ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    const A* args[] = { &a };
4466ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    escape(args);
4476ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  }
4486ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4496ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  void testNoWarning() {
4506ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    int x;
4516ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    callEscape(A(&x));
4526ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    check(x); // Analyzer used to give a "x is uninitialized warning" here
4536ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  }
4546ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4556ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  void set(const A*a[]) {
4566ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    *a[0]->p = 47;
4576ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  }
4586ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4596ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  void callSet(const A& a) {
4606ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    const A* args[] = { &a };
4616ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    set(args);
4626ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  }
4636ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath
4646ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  void testConsistency() {
4656ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    int x;
4666ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    callSet(A(&x));
4676ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath    clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
4686ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath  }
4696ebe9df900b79fd56a4db03b4f8aa6a180307a9dPavel Labath}
470