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