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()17void zeroSizeArrayStack() { 18 S::CtorInvocationCount = 0; 19 20 S arr[0]; 21 22 clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}} 23 } 24 zeroSizeMultidimensionalArrayStack()25void 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()42void 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()54void 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()65void 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()90void 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()105void 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()122void 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()135void 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()149void 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()161void 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()179void 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