temporaries.cpp revision 062ef6e6d956b8873e33fe84574c7630d2829d3d
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
3
4extern bool clang_analyzer_eval(bool);
5
6struct Trivial {
7  Trivial(int x) : value(x) {}
8  int value;
9};
10
11struct NonTrivial : public Trivial {
12  NonTrivial(int x) : Trivial(x) {}
13  ~NonTrivial();
14};
15
16
17Trivial getTrivial() {
18  return Trivial(42); // no-warning
19}
20
21const Trivial &getTrivialRef() {
22  return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
23}
24
25
26NonTrivial getNonTrivial() {
27  return NonTrivial(42); // no-warning
28}
29
30const NonTrivial &getNonTrivialRef() {
31  return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
32}
33
34namespace rdar13265460 {
35  struct TrivialSubclass : public Trivial {
36    TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
37    int anotherValue;
38  };
39
40  TrivialSubclass getTrivialSub() {
41    TrivialSubclass obj(1);
42    obj.value = 42;
43    obj.anotherValue = -42;
44    return obj;
45  }
46
47  void testImmediate() {
48    TrivialSubclass obj = getTrivialSub();
49
50    clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
51    clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
52
53    clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
54    clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
55  }
56
57  void testMaterializeTemporaryExpr() {
58    const TrivialSubclass &ref = getTrivialSub();
59    clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
60
61    const Trivial &baseRef = getTrivialSub();
62    clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
63  }
64}
65
66namespace rdar13281951 {
67  struct Derived : public Trivial {
68    Derived(int value) : Trivial(value), value2(-value) {}
69    int value2;
70  };
71
72  void test() {
73    Derived obj(1);
74    obj.value = 42;
75    const Trivial * const &pointerRef = &obj;
76    clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}
77  }
78}
79
80namespace compound_literals {
81  struct POD {
82    int x, y;
83  };
84  struct HasCtor {
85    HasCtor(int x, int y) : x(x), y(y) {}
86    int x, y;
87  };
88  struct HasDtor {
89    int x, y;
90    ~HasDtor();
91  };
92  struct HasCtorDtor {
93    HasCtorDtor(int x, int y) : x(x), y(y) {}
94    ~HasCtorDtor();
95    int x, y;
96  };
97
98  void test() {
99    clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
100    clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
101
102#if __cplusplus >= 201103L
103    clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
104
105    // FIXME: should be TRUE, but we don't inline the constructors of
106    // temporaries because we can't model their destructors yet.
107    clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
108#endif
109  }
110}
111
112namespace destructors {
113  void testPR16664Crash() {
114    struct Dtor {
115      ~Dtor();
116    };
117    extern bool coin();
118    extern bool check(const Dtor &);
119
120    // Don't crash here.
121    if (coin() && (coin() || coin() || check(Dtor()))) {
122      Dtor();
123    }
124  }
125
126  void testConsistency(int i) {
127    struct NoReturnDtor {
128      ~NoReturnDtor() __attribute__((noreturn));
129    };
130    extern bool check(const NoReturnDtor &);
131
132    if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
133      clang_analyzer_eval(true); // expected-warning{{TRUE}}
134
135    if (i != 5)
136      return;
137    if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
138      // FIXME: Should be no-warning, because the noreturn destructor should
139      // fire on all paths.
140      clang_analyzer_eval(true); // expected-warning{{TRUE}}
141    }
142  }
143}
144