array-struct.c revision e1cea75e70d76f55157749a7bcad319050492945
1// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s &&
2// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic-new-cast -analyzer-constraints=basic -verify %s &&
3// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s &&
4// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic-new-cast -analyzer-constraints=range -verify %s
5
6// RegionStore now has an infinite recursion with this test case.
7// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s &&
8// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s
9
10struct s {
11  int data;
12  int data_array[10];
13};
14
15typedef struct {
16  int data;
17} STYPE;
18
19void g(char *p);
20void g1(struct s* p);
21
22// Array to pointer conversion. Array in the struct field.
23void f(void) {
24  int a[10];
25  int (*p)[10];
26  p = &a;
27  (*p)[3] = 1;
28
29  struct s d;
30  struct s *q;
31  q = &d;
32  q->data = 3;
33  d.data_array[9] = 17;
34}
35
36// StringLiteral in lvalue context and pointer to array type.
37// p: ElementRegion, q: StringRegion
38void f2() {
39  char *p = "/usr/local";
40  char (*q)[4];
41  q = &"abc";
42}
43
44// Typedef'ed struct definition.
45void f3() {
46  STYPE s;
47}
48
49// Initialize array with InitExprList.
50void f4() {
51  int a[] = { 1, 2, 3};
52  int b[3] = { 1, 2 };
53  struct s c[] = {{1,{1}}};
54}
55
56// Struct variable in lvalue context.
57// Assign UnknownVal to the whole struct.
58void f5() {
59  struct s data;
60  g1(&data);
61}
62
63// AllocaRegion test.
64void f6() {
65  char *p;
66  p = __builtin_alloca(10);
67  g(p);
68  char c = *p;
69  p[1] = 'a';
70  // Test if RegionStore::EvalBinOp converts the alloca region to element
71  // region.
72  p += 2;
73}
74
75struct s2;
76
77void g2(struct s2 *p);
78
79// Incomplete struct pointer used as function argument.
80void f7() {
81  struct s2 *p = __builtin_alloca(10);
82  g2(p);
83}
84
85// sizeof() is unsigned while -1 is signed in array index.
86void f8() {
87  int a[10];
88  a[sizeof(a)/sizeof(int) - 1] = 1; // no-warning
89}
90
91// Initialization of struct array elements.
92void f9() {
93  struct s a[10];
94}
95
96// Initializing array with string literal.
97void f10() {
98  char a1[4] = "abc";
99  char a3[6] = "abc";
100}
101
102// Retrieve the default value of element/field region.
103void f11() {
104  struct s a;
105  g1(&a);
106  if (a.data == 0) // no-warning
107    a.data = 1;
108}
109
110// Convert unsigned offset to signed when creating ElementRegion from
111// SymbolicRegion.
112void f12(int *list) {
113  unsigned i = 0;
114  list[i] = 1;
115}
116
117struct s1 {
118  struct s2 {
119    int d;
120  } e;
121};
122
123// The binding of a.e.d should not be removed. Test recursive subregion map
124// building: a->e, e->d. Only then 'a' could be added to live region roots.
125void f13(double timeout) {
126  struct s1 a;
127  a.e.d = (long) timeout;
128  if (a.e.d == 10)
129    a.e.d = 4;
130}
131
132struct s3 {
133  int a[2];
134};
135
136static struct s3 opt;
137
138// Test if the embedded array is retrieved correctly.
139void f14() {
140  struct s3 my_opt = opt;
141}
142
143void bar(int*);
144
145// Test if the array is correctly invalidated.
146void f15() {
147  int a[10];
148  bar(a);
149  if (a[1]) // no-warning
150    1;
151}
152
153struct s3 p[1];
154
155// Code from postgresql.
156// Current cast logic of region store mistakenly leaves the final result region
157// an ElementRegion of type 'char'. Then load a nonloc::SymbolVal from it and
158// assigns to 'a'.
159void f16(struct s3 *p) {
160  struct s3 a = *((struct s3*) ((char*) &p[0]));
161}
162
163void inv(struct s1 *);
164
165// Invalidate the struct field.
166void f17() {
167  struct s1 t;
168  int x;
169  inv(&t);
170  if (t.e.d)
171    x = 1;
172}
173
174void read(char*);
175
176void f18() {
177  char *q;
178  char *p = (char *) __builtin_alloca(10);
179  read(p);
180  q = p;
181  q++;
182  if (*q) { // no-warning
183  }
184}
185