xref: /llvm-project/clang/test/Analysis/zero-size-non-pod-array.cpp (revision e3e9082b013ba948e3df6d4a2536df9d04656e76)
1*e3e9082bSisuckatcs // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s
2*e3e9082bSisuckatcs // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
3*e3e9082bSisuckatcs 
4*e3e9082bSisuckatcs void clang_analyzer_eval(bool);
5*e3e9082bSisuckatcs 
6*e3e9082bSisuckatcs struct S{
7*e3e9082bSisuckatcs     static int CtorInvocationCount;
8*e3e9082bSisuckatcs     static int DtorInvocationCount;
9*e3e9082bSisuckatcs 
SS10*e3e9082bSisuckatcs     S(){CtorInvocationCount++;}
~SS11*e3e9082bSisuckatcs     ~S(){DtorInvocationCount++;}
12*e3e9082bSisuckatcs };
13*e3e9082bSisuckatcs 
14*e3e9082bSisuckatcs int S::CtorInvocationCount = 0;
15*e3e9082bSisuckatcs int S::DtorInvocationCount = 0;
16*e3e9082bSisuckatcs 
zeroSizeArrayStack()17*e3e9082bSisuckatcs void zeroSizeArrayStack() {
18*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
19*e3e9082bSisuckatcs 
20*e3e9082bSisuckatcs     S arr[0];
21*e3e9082bSisuckatcs 
22*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
23*e3e9082bSisuckatcs }
24*e3e9082bSisuckatcs 
zeroSizeMultidimensionalArrayStack()25*e3e9082bSisuckatcs void zeroSizeMultidimensionalArrayStack() {
26*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
27*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
28*e3e9082bSisuckatcs 
29*e3e9082bSisuckatcs     {
30*e3e9082bSisuckatcs         S arr[2][0];
31*e3e9082bSisuckatcs         S arr2[0][2];
32*e3e9082bSisuckatcs 
33*e3e9082bSisuckatcs         S arr3[0][2][2];
34*e3e9082bSisuckatcs         S arr4[2][2][0];
35*e3e9082bSisuckatcs         S arr5[2][0][2];
36*e3e9082bSisuckatcs     }
37*e3e9082bSisuckatcs 
38*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
39*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
40*e3e9082bSisuckatcs }
41*e3e9082bSisuckatcs 
zeroSizeArrayStackInLambda()42*e3e9082bSisuckatcs void zeroSizeArrayStackInLambda() {
43*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
44*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
45*e3e9082bSisuckatcs 
46*e3e9082bSisuckatcs     []{
47*e3e9082bSisuckatcs         S arr[0];
48*e3e9082bSisuckatcs     }();
49*e3e9082bSisuckatcs 
50*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
51*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
52*e3e9082bSisuckatcs }
53*e3e9082bSisuckatcs 
zeroSizeArrayHeap()54*e3e9082bSisuckatcs void zeroSizeArrayHeap() {
55*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
56*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
57*e3e9082bSisuckatcs 
58*e3e9082bSisuckatcs     auto *arr = new S[0];
59*e3e9082bSisuckatcs     delete[] arr;
60*e3e9082bSisuckatcs 
61*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
62*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
63*e3e9082bSisuckatcs }
64*e3e9082bSisuckatcs 
zeroSizeMultidimensionalArrayHeap()65*e3e9082bSisuckatcs void zeroSizeMultidimensionalArrayHeap() {
66*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
67*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
68*e3e9082bSisuckatcs 
69*e3e9082bSisuckatcs     auto *arr = new S[2][0];
70*e3e9082bSisuckatcs     delete[] arr;
71*e3e9082bSisuckatcs 
72*e3e9082bSisuckatcs     auto *arr2 = new S[0][2];
73*e3e9082bSisuckatcs     delete[] arr2;
74*e3e9082bSisuckatcs 
75*e3e9082bSisuckatcs     auto *arr3 = new S[0][2][2];
76*e3e9082bSisuckatcs     delete[] arr3;
77*e3e9082bSisuckatcs 
78*e3e9082bSisuckatcs     auto *arr4 = new S[2][2][0];
79*e3e9082bSisuckatcs     delete[] arr4;
80*e3e9082bSisuckatcs 
81*e3e9082bSisuckatcs     auto *arr5 = new S[2][0][2];
82*e3e9082bSisuckatcs     delete[] arr5;
83*e3e9082bSisuckatcs 
84*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
85*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
86*e3e9082bSisuckatcs }
87*e3e9082bSisuckatcs 
88*e3e9082bSisuckatcs #if __cplusplus >= 201703L
89*e3e9082bSisuckatcs 
zeroSizeArrayBinding()90*e3e9082bSisuckatcs void zeroSizeArrayBinding() {
91*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
92*e3e9082bSisuckatcs 
93*e3e9082bSisuckatcs     S arr[0];
94*e3e9082bSisuckatcs 
95*e3e9082bSisuckatcs     // Note: This is an error in gcc but a warning in clang.
96*e3e9082bSisuckatcs     // In MSVC the declaration of 'S arr[0]' is already an error
97*e3e9082bSisuckatcs     // and it doesn't recognize this syntax as a structured binding.
98*e3e9082bSisuckatcs     auto [] = arr; //expected-warning{{ISO C++17 does not allow a decomposition group to be empty}}
99*e3e9082bSisuckatcs 
100*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
101*e3e9082bSisuckatcs }
102*e3e9082bSisuckatcs 
103*e3e9082bSisuckatcs #endif
104*e3e9082bSisuckatcs 
zeroSizeArrayLambdaCapture()105*e3e9082bSisuckatcs void zeroSizeArrayLambdaCapture() {
106*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
107*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
108*e3e9082bSisuckatcs 
109*e3e9082bSisuckatcs     S arr[0];
110*e3e9082bSisuckatcs 
111*e3e9082bSisuckatcs     auto l = [arr]{};
112*e3e9082bSisuckatcs     [arr]{}();
113*e3e9082bSisuckatcs 
114*e3e9082bSisuckatcs     //FIXME: These should be TRUE. We should avoid calling the destructor
115*e3e9082bSisuckatcs     // of the temporary that is materialized as the lambda.
116*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}} expected-warning{{FALSE}}
117*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}} expected-warning{{FALSE}}
118*e3e9082bSisuckatcs }
119*e3e9082bSisuckatcs 
120*e3e9082bSisuckatcs // FIXME: Report a warning if the standard is at least C++17.
121*e3e9082bSisuckatcs #if __cplusplus < 201703L
zeroSizeArrayLambdaCaptureUndefined1()122*e3e9082bSisuckatcs void zeroSizeArrayLambdaCaptureUndefined1() {
123*e3e9082bSisuckatcs     S arr[0];
124*e3e9082bSisuckatcs     int n;
125*e3e9082bSisuckatcs 
126*e3e9082bSisuckatcs     auto l = [arr, n]{
127*e3e9082bSisuckatcs         int x = n; //expected-warning{{Assigned value is garbage or undefined}}
128*e3e9082bSisuckatcs         (void) x;
129*e3e9082bSisuckatcs     };
130*e3e9082bSisuckatcs 
131*e3e9082bSisuckatcs     l();
132*e3e9082bSisuckatcs }
133*e3e9082bSisuckatcs #endif
134*e3e9082bSisuckatcs 
zeroSizeArrayLambdaCaptureUndefined2()135*e3e9082bSisuckatcs void zeroSizeArrayLambdaCaptureUndefined2() {
136*e3e9082bSisuckatcs     S arr[0];
137*e3e9082bSisuckatcs     int n;
138*e3e9082bSisuckatcs 
139*e3e9082bSisuckatcs     [arr, n]{
140*e3e9082bSisuckatcs         int x = n; //expected-warning{{Assigned value is garbage or undefined}}
141*e3e9082bSisuckatcs         (void) x;
142*e3e9082bSisuckatcs     }();
143*e3e9082bSisuckatcs }
144*e3e9082bSisuckatcs 
145*e3e9082bSisuckatcs struct Wrapper{
146*e3e9082bSisuckatcs     S arr[0];
147*e3e9082bSisuckatcs };
148*e3e9082bSisuckatcs 
zeroSizeArrayMember()149*e3e9082bSisuckatcs void zeroSizeArrayMember() {
150*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
151*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
152*e3e9082bSisuckatcs 
153*e3e9082bSisuckatcs     {
154*e3e9082bSisuckatcs         Wrapper W;
155*e3e9082bSisuckatcs     }
156*e3e9082bSisuckatcs 
157*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
158*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
159*e3e9082bSisuckatcs }
160*e3e9082bSisuckatcs 
zeroSizeArrayMemberCopyMove()161*e3e9082bSisuckatcs void zeroSizeArrayMemberCopyMove() {
162*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
163*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
164*e3e9082bSisuckatcs 
165*e3e9082bSisuckatcs     {
166*e3e9082bSisuckatcs         Wrapper W;
167*e3e9082bSisuckatcs         Wrapper W2 = W;
168*e3e9082bSisuckatcs         Wrapper W3 = (Wrapper&&) W2;
169*e3e9082bSisuckatcs     }
170*e3e9082bSisuckatcs 
171*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
172*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
173*e3e9082bSisuckatcs }
174*e3e9082bSisuckatcs 
175*e3e9082bSisuckatcs struct MultiWrapper{
176*e3e9082bSisuckatcs     S arr[2][0];
177*e3e9082bSisuckatcs };
178*e3e9082bSisuckatcs 
zeroSizeMultidimensionalArrayMember()179*e3e9082bSisuckatcs void zeroSizeMultidimensionalArrayMember() {
180*e3e9082bSisuckatcs     S::CtorInvocationCount = 0;
181*e3e9082bSisuckatcs     S::DtorInvocationCount = 0;
182*e3e9082bSisuckatcs 
183*e3e9082bSisuckatcs     {
184*e3e9082bSisuckatcs         MultiWrapper MW;
185*e3e9082bSisuckatcs     }
186*e3e9082bSisuckatcs 
187*e3e9082bSisuckatcs     clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
188*e3e9082bSisuckatcs     clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
189*e3e9082bSisuckatcs }
190