array-struct-region.cpp revision f1e67d75fc922ff905de9faa6326bb1a96685ec1
1// 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
3// 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
5
6void clang_analyzer_eval(int);
7
8struct 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
23const struct S *operator -(const struct S &s) { return &s; }
24bool operator ~(const struct S &s) { return &s != &s; }
25#endif
26
27
28#ifdef INLINE
29struct S getS() {
30  struct S s = { 42 };
31  return s;
32}
33#else
34struct S getS();
35#endif
36
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}}
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
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}}
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
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}}
90  clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
91}
92
93
94//--------------------
95// C++-only tests
96//--------------------
97
98#if __cplusplus
99void testReferenceAssignment() {
100  const S &s = getS();
101
102  if (s.field != 42) return;
103  clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
104
105  clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
106  clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
107
108  clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
109  clang_analyzer_eval(!s); // expected-warning{{FALSE}}
110  clang_analyzer_eval(~s); // expected-warning{{FALSE}}
111
112  clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}
113}
114
115
116int getConstrainedFieldRef(const S &s) {
117  if (s.field != 42) return 42;
118  return s.field;
119}
120
121bool checkThis(const S &s) {
122  return s.getThis() == &s;
123}
124
125bool checkThisOp(const S &s) {
126  return +s == &s;
127}
128
129bool checkThisStaticOp(const S &s) {
130  return -s == &s;
131}
132
133void testReferenceArgument() {
134  clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
135  clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
136  clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
137  clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
138}
139
140
141int getConstrainedFieldOp(S s) {
142  if (*s != 42) return 42;
143  return *s;
144}
145
146int getConstrainedFieldRefOp(const S &s) {
147  if (*s != 42) return 42;
148  return *s;
149}
150
151void testImmediateUseOp() {
152  int x = *getS();
153  if (x != 42) return;
154  clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
155
156  clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}
157  clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}
158}
159
160#endif
161