]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/array-struct-region.cpp
Vendor import of clang trunk r300422:
[FreeBSD/FreeBSD.git] / test / Analysis / array-struct-region.cpp
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s
3 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c %s
4 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c++ -analyzer-config c++-inlining=constructors %s
5
6 void clang_analyzer_eval(int);
7
8 struct S {
9   int field;
10
11 #if __cplusplus
12   const struct S *getThis() const { return this; }
13   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; }
19 #endif
20 };
21
22 #if __cplusplus
23 const struct S *operator -(const struct S &s) { return &s; }
24 bool operator ~(const struct S &s) { return (&s) != &s; }
25 #endif
26
27
28 #ifdef INLINE
29 struct S getS() {
30   struct S s = { 42 };
31   return s;
32 }
33 #else
34 struct S getS();
35 #endif
36
37
38 void 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}}
49   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}}
57 #endif
58 }
59
60
61 void 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}}
69   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}}
75 #endif
76 }
77
78 int getConstrainedField(struct S s) {
79   if (s.field != 42) return 42;
80   return s.field;
81 }
82
83 int getAssignedField(struct S s) {
84   s.field = 42;
85   return s.field;
86 }
87
88 void testArgument() {
89   clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
90   clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
91 }
92
93 void 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
109
110 //--------------------
111 // C++-only tests
112 //--------------------
113
114 #if __cplusplus
115 void 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}}
122   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}}
129 }
130
131
132 int getConstrainedFieldRef(const S &s) {
133   if (s.field != 42) return 42;
134   return s.field;
135 }
136
137 bool checkThis(const S &s) {
138   return s.getThis() == &s;
139 }
140
141 bool checkThisOp(const S &s) {
142   return +s == &s;
143 }
144
145 bool checkThisStaticOp(const S &s) {
146   return -s == &s;
147 }
148
149 void testReferenceArgument() {
150   clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
151   clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
152   clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
153   clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
154 }
155
156
157 int getConstrainedFieldOp(S s) {
158   if (*s != 42) return 42;
159   return *s;
160 }
161
162 int getConstrainedFieldRefOp(const S &s) {
163   if (*s != 42) return 42;
164   return *s;
165 }
166
167 void 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
176 namespace 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
199 #endif