blob: ea4abb2d843c11720e1bd15e392776e670f3613d [file] [log] [blame]
Jordan Rose5d2abef2013-05-06 16:48:20 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
Pavel Labathe4e30862013-07-26 12:50:30 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
Jordan Rose2c625dd2012-08-29 01:11:59 +00003
Jordan Rosefe03e402013-02-21 23:57:17 +00004extern bool clang_analyzer_eval(bool);
5
Jordan Rose2c625dd2012-08-29 01:11:59 +00006struct 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() {
Jordan Rosec9487092013-02-26 01:21:21 +000022 return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
Jordan Rose2c625dd2012-08-29 01:11:59 +000023}
24
25
26NonTrivial getNonTrivial() {
27 return NonTrivial(42); // no-warning
28}
29
30const NonTrivial &getNonTrivialRef() {
Jordan Rosec9487092013-02-26 01:21:21 +000031 return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
Jordan Rose2c625dd2012-08-29 01:11:59 +000032}
33
Jordan Rosefe03e402013-02-21 23:57:17 +000034namespace 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
Jordan Rose5772f822013-02-22 01:51:15 +000047 void testImmediate() {
Jordan Rosefe03e402013-02-21 23:57:17 +000048 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 }
Jordan Rose5772f822013-02-22 01:51:15 +000056
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 }
Jordan Rosefe03e402013-02-21 23:57:17 +000064}
65
Jordan Rose861a1742013-02-26 01:21:27 +000066namespace 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
Jordan Rose5d2abef2013-05-06 16:48:20 +000080namespace 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
Jordan Rosee15a8a42013-07-25 17:22:05 +0000112namespace 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}
Pavel Labathcf878bb2013-07-26 11:50:42 +0000144
145void testStaticMaterializeTemporaryExpr() {
146 static const Trivial &ref = getTrivial();
147 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
148
149 static const Trivial &directRef = Trivial(42);
150 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
151
Pavel Labathe4e30862013-07-26 12:50:30 +0000152#if __has_feature(cxx_thread_local)
Pavel Labathcf878bb2013-07-26 11:50:42 +0000153 thread_local static const Trivial &threadRef = getTrivial();
154 clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
155
156 thread_local static const Trivial &threadDirectRef = Trivial(42);
157 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
158#endif
159}