// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
void clang_analyzer_eval(bool);
struct S{
static int CtorInvocationCount;
static int DtorInvocationCount;
S(){CtorInvocationCount++;}
~S(){DtorInvocationCount++;}
};
int S::CtorInvocationCount = 0;
int S::DtorInvocationCount = 0;
void zeroSizeArrayStack() {
S::CtorInvocationCount = 0;
S arr[0];
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
}
void zeroSizeMultidimensionalArrayStack() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
{
S arr[2][0];
S arr2[0][2];
S arr3[0][2][2];
S arr4[2][2][0];
S arr5[2][0][2];
}
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}
void zeroSizeArrayStackInLambda() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
[]{
S arr[0];
}();
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}
void zeroSizeArrayHeap() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
auto *arr = new S[0];
delete[] arr;
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}
void zeroSizeMultidimensionalArrayHeap() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
auto *arr = new S[2][0];
delete[] arr;
auto *arr2 = new S[0][2];
delete[] arr2;
auto *arr3 = new S[0][2][2];
delete[] arr3;
auto *arr4 = new S[2][2][0];
delete[] arr4;
auto *arr5 = new S[2][0][2];
delete[] arr5;
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}
#if __cplusplus >= 201703L
void zeroSizeArrayBinding() {
S::CtorInvocationCount = 0;
S arr[0];
// Note: This is an error in gcc but a warning in clang.
// In MSVC the declaration of 'S arr[0]' is already an error
// and it doesn't recognize this syntax as a structured binding.
auto [] = arr; //expected-warning{{ISO C++17 does not allow a decomposition group to be empty}}
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
}
#endif
void zeroSizeArrayLambdaCapture() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
S arr[0];
auto l = [arr]{};
[arr]{}();
//FIXME: These should be TRUE. We should avoid calling the destructor
// of the temporary that is materialized as the lambda.
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}} expected-warning{{FALSE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}} expected-warning{{FALSE}}
}
// FIXME: Report a warning if the standard is at least C++17.
#if __cplusplus < 201703L
void zeroSizeArrayLambdaCaptureUndefined1() {
S arr[0];
int n;
auto l = [arr, n]{
int x = n; //expected-warning{{Assigned value is garbage or undefined}}
(void) x;
};
l();
}
#endif
void zeroSizeArrayLambdaCaptureUndefined2() {
S arr[0];
int n;
[arr, n]{
int x = n; //expected-warning{{Assigned value is garbage or undefined}}
(void) x;
}();
}
struct Wrapper{
S arr[0];
};
void zeroSizeArrayMember() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
{
Wrapper W;
}
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}
void zeroSizeArrayMemberCopyMove() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
{
Wrapper W;
Wrapper W2 = W;
Wrapper W3 = (Wrapper&&) W2;
}
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}
struct MultiWrapper{
S arr[2][0];
};
void zeroSizeMultidimensionalArrayMember() {
S::CtorInvocationCount = 0;
S::DtorInvocationCount = 0;
{
MultiWrapper MW;
}
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
clang_analyzer_eval(S::DtorInvocationCount == 0); //expected-warning{{TRUE}}
}