xref: /llvm-project/clang/test/Analysis/array-struct-region.cpp (revision cd9000e840e57d25fbc7fea995413379ef5b1cbc)
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 
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 #endif
14 };
15 
16 #ifdef INLINE
17 struct S getS() {
18   struct S s = { 42 };
19   return s;
20 }
21 #else
22 struct S getS();
23 #endif
24 
25 
26 void 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 
41 void 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 
52 int getConstrainedField(struct S s) {
53   if (s.field != 42) return 42;
54   return s.field;
55 }
56 
57 int getAssignedField(struct S s) {
58   s.field = 42;
59   return s.field;
60 }
61 
62 void 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
79 void 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 
89 int getConstrainedFieldRef(const S &s) {
90   if (s.field != 42) return 42;
91   return s.field;
92 }
93 
94 bool checkThis(const S &s) {
95   return s.getThis() == &s;
96 }
97 
98 void testReferenceArgument() {
99   clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
100   clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
101 }
102 #endif
103