190 lines
4.6 KiB
C++
190 lines
4.6 KiB
C++
// 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}}
|
|
}
|