blob: cffa64d21ab5d834c2359800172e3776112e19c3 [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; }
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
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
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}}
Jordan Rosef1e67d72012-10-17 19:35:37 +0000106 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}}
Jordan Rose6ebea892012-09-05 17:11:26 +0000113}
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
Jordan Rosef1e67d72012-10-17 19:35:37 +0000125bool checkThisOp(const S &s) {
126 return +s == &s;
127}
128
129bool checkThisStaticOp(const S &s) {
130 return -s == &s;
131}
132
Jordan Rose6ebea892012-09-05 17:11:26 +0000133void testReferenceArgument() {
134 clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
135 clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
Jordan Rosef1e67d72012-10-17 19:35:37 +0000136 clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
137 clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
Jordan Rose6ebea892012-09-05 17:11:26 +0000138}
Jordan Rosef1e67d72012-10-17 19:35:37 +0000139
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
Jordan Rose6ebea892012-09-05 17:11:26 +0000160#endif