array-struct-region.cpp revision 0006ba445962621ed82ec84400a6b978205a3fbc
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#endif
14};
15
16#ifdef INLINE
17struct S getS() {
18  struct S s = { 42 };
19  return s;
20}
21#else
22struct S getS();
23#endif
24
25
26void testAssignment() {
27  struct S s = getS();
28
29  if (s.field != 42) return;
30  clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
31
32  s.field = 0;
33  clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
34
35#if __cplusplus
36  clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
37#endif
38}
39
40
41void testImmediateUse() {
42  int x = getS().field;
43
44  if (x != 42) return;
45  clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
46
47#if __cplusplus
48  clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
49#endif
50}
51
52int getConstrainedField(struct S s) {
53  if (s.field != 42) return 42;
54  return s.field;
55}
56
57int getAssignedField(struct S s) {
58  s.field = 42;
59  return s.field;
60}
61
62void testArgument() {
63  clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
64#if __cplusplus
65  // FIXME: Passing the struct by value seems to be confusing C++.
66  // Possibly related to <rdar://problem/12137950>.
67  // expected-warning@-4{{UNKNOWN}}
68#endif
69
70  clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
71}
72
73
74//--------------------
75// C++-only tests
76//--------------------
77
78#if __cplusplus
79void testReferenceAssignment() {
80  const S &s = getS();
81
82  if (s.field != 42) return;
83  clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
84
85  clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
86}
87
88
89int getConstrainedFieldRef(const S &s) {
90  if (s.field != 42) return 42;
91  return s.field;
92}
93
94bool checkThis(const S &s) {
95  return s.getThis() == &s;
96}
97
98void testReferenceArgument() {
99  clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
100  clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
101}
102#endif
103