xref: /minix3/external/bsd/llvm/dist/clang/test/Analysis/array-struct-region.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c %s
2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -x c++ -analyzer-config c++-inlining=constructors %s
3*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c %s
4*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -DINLINE -verify -x c++ -analyzer-config c++-inlining=constructors %s
5*f4a2713aSLionel Sambuc 
6*f4a2713aSLionel Sambuc void clang_analyzer_eval(int);
7*f4a2713aSLionel Sambuc 
8*f4a2713aSLionel Sambuc struct S {
9*f4a2713aSLionel Sambuc   int field;
10*f4a2713aSLionel Sambuc 
11*f4a2713aSLionel Sambuc #if __cplusplus
getThisS12*f4a2713aSLionel Sambuc   const struct S *getThis() const { return this; }
operator +S13*f4a2713aSLionel Sambuc   const struct S *operator +() const { return this; }
14*f4a2713aSLionel Sambuc 
checkS15*f4a2713aSLionel Sambuc   bool check() const { return this == this; }
operator !S16*f4a2713aSLionel Sambuc   bool operator !() const { return this != this; }
17*f4a2713aSLionel Sambuc 
operator *S18*f4a2713aSLionel Sambuc   int operator *() const { return field; }
19*f4a2713aSLionel Sambuc #endif
20*f4a2713aSLionel Sambuc };
21*f4a2713aSLionel Sambuc 
22*f4a2713aSLionel Sambuc #if __cplusplus
operator -(const struct S & s)23*f4a2713aSLionel Sambuc const struct S *operator -(const struct S &s) { return &s; }
operator ~(const struct S & s)24*f4a2713aSLionel Sambuc bool operator ~(const struct S &s) { return (&s) != &s; }
25*f4a2713aSLionel Sambuc #endif
26*f4a2713aSLionel Sambuc 
27*f4a2713aSLionel Sambuc 
28*f4a2713aSLionel Sambuc #ifdef INLINE
getS()29*f4a2713aSLionel Sambuc struct S getS() {
30*f4a2713aSLionel Sambuc   struct S s = { 42 };
31*f4a2713aSLionel Sambuc   return s;
32*f4a2713aSLionel Sambuc }
33*f4a2713aSLionel Sambuc #else
34*f4a2713aSLionel Sambuc struct S getS();
35*f4a2713aSLionel Sambuc #endif
36*f4a2713aSLionel Sambuc 
37*f4a2713aSLionel Sambuc 
testAssignment()38*f4a2713aSLionel Sambuc void testAssignment() {
39*f4a2713aSLionel Sambuc   struct S s = getS();
40*f4a2713aSLionel Sambuc 
41*f4a2713aSLionel Sambuc   if (s.field != 42) return;
42*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
43*f4a2713aSLionel Sambuc 
44*f4a2713aSLionel Sambuc   s.field = 0;
45*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
46*f4a2713aSLionel Sambuc 
47*f4a2713aSLionel Sambuc #if __cplusplus
48*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
49*f4a2713aSLionel Sambuc   clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
50*f4a2713aSLionel Sambuc   clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}}
51*f4a2713aSLionel Sambuc 
52*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
53*f4a2713aSLionel Sambuc   clang_analyzer_eval(!s); // expected-warning{{FALSE}}
54*f4a2713aSLionel Sambuc   clang_analyzer_eval(~s); // expected-warning{{FALSE}}
55*f4a2713aSLionel Sambuc 
56*f4a2713aSLionel Sambuc   clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}}
57*f4a2713aSLionel Sambuc #endif
58*f4a2713aSLionel Sambuc }
59*f4a2713aSLionel Sambuc 
60*f4a2713aSLionel Sambuc 
testImmediateUse()61*f4a2713aSLionel Sambuc void testImmediateUse() {
62*f4a2713aSLionel Sambuc   int x = getS().field;
63*f4a2713aSLionel Sambuc 
64*f4a2713aSLionel Sambuc   if (x != 42) return;
65*f4a2713aSLionel Sambuc   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
66*f4a2713aSLionel Sambuc 
67*f4a2713aSLionel Sambuc #if __cplusplus
68*f4a2713aSLionel Sambuc   clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
69*f4a2713aSLionel Sambuc   clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}}
70*f4a2713aSLionel Sambuc   clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}}
71*f4a2713aSLionel Sambuc 
72*f4a2713aSLionel Sambuc   clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}}
73*f4a2713aSLionel Sambuc   clang_analyzer_eval(!getS()); // expected-warning{{FALSE}}
74*f4a2713aSLionel Sambuc   clang_analyzer_eval(~getS()); // expected-warning{{FALSE}}
75*f4a2713aSLionel Sambuc #endif
76*f4a2713aSLionel Sambuc }
77*f4a2713aSLionel Sambuc 
getConstrainedField(struct S s)78*f4a2713aSLionel Sambuc int getConstrainedField(struct S s) {
79*f4a2713aSLionel Sambuc   if (s.field != 42) return 42;
80*f4a2713aSLionel Sambuc   return s.field;
81*f4a2713aSLionel Sambuc }
82*f4a2713aSLionel Sambuc 
getAssignedField(struct S s)83*f4a2713aSLionel Sambuc int getAssignedField(struct S s) {
84*f4a2713aSLionel Sambuc   s.field = 42;
85*f4a2713aSLionel Sambuc   return s.field;
86*f4a2713aSLionel Sambuc }
87*f4a2713aSLionel Sambuc 
testArgument()88*f4a2713aSLionel Sambuc void testArgument() {
89*f4a2713aSLionel Sambuc   clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
90*f4a2713aSLionel Sambuc   clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
91*f4a2713aSLionel Sambuc }
92*f4a2713aSLionel Sambuc 
testImmediateUseParens()93*f4a2713aSLionel Sambuc void testImmediateUseParens() {
94*f4a2713aSLionel Sambuc   int x = ((getS())).field;
95*f4a2713aSLionel Sambuc 
96*f4a2713aSLionel Sambuc   if (x != 42) return;
97*f4a2713aSLionel Sambuc   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
98*f4a2713aSLionel Sambuc 
99*f4a2713aSLionel Sambuc   clang_analyzer_eval(getConstrainedField(((getS()))) == 42); // expected-warning{{TRUE}}
100*f4a2713aSLionel Sambuc   clang_analyzer_eval(getAssignedField(((getS()))) == 42); // expected-warning{{TRUE}}
101*f4a2713aSLionel Sambuc 
102*f4a2713aSLionel Sambuc #if __cplusplus
103*f4a2713aSLionel Sambuc   clang_analyzer_eval(((getS())).check()); // expected-warning{{TRUE}}
104*f4a2713aSLionel Sambuc   clang_analyzer_eval(!((getS()))); // expected-warning{{FALSE}}
105*f4a2713aSLionel Sambuc   clang_analyzer_eval(~((getS()))); // expected-warning{{FALSE}}
106*f4a2713aSLionel Sambuc #endif
107*f4a2713aSLionel Sambuc }
108*f4a2713aSLionel Sambuc 
109*f4a2713aSLionel Sambuc 
110*f4a2713aSLionel Sambuc //--------------------
111*f4a2713aSLionel Sambuc // C++-only tests
112*f4a2713aSLionel Sambuc //--------------------
113*f4a2713aSLionel Sambuc 
114*f4a2713aSLionel Sambuc #if __cplusplus
testReferenceAssignment()115*f4a2713aSLionel Sambuc void testReferenceAssignment() {
116*f4a2713aSLionel Sambuc   const S &s = getS();
117*f4a2713aSLionel Sambuc 
118*f4a2713aSLionel Sambuc   if (s.field != 42) return;
119*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
120*f4a2713aSLionel Sambuc 
121*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
122*f4a2713aSLionel Sambuc   clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
123*f4a2713aSLionel Sambuc 
124*f4a2713aSLionel Sambuc   clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
125*f4a2713aSLionel Sambuc   clang_analyzer_eval(!s); // expected-warning{{FALSE}}
126*f4a2713aSLionel Sambuc   clang_analyzer_eval(~s); // expected-warning{{FALSE}}
127*f4a2713aSLionel Sambuc 
128*f4a2713aSLionel Sambuc   clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}
129*f4a2713aSLionel Sambuc }
130*f4a2713aSLionel Sambuc 
131*f4a2713aSLionel Sambuc 
getConstrainedFieldRef(const S & s)132*f4a2713aSLionel Sambuc int getConstrainedFieldRef(const S &s) {
133*f4a2713aSLionel Sambuc   if (s.field != 42) return 42;
134*f4a2713aSLionel Sambuc   return s.field;
135*f4a2713aSLionel Sambuc }
136*f4a2713aSLionel Sambuc 
checkThis(const S & s)137*f4a2713aSLionel Sambuc bool checkThis(const S &s) {
138*f4a2713aSLionel Sambuc   return s.getThis() == &s;
139*f4a2713aSLionel Sambuc }
140*f4a2713aSLionel Sambuc 
checkThisOp(const S & s)141*f4a2713aSLionel Sambuc bool checkThisOp(const S &s) {
142*f4a2713aSLionel Sambuc   return +s == &s;
143*f4a2713aSLionel Sambuc }
144*f4a2713aSLionel Sambuc 
checkThisStaticOp(const S & s)145*f4a2713aSLionel Sambuc bool checkThisStaticOp(const S &s) {
146*f4a2713aSLionel Sambuc   return -s == &s;
147*f4a2713aSLionel Sambuc }
148*f4a2713aSLionel Sambuc 
testReferenceArgument()149*f4a2713aSLionel Sambuc void testReferenceArgument() {
150*f4a2713aSLionel Sambuc   clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
151*f4a2713aSLionel Sambuc   clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
152*f4a2713aSLionel Sambuc   clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
153*f4a2713aSLionel Sambuc   clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
154*f4a2713aSLionel Sambuc }
155*f4a2713aSLionel Sambuc 
156*f4a2713aSLionel Sambuc 
getConstrainedFieldOp(S s)157*f4a2713aSLionel Sambuc int getConstrainedFieldOp(S s) {
158*f4a2713aSLionel Sambuc   if (*s != 42) return 42;
159*f4a2713aSLionel Sambuc   return *s;
160*f4a2713aSLionel Sambuc }
161*f4a2713aSLionel Sambuc 
getConstrainedFieldRefOp(const S & s)162*f4a2713aSLionel Sambuc int getConstrainedFieldRefOp(const S &s) {
163*f4a2713aSLionel Sambuc   if (*s != 42) return 42;
164*f4a2713aSLionel Sambuc   return *s;
165*f4a2713aSLionel Sambuc }
166*f4a2713aSLionel Sambuc 
testImmediateUseOp()167*f4a2713aSLionel Sambuc void testImmediateUseOp() {
168*f4a2713aSLionel Sambuc   int x = *getS();
169*f4a2713aSLionel Sambuc   if (x != 42) return;
170*f4a2713aSLionel Sambuc   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
171*f4a2713aSLionel Sambuc 
172*f4a2713aSLionel Sambuc   clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}
173*f4a2713aSLionel Sambuc   clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}
174*f4a2713aSLionel Sambuc }
175*f4a2713aSLionel Sambuc 
176*f4a2713aSLionel Sambuc namespace EmptyClass {
177*f4a2713aSLionel Sambuc   struct Base {
178*f4a2713aSLionel Sambuc     int& x;
179*f4a2713aSLionel Sambuc 
BaseEmptyClass::Base180*f4a2713aSLionel Sambuc     Base(int& x) : x(x) {}
181*f4a2713aSLionel Sambuc   };
182*f4a2713aSLionel Sambuc 
183*f4a2713aSLionel Sambuc   struct Derived : public Base {
DerivedEmptyClass::Derived184*f4a2713aSLionel Sambuc     Derived(int& x) : Base(x) {}
185*f4a2713aSLionel Sambuc 
operator =EmptyClass::Derived186*f4a2713aSLionel Sambuc     void operator=(int a) { x = a; }
187*f4a2713aSLionel Sambuc   };
188*f4a2713aSLionel Sambuc 
ref(int & a)189*f4a2713aSLionel Sambuc   Derived ref(int& a) { return Derived(a); }
190*f4a2713aSLionel Sambuc 
191*f4a2713aSLionel Sambuc   // There used to be a warning here, because analyzer treated Derived as empty.
test()192*f4a2713aSLionel Sambuc   int test() {
193*f4a2713aSLionel Sambuc     int a;
194*f4a2713aSLionel Sambuc     ref(a) = 42;
195*f4a2713aSLionel Sambuc     return a; // no warning
196*f4a2713aSLionel Sambuc   }
197*f4a2713aSLionel Sambuc }
198*f4a2713aSLionel Sambuc 
199*f4a2713aSLionel Sambuc #endif
200