| // 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}} |
| } |