blob: 47776863d6a2171dd51b55366386e39e9fd54258 [file] [log] [blame]
Jordan Rose6ebea892012-09-05 17:11:26 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s
Jordan Rosef1e67d72012-10-17 19:35:37 +00003// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c %s
4// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c++ -analyzer-config c++-inlining=constructors %s
Jordan Rose6ebea892012-09-05 17:11:26 +00005
6void clang_analyzer_eval(int);
7
8struct S {
9 int field;
10
11#if __cplusplus
12 const struct S *getThis() const { return this; }
Jordan Rosef1e67d72012-10-17 19:35:37 +000013 const struct S *operator +() const { return this; }
14
15 bool check() const { return this == this; }
16 bool operator !() const { return this != this; }
17
18 int operator *() const { return field; }
Jordan Rose6ebea892012-09-05 17:11:26 +000019#endif
20};
21
Jordan Rosef1e67d72012-10-17 19:35:37 +000022#if __cplusplus
23const struct S *operator -(const struct S &s) { return &s; }
Jordan Rose9a7a5682013-11-08 01:15:39 +000024bool operator ~(const struct S &s) { return (&s) != &s; }
Jordan Rosef1e67d72012-10-17 19:35:37 +000025#endif
26
27
28#ifdef INLINE
29struct S getS() {
30 struct S s = { 42 };
31 return s;
32}
33#else
Jordan Rose6ebea892012-09-05 17:11:26 +000034struct S getS();
Jordan Rosef1e67d72012-10-17 19:35:37 +000035#endif
Jordan Rose6ebea892012-09-05 17:11:26 +000036
37
38void testAssignment() {
39 struct S s = getS();
40
41 if (s.field != 42) return;
42 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
43
44 s.field = 0;
45 clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
46
47#if __cplusplus
48 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
Jordan Rosef1e67d72012-10-17 19:35:37 +000049 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
50 clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}}
51
52 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
53 clang_analyzer_eval(!s); // expected-warning{{FALSE}}
54 clang_analyzer_eval(~s); // expected-warning{{FALSE}}
55
56 clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}}
Jordan Rose6ebea892012-09-05 17:11:26 +000057#endif
58}
59
60
61void testImmediateUse() {
62 int x = getS().field;
63
64 if (x != 42) return;
65 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
66
67#if __cplusplus
68 clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
Jordan Rosef1e67d72012-10-17 19:35:37 +000069 clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}}
70 clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}}
71
72 clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}}
73 clang_analyzer_eval(!getS()); // expected-warning{{FALSE}}
74 clang_analyzer_eval(~getS()); // expected-warning{{FALSE}}
Jordan Rose6ebea892012-09-05 17:11:26 +000075#endif
76}
77
78int getConstrainedField(struct S s) {
79 if (s.field != 42) return 42;
80 return s.field;
81}
82
83int getAssignedField(struct S s) {
84 s.field = 42;
85 return s.field;
86}
87
88void testArgument() {
89 clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
Jordan Rose6ebea892012-09-05 17:11:26 +000090 clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
91}
92
Jordan Rosed4ce8112012-10-17 19:35:44 +000093void testImmediateUseParens() {
94 int x = ((getS())).field;
95
96 if (x != 42) return;
97 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
98
99 clang_analyzer_eval(getConstrainedField(((getS()))) == 42); // expected-warning{{TRUE}}
100 clang_analyzer_eval(getAssignedField(((getS()))) == 42); // expected-warning{{TRUE}}
101
102#if __cplusplus
103 clang_analyzer_eval(((getS())).check()); // expected-warning{{TRUE}}
104 clang_analyzer_eval(!((getS()))); // expected-warning{{FALSE}}
105 clang_analyzer_eval(~((getS()))); // expected-warning{{FALSE}}
106#endif
107}
108
Jordan Rose6ebea892012-09-05 17:11:26 +0000109
110//--------------------
111// C++-only tests
112//--------------------
113
114#if __cplusplus
115void testReferenceAssignment() {
116 const S &s = getS();
117
118 if (s.field != 42) return;
119 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
120
121 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
Jordan Rosef1e67d72012-10-17 19:35:37 +0000122 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
123
124 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
125 clang_analyzer_eval(!s); // expected-warning{{FALSE}}
126 clang_analyzer_eval(~s); // expected-warning{{FALSE}}
127
128 clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}
Jordan Rose6ebea892012-09-05 17:11:26 +0000129}
130
131
132int getConstrainedFieldRef(const S &s) {
133 if (s.field != 42) return 42;
134 return s.field;
135}
136
137bool checkThis(const S &s) {
138 return s.getThis() == &s;
139}
140
Jordan Rosef1e67d72012-10-17 19:35:37 +0000141bool checkThisOp(const S &s) {
142 return +s == &s;
143}
144
145bool checkThisStaticOp(const S &s) {
146 return -s == &s;
147}
148
Jordan Rose6ebea892012-09-05 17:11:26 +0000149void testReferenceArgument() {
150 clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
151 clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
Jordan Rosef1e67d72012-10-17 19:35:37 +0000152 clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
153 clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
Jordan Rose6ebea892012-09-05 17:11:26 +0000154}
Jordan Rosef1e67d72012-10-17 19:35:37 +0000155
156
157int getConstrainedFieldOp(S s) {
158 if (*s != 42) return 42;
159 return *s;
160}
161
162int getConstrainedFieldRefOp(const S &s) {
163 if (*s != 42) return 42;
164 return *s;
165}
166
167void testImmediateUseOp() {
168 int x = *getS();
169 if (x != 42) return;
170 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
171
172 clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}
173 clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}
174}
175
Pavel Labath3c114f72013-08-29 16:06:04 +0000176namespace EmptyClass {
177 struct Base {
178 int& x;
179
180 Base(int& x) : x(x) {}
181 };
182
183 struct Derived : public Base {
184 Derived(int& x) : Base(x) {}
185
186 void operator=(int a) { x = a; }
187 };
188
189 Derived ref(int& a) { return Derived(a); }
190
191 // There used to be a warning here, because analyzer treated Derived as empty.
192 int test() {
193 int a;
194 ref(a) = 42;
195 return a; // no warning
196 }
197}
198
Jordan Rose6ebea892012-09-05 17:11:26 +0000199#endif