xref: /llvm-project/clang/test/Analysis/flexible-array-members.c (revision 12559064e05a11e8418425de59d8745f0cfb1122)
1 // -fstrict-flex-arrays=2 means that only undefined or zero element arrays are considered as FAMs.
2 
3 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c90 \
4 // RUN:    -fstrict-flex-arrays=2
5 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c99 \
6 // RUN:    -fstrict-flex-arrays=2
7 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c11 \
8 // RUN:    -fstrict-flex-arrays=2
9 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c17 \
10 // RUN:    -fstrict-flex-arrays=2
11 
12 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++98 -x c++ \
13 // RUN:    -fstrict-flex-arrays=2
14 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++03 -x c++ \
15 // RUN:    -fstrict-flex-arrays=2
16 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++11 -x c++ \
17 // RUN:    -fstrict-flex-arrays=2
18 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++14 -x c++ \
19 // RUN:    -fstrict-flex-arrays=2
20 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++17 -x c++ \
21 // RUN:    -fstrict-flex-arrays=2
22 
23 // By default, -fstrict-flex-arrays=0, which means that even single element arrays are considered as FAMs.
24 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c17 \
25 // RUN:    -DSINGLE_ELEMENT_FAMS
26 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++17 -x c++ \
27 // RUN:    -DSINGLE_ELEMENT_FAMS
28 
29 typedef __typeof(sizeof(int)) size_t;
30 size_t clang_analyzer_getExtent(void *);
31 void clang_analyzer_dump(size_t);
32 
33 void *alloca(size_t size);
34 void *malloc(size_t size);
35 void free(void *ptr);
36 
test_incomplete_array_fam(void)37 void test_incomplete_array_fam(void) {
38   typedef struct FAM {
39     char c;
40     int data[];
41   } FAM;
42 
43   FAM fam;
44   clang_analyzer_dump(clang_analyzer_getExtent(&fam));
45   clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
46   // expected-warning@-2 {{4 S64b}}
47   // expected-warning@-2 {{0 S64b}}
48 
49   FAM *p = (FAM *)alloca(sizeof(FAM));
50   clang_analyzer_dump(clang_analyzer_getExtent(p));
51   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
52   // expected-warning@-2 {{4 S64b}}
53   // expected-warning@-2 {{0 S64b}}
54 
55   FAM *q = (FAM *)malloc(sizeof(FAM));
56   clang_analyzer_dump(clang_analyzer_getExtent(q));
57   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
58   // expected-warning@-2 {{4 S64b}}
59   // expected-warning@-2 {{0 S64b}}
60   free(q);
61 
62   q = (FAM *)malloc(sizeof(FAM) + sizeof(int) * 2);
63   clang_analyzer_dump(clang_analyzer_getExtent(q));
64   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
65   // expected-warning@-2 {{12 S64b}}
66   // expected-warning@-2 {{8 S64b}}
67   free(q);
68 
69   typedef struct __attribute__((packed)) {
70     char c;
71     int data[];
72   } PackedFAM;
73 
74   PackedFAM *t = (PackedFAM *)malloc(sizeof(PackedFAM) + sizeof(int) * 2);
75   clang_analyzer_dump(clang_analyzer_getExtent(t));
76   clang_analyzer_dump(clang_analyzer_getExtent(t->data));
77   // expected-warning@-2 {{9 S64b}}
78   // expected-warning@-2 {{8 S64b}}
79   free(t);
80 }
81 
test_too_small_base(void)82 void test_too_small_base(void) {
83   typedef struct FAM {
84     long c;
85     int data[];
86   } FAM;
87   short s = 0;
88   FAM *p = (FAM *) &s;
89   clang_analyzer_dump(clang_analyzer_getExtent(p));
90   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
91   // expected-warning@-2 {{2 S64b}}
92   // expected-warning@-2 {{-6 S64b}}
93 }
94 
test_zero_length_array_fam(void)95 void test_zero_length_array_fam(void) {
96   typedef struct FAM {
97     char c;
98     int data[0];
99   } FAM;
100 
101   FAM fam;
102   clang_analyzer_dump(clang_analyzer_getExtent(&fam));
103   clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
104   // expected-warning@-2 {{4 S64b}}
105   // expected-warning@-2 {{0 S64b}}
106 
107   FAM *p = (FAM *)alloca(sizeof(FAM));
108   clang_analyzer_dump(clang_analyzer_getExtent(p));
109   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
110   // expected-warning@-2 {{4 S64b}}
111   // expected-warning@-2 {{0 S64b}}
112 
113   FAM *q = (FAM *)malloc(sizeof(FAM));
114   clang_analyzer_dump(clang_analyzer_getExtent(q));
115   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
116   // expected-warning@-2 {{4 S64b}}
117   // expected-warning@-2 {{0 S64b}}
118   free(q);
119 }
120 
test_single_element_array_possible_fam(void)121 void test_single_element_array_possible_fam(void) {
122   typedef struct FAM {
123     char c;
124     int data[1];
125   } FAM;
126 
127 #ifdef SINGLE_ELEMENT_FAMS
128   FAM likely_fam;
129   clang_analyzer_dump(clang_analyzer_getExtent(&likely_fam));
130   clang_analyzer_dump(clang_analyzer_getExtent(likely_fam.data));
131   // expected-warning@-2 {{8 S64b}}
132   // expected-warning@-2 {{4 S64b}}
133 
134   FAM *p = (FAM *)alloca(sizeof(FAM));
135   clang_analyzer_dump(clang_analyzer_getExtent(p));
136   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
137   // expected-warning@-2 {{8 S64b}}
138   // expected-warning@-2 {{4 S64b}}
139 
140   FAM *q = (FAM *)malloc(sizeof(FAM));
141   clang_analyzer_dump(clang_analyzer_getExtent(q));
142   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
143   // expected-warning@-2 {{8 S64b}}
144   // expected-warning@-2 {{4 S64b}}
145   free(q);
146 #else
147   FAM likely_fam;
148   clang_analyzer_dump(clang_analyzer_getExtent(&likely_fam));
149   clang_analyzer_dump(clang_analyzer_getExtent(likely_fam.data));
150   // expected-warning@-2 {{8 S64b}}
151   // expected-warning@-2 {{4 S64b}}
152 
153   FAM *p = (FAM *)alloca(sizeof(FAM));
154   clang_analyzer_dump(clang_analyzer_getExtent(p));
155   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
156   // expected-warning@-2 {{8 S64b}}
157   // expected-warning@-2 {{4 S64b}}
158 
159   FAM *q = (FAM *)malloc(sizeof(FAM));
160   clang_analyzer_dump(clang_analyzer_getExtent(q));
161   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
162   // expected-warning@-2 {{8 S64b}}
163   // expected-warning@-2 {{4 S64b}}
164   free(q);
165 #endif
166 }
167