371 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s2 3void clang_analyzer_eval(bool);4 5void array_init() {6 int arr[] = {1, 2, 3, 4, 5};7 8 auto [a, b, c, d, e] = arr;9 10 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}11 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}12 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}13 clang_analyzer_eval(d == 4); // expected-warning{{TRUE}}14 clang_analyzer_eval(e == 5); // expected-warning{{TRUE}}15}16 17void array_uninit() {18 int arr[5];19 20 auto [a, b, c, d, e] = arr;21 22 int x = e; // expected-warning{{Assigned value is uninitialized}}23}24 25void lambda_init() {26 int arr[] = {1, 2, 3, 4, 5};27 28 auto l = [arr] { return arr[0]; }();29 clang_analyzer_eval(l == 1); // expected-warning{{TRUE}}30 31 l = [arr] { return arr[1]; }();32 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}33 34 l = [arr] { return arr[2]; }();35 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}36 37 l = [arr] { return arr[3]; }();38 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}39 40 l = [arr] { return arr[4]; }();41 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}42}43 44void lambda_uninit() {45 int arr[5];46 47 // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal48 int l = [arr] { return arr[0]; }();49 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}50 51 l = [arr] { return arr[1]; }();52 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}53 54 l = [arr] { return arr[2]; }();55 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}56 57 l = [arr] { return arr[3]; }();58 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}59 60 l = [arr] { return arr[4]; }();61 clang_analyzer_eval(l); // expected-warning{{UNKNOWN}}62}63 64struct S {65 int arr[5];66};67 68void copy_ctor_init() {69 S orig;70 orig.arr[0] = 1;71 orig.arr[1] = 2;72 orig.arr[2] = 3;73 orig.arr[3] = 4;74 orig.arr[4] = 5;75 76 S copy = orig;77 clang_analyzer_eval(copy.arr[0] == 1); // expected-warning{{TRUE}}78 clang_analyzer_eval(copy.arr[1] == 2); // expected-warning{{TRUE}}79 clang_analyzer_eval(copy.arr[2] == 3); // expected-warning{{TRUE}}80 clang_analyzer_eval(copy.arr[3] == 4); // expected-warning{{TRUE}}81 clang_analyzer_eval(copy.arr[4] == 5); // expected-warning{{TRUE}}82}83 84void copy_ctor_uninit() {85 S orig;86 87 S copy = orig;88 89 // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal.90 // If the struct is not considered a small struct, instead of a copy, we store a lazy compound value.91 // As the struct has an array data member, it is not considered small.92 clang_analyzer_eval(copy.arr[0]); // expected-warning{{UNKNOWN}}93 clang_analyzer_eval(copy.arr[1]); // expected-warning{{UNKNOWN}}94 clang_analyzer_eval(copy.arr[2]); // expected-warning{{UNKNOWN}}95 clang_analyzer_eval(copy.arr[3]); // expected-warning{{UNKNOWN}}96 clang_analyzer_eval(copy.arr[4]); // expected-warning{{UNKNOWN}}97}98 99void move_ctor_init() {100 S orig;101 orig.arr[0] = 1;102 orig.arr[1] = 2;103 orig.arr[2] = 3;104 orig.arr[3] = 4;105 orig.arr[4] = 5;106 107 S moved = (S &&) orig;108 109 clang_analyzer_eval(moved.arr[0] == 1); // expected-warning{{TRUE}}110 clang_analyzer_eval(moved.arr[1] == 2); // expected-warning{{TRUE}}111 clang_analyzer_eval(moved.arr[2] == 3); // expected-warning{{TRUE}}112 clang_analyzer_eval(moved.arr[3] == 4); // expected-warning{{TRUE}}113 clang_analyzer_eval(moved.arr[4] == 5); // expected-warning{{TRUE}}114}115 116void move_ctor_uninit() {117 S orig;118 119 S moved = (S &&) orig;120 121 // FIXME: These should be Undefined, but we fail to read Undefined from a lazyCompoundVal.122 clang_analyzer_eval(moved.arr[0]); // expected-warning{{UNKNOWN}}123 clang_analyzer_eval(moved.arr[1]); // expected-warning{{UNKNOWN}}124 clang_analyzer_eval(moved.arr[2]); // expected-warning{{UNKNOWN}}125 clang_analyzer_eval(moved.arr[3]); // expected-warning{{UNKNOWN}}126 clang_analyzer_eval(moved.arr[4]); // expected-warning{{UNKNOWN}}127}128 129// The struct has a user defined copy and move ctor, which allow us to130// track the values more precisely when an array of this struct is being131// copy/move initialized by ArrayInitLoopExpr.132struct S2 {133 inline static int c = 0;134 int i;135 136 S2() : i(++c) {}137 138 S2(const S2 ©) {139 i = copy.i + 1;140 }141 142 S2(S2 &&move) {143 i = move.i + 2;144 }145};146 147void array_init_non_pod() {148 S2::c = 0;149 S2 arr[4];150 151 auto [a, b, c, d] = arr;152 153 clang_analyzer_eval(a.i == 2); // expected-warning{{TRUE}}154 clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}}155 clang_analyzer_eval(c.i == 4); // expected-warning{{TRUE}}156 clang_analyzer_eval(d.i == 5); // expected-warning{{TRUE}}157}158 159struct S3 {160 int i;161};162 163// The duplicate is required to emit a warning at 2 different places. 164struct S3_duplicate {165 int i;166};167 168void array_uninit_non_pod() {169 S3 arr[1];170 171 auto [a] = arr; // expected-warning@159{{ in implicit constructor is uninitialized}}172}173 174void lambda_init_non_pod() {175 S2::c = 0;176 S2 arr[4];177 178 auto l = [arr] { return arr[0].i; }();179 clang_analyzer_eval(l == 2); // expected-warning{{TRUE}}180 181 l = [arr] { return arr[1].i; }();182 clang_analyzer_eval(l == 3); // expected-warning{{TRUE}}183 184 l = [arr] { return arr[2].i; }();185 clang_analyzer_eval(l == 4); // expected-warning{{TRUE}}186 187 l = [arr] { return arr[3].i; }();188 clang_analyzer_eval(l == 5); // expected-warning{{TRUE}}189}190 191void lambda_uninit_non_pod() {192 S3_duplicate arr[4];193 194 int l = [arr] { return arr[3].i; }(); // expected-warning@164{{ in implicit constructor is uninitialized }}195}196 197// If this struct is being copy/move constructed by the implicit ctors, ArrayInitLoopExpr198// is responsible for the initialization of 'arr' by copy/move constructing each of the199// elements.200struct S5 {201 S2 arr[4];202};203 204void copy_ctor_init_non_pod() {205 S2::c = 0;206 S5 orig;207 208 S5 copy = orig;209 clang_analyzer_eval(copy.arr[0].i == 2); // expected-warning{{TRUE}}210 clang_analyzer_eval(copy.arr[1].i == 3); // expected-warning{{TRUE}}211 clang_analyzer_eval(copy.arr[2].i == 4); // expected-warning{{TRUE}}212 clang_analyzer_eval(copy.arr[3].i == 5); // expected-warning{{TRUE}}213}214 215void move_ctor_init_non_pod() {216 S2::c = 0;217 S5 orig;218 219 S5 moved = (S5 &&) orig;220 221 clang_analyzer_eval(moved.arr[0].i == 3); // expected-warning{{TRUE}}222 clang_analyzer_eval(moved.arr[1].i == 4); // expected-warning{{TRUE}}223 clang_analyzer_eval(moved.arr[2].i == 5); // expected-warning{{TRUE}}224 clang_analyzer_eval(moved.arr[3].i == 6); // expected-warning{{TRUE}}225}226 227//Note: This is the only solution I could find to check the values without 228// crashing clang. For more details on the crash see Issue #57135.229void lambda_capture_multi_array() {230 S3 arr[2][2] = {1,2,3,4};231 232 {233 int x = [arr] { return arr[0][0].i; }();234 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}235 }236 237 {238 int x = [arr] { return arr[0][1].i; }();239 clang_analyzer_eval(x == 2); // expected-warning{{TRUE}}240 }241 242 {243 int x = [arr] { return arr[1][0].i; }();244 clang_analyzer_eval(x == 3); // expected-warning{{TRUE}}245 }246 247 {248 int x = [arr] { return arr[1][1].i; }();249 clang_analyzer_eval(x == 4); // expected-warning{{TRUE}}250 }251}252 253// This struct will force constructor inlining in MultiWrapper.254struct UserDefinedCtor {255 int i;256 UserDefinedCtor() {}257 UserDefinedCtor(const UserDefinedCtor ©) {258 int j = 1;259 i = copy.i;260 }261};262 263struct MultiWrapper {264 UserDefinedCtor arr[2][2];265};266 267void copy_ctor_multi() {268 MultiWrapper MW;269 270 MW.arr[0][0].i = 0;271 MW.arr[0][1].i = 1;272 MW.arr[1][0].i = 2;273 MW.arr[1][1].i = 3;274 275 MultiWrapper MWCopy = MW;276 277 clang_analyzer_eval(MWCopy.arr[0][0].i == 0); // expected-warning{{TRUE}}278 clang_analyzer_eval(MWCopy.arr[0][1].i == 1); // expected-warning{{TRUE}}279 clang_analyzer_eval(MWCopy.arr[1][0].i == 2); // expected-warning{{TRUE}}280 clang_analyzer_eval(MWCopy.arr[1][1].i == 3); // expected-warning{{TRUE}}281} 282 283void move_ctor_multi() {284 MultiWrapper MW;285 286 MW.arr[0][0].i = 0;287 MW.arr[0][1].i = 1;288 MW.arr[1][0].i = 2;289 MW.arr[1][1].i = 3;290 291 MultiWrapper MWMove = (MultiWrapper &&) MW;292 293 clang_analyzer_eval(MWMove.arr[0][0].i == 0); // expected-warning{{TRUE}}294 clang_analyzer_eval(MWMove.arr[0][1].i == 1); // expected-warning{{TRUE}}295 clang_analyzer_eval(MWMove.arr[1][0].i == 2); // expected-warning{{TRUE}}296 clang_analyzer_eval(MWMove.arr[1][1].i == 3); // expected-warning{{TRUE}}297} 298 299void structured_binding_multi() {300 S3 arr[2][2] = {1,2,3,4};301 302 auto [a,b] = arr;303 304 clang_analyzer_eval(a[0].i == 1); // expected-warning{{TRUE}}305 clang_analyzer_eval(a[1].i == 2); // expected-warning{{TRUE}}306 clang_analyzer_eval(b[0].i == 3); // expected-warning{{TRUE}}307 clang_analyzer_eval(b[1].i == 4); // expected-warning{{TRUE}}308}309 310// This snippet used to crash311namespace crash {312 313struct S314{315 int x;316 S() { x = 1; }317};318 319void no_crash() {320 S arr[0];321 int n = 1;322 323 auto l = [arr, n] { return n; };324 325 int x = l();326 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}327 328 // FIXME: This should be 'Undefined'.329 clang_analyzer_eval(arr[0].x); // expected-warning{{UNKNOWN}}330}331 332} // namespace crash333 334namespace array_subscript_initializer {335struct S {336 int x;337};338 339void no_crash() {340 S arr[][2] = {{1, 2}};341 342 const auto [a, b] = arr[0]; // no-crash343 344 clang_analyzer_eval(a.x == 1); // expected-warning{{TRUE}}345 clang_analyzer_eval(b.x == 2); // expected-warning{{TRUE}}346}347} // namespace array_subscript_initializer348 349namespace iterator_initializer {350struct S {351 int x;352};353 354void no_crash() {355 S arr[][2] = {{1, 2}, {3, 4}};356 357 int i = 0;358 for (const auto [a, b] : arr) { // no-crash359 if (i == 0) {360 clang_analyzer_eval(a.x == 1); // expected-warning{{TRUE}}361 clang_analyzer_eval(b.x == 2); // expected-warning{{TRUE}}362 } else {363 clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}}364 clang_analyzer_eval(b.x == 4); // expected-warning{{TRUE}}365 }366 367 ++i;368 }369}370} // namespace iterator_initializer371