[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
This revision was automatically updated to reflect the committed changes. Closed by commit rC333417: [analyzer] const init: handle non-explicit cases more accurately (authored by r.stahl, committed by ). Repository: rC Clang https://reviews.llvm.org/D46823 Files: lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/initialization.c test/Analysis/initialization.cpp Index: lib/StaticAnalyzer/Core/RegionStore.cpp === --- lib/StaticAnalyzer/Core/RegionStore.cpp +++ lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1638,9 +1638,18 @@ // The array index has to be known. if (auto CI = R->getIndex().getAs()) { int64_t i = CI->getValue().getSExtValue(); -// Return unknown value if index is out of bounds. -if (i < 0 || i >= InitList->getNumInits()) - return UnknownVal(); +// If it is known that the index is out of bounds, we can return +// an undefined value. +if (i < 0) + return UndefinedVal(); + +if (auto CAT = Ctx.getAsConstantArrayType(VD->getType())) + if (CAT->getSize().sle(i)) +return UndefinedVal(); + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); if (const Expr *ElemInit = InitList->getInit(i)) if (Optional V = svalBuilder.getConstantVal(ElemInit)) @@ -1715,11 +1724,15 @@ // Either the record variable or the field has to be const qualified. if (RecordVarTy.isConstQualified() || Ty.isConstQualified()) if (const Expr *Init = VD->getInit()) -if (const auto *InitList = dyn_cast(Init)) - if (Index < InitList->getNumInits()) +if (const auto *InitList = dyn_cast(Init)) { + if (Index < InitList->getNumInits()) { if (const Expr *FieldInit = InitList->getInit(Index)) if (Optional V = svalBuilder.getConstantVal(FieldInit)) return *V; + } else { +return svalBuilder.makeZeroVal(Ty); + } +} } return getBindingForFieldOrElementCommon(B, R, Ty); Index: test/Analysis/initialization.c === --- test/Analysis/initialization.c +++ test/Analysis/initialization.c @@ -1,7 +1,28 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); void initbug() { const union { float a; } u = {}; (void)u.a; // no-crash } + +int const parr[2] = {1}; +void constarr() { + int i = 2; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} + i = 1; + clang_analyzer_eval(parr[i] == 0); // expected-warning{{TRUE}} + i = -1; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} +} + +struct SM { + int a; + int b; +}; +const struct SM sm = {.a = 1}; +void multinit() { + clang_analyzer_eval(sm.a == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(sm.b == 0); // expected-warning{{TRUE}} +} Index: test/Analysis/initialization.cpp === --- test/Analysis/initialization.cpp +++ test/Analysis/initialization.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); + +struct S { + int a = 3; +}; +S const sarr[2] = {}; +void definit() { + int i = 1; + // FIXME: Should recognize that it is 3. + clang_analyzer_eval(sarr[i].a); // expected-warning{{UNKNOWN}} +} + +int const arr[2][2] = {}; +void arr2init() { + int i = 1; + // FIXME: Should recognize that it is 0. + clang_analyzer_eval(arr[i][0]); // expected-warning{{UNKNOWN}} +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
r.stahl updated this revision to Diff 148809. r.stahl added a comment. Added FIXME tests. I know my example didn't exercise your scenario, but it was the only one I could think of where returning zero would have been straight up wrong. Note that I default initialized `a` to 3 there, so `sarr` is not just zero-initialized. I do not have access yet, but applied today! https://reviews.llvm.org/D46823 Files: lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/initialization.c test/Analysis/initialization.cpp Index: test/Analysis/initialization.cpp === --- test/Analysis/initialization.cpp +++ test/Analysis/initialization.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); + +struct S { + int a = 3; +}; +S const sarr[2] = {}; +void definit() { + int i = 1; + // FIXME: Should recognize that it is 3. + clang_analyzer_eval(sarr[i].a); // expected-warning{{UNKNOWN}} +} + +int const arr[2][2] = {}; +void arr2init() { + int i = 1; + // FIXME: Should recognize that it is 0. + clang_analyzer_eval(arr[i][0]); // expected-warning{{UNKNOWN}} +} Index: test/Analysis/initialization.c === --- test/Analysis/initialization.c +++ test/Analysis/initialization.c @@ -1,7 +1,28 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); void initbug() { const union { float a; } u = {}; (void)u.a; // no-crash } + +int const parr[2] = {1}; +void constarr() { + int i = 2; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} + i = 1; + clang_analyzer_eval(parr[i] == 0); // expected-warning{{TRUE}} + i = -1; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} +} + +struct SM { + int a; + int b; +}; +const struct SM sm = {.a = 1}; +void multinit() { + clang_analyzer_eval(sm.a == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(sm.b == 0); // expected-warning{{TRUE}} +} Index: lib/StaticAnalyzer/Core/RegionStore.cpp === --- lib/StaticAnalyzer/Core/RegionStore.cpp +++ lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1638,9 +1638,18 @@ // The array index has to be known. if (auto CI = R->getIndex().getAs()) { int64_t i = CI->getValue().getSExtValue(); -// Return unknown value if index is out of bounds. -if (i < 0 || i >= InitList->getNumInits()) - return UnknownVal(); +// If it is known that the index is out of bounds, we can return +// an undefined value. +if (i < 0) + return UndefinedVal(); + +if (auto CAT = Ctx.getAsConstantArrayType(VD->getType())) + if (CAT->getSize().sle(i)) +return UndefinedVal(); + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); if (const Expr *ElemInit = InitList->getInit(i)) if (Optional V = svalBuilder.getConstantVal(ElemInit)) @@ -1715,11 +1724,15 @@ // Either the record variable or the field has to be const qualified. if (RecordVarTy.isConstQualified() || Ty.isConstQualified()) if (const Expr *Init = VD->getInit()) -if (const auto *InitList = dyn_cast(Init)) - if (Index < InitList->getNumInits()) +if (const auto *InitList = dyn_cast(Init)) { + if (Index < InitList->getNumInits()) { if (const Expr *FieldInit = InitList->getInit(Index)) if (Optional V = svalBuilder.getConstantVal(FieldInit)) return *V; + } else { +return svalBuilder.makeZeroVal(Ty); + } +} } return getBindingForFieldOrElementCommon(B, R, Ty); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
NoQ accepted this revision. NoQ added a comment. This revision is now accepted and ready to land. Looks good! Do you have commit access? I think you should get commit access. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650 + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) r.stahl wrote: > r.stahl wrote: > > NoQ wrote: > > > NoQ wrote: > > > > Would this work correctly if the element is not of an integral or > > > > enumeration type? I think this needs an explicit check. > > > What if we have an out-of-bounds access to a variable-length array? I > > > don't think it'd yield zero. > > I'm getting "variable-sized object may not be initialized", so this case > > should not be possible. > I'm having a hard time reproducing this either. > > > ``` > struct S { > int a = 3; > }; > S const sarr[2] = {}; > void definit() { > int i = 1; > clang_analyzer_dump(sarr[i].a); // expected-warning{{test}} > } > ``` > > results in a symbolic value, because makeZeroVal returns an empty SVal list > for arrays, records, vectors and complex types. Otherwise it just returns > UnknownVal (for example for not-yet-implemented floats). > > Can you think of a case where this would be an issue? Yup, sounds reasonable. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650-1652 +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); NoQ wrote: > r.stahl wrote: > > r.stahl wrote: > > > NoQ wrote: > > > > NoQ wrote: > > > > > Would this work correctly if the element is not of an integral or > > > > > enumeration type? I think this needs an explicit check. > > > > What if we have an out-of-bounds access to a variable-length array? I > > > > don't think it'd yield zero. > > > I'm getting "variable-sized object may not be initialized", so this case > > > should not be possible. > > I'm having a hard time reproducing this either. > > > > > > ``` > > struct S { > > int a = 3; > > }; > > S const sarr[2] = {}; > > void definit() { > > int i = 1; > > clang_analyzer_dump(sarr[i].a); // expected-warning{{test}} > > } > > ``` > > > > results in a symbolic value, because makeZeroVal returns an empty SVal list > > for arrays, records, vectors and complex types. Otherwise it just returns > > UnknownVal (for example for not-yet-implemented floats). > > > > Can you think of a case where this would be an issue? > Yup, sounds reasonable. Had a look. This indeed looks fine, but for a completely different reason. In fact structs don't appear in `getBindingForElement()` because they all go through `getBindingForStruct()` instead. Hopefully this does take care of other cornercases. So your test case doesn't even trigger your code to be executed, neither would `S s = sarr[i]; clang_analyzer_dump(s.a);`. Still, as far as i understand, `sarr` here should be zero-initialized, so i think the symbolic value can be improved upon, so we might as well add this as a FIXME test. https://reviews.llvm.org/D46823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
r.stahl added inline comments. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650 + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) NoQ wrote: > NoQ wrote: > > Would this work correctly if the element is not of an integral or > > enumeration type? I think this needs an explicit check. > What if we have an out-of-bounds access to a variable-length array? I don't > think it'd yield zero. I'm getting "variable-sized object may not be initialized", so this case should not be possible. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650-1652 +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); r.stahl wrote: > NoQ wrote: > > NoQ wrote: > > > Would this work correctly if the element is not of an integral or > > > enumeration type? I think this needs an explicit check. > > What if we have an out-of-bounds access to a variable-length array? I don't > > think it'd yield zero. > I'm getting "variable-sized object may not be initialized", so this case > should not be possible. I'm having a hard time reproducing this either. ``` struct S { int a = 3; }; S const sarr[2] = {}; void definit() { int i = 1; clang_analyzer_dump(sarr[i].a); // expected-warning{{test}} } ``` results in a symbolic value, because makeZeroVal returns an empty SVal list for arrays, records, vectors and complex types. Otherwise it just returns UnknownVal (for example for not-yet-implemented floats). Can you think of a case where this would be an issue? https://reviews.llvm.org/D46823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
r.stahl updated this revision to Diff 146809. r.stahl marked 2 inline comments as done. r.stahl added a comment. updated test https://reviews.llvm.org/D46823 Files: lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/initialization.c Index: test/Analysis/initialization.c === --- test/Analysis/initialization.c +++ test/Analysis/initialization.c @@ -1,7 +1,28 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); void initbug() { const union { float a; } u = {}; (void)u.a; // no-crash } + +int const parr[2] = {1}; +void constarr() { + int i = 2; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} + i = 1; + clang_analyzer_eval(parr[i] == 0); // expected-warning{{TRUE}} + i = -1; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} +} + +struct SM { + int a; + int b; +}; +const struct SM sm = {.a = 1}; +void multinit() { + clang_analyzer_eval(sm.a == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(sm.b == 0); // expected-warning{{TRUE}} +} Index: lib/StaticAnalyzer/Core/RegionStore.cpp === --- lib/StaticAnalyzer/Core/RegionStore.cpp +++ lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1638,9 +1638,18 @@ // The array index has to be known. if (auto CI = R->getIndex().getAs()) { int64_t i = CI->getValue().getSExtValue(); -// Return unknown value if index is out of bounds. -if (i < 0 || i >= InitList->getNumInits()) - return UnknownVal(); +// If it is known that the index is out of bounds, we can return +// an undefined value. +if (i < 0) + return UndefinedVal(); + +if (auto CAT = Ctx.getAsConstantArrayType(VD->getType())) + if (CAT->getSize().sle(i)) +return UndefinedVal(); + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); if (const Expr *ElemInit = InitList->getInit(i)) if (Optional V = svalBuilder.getConstantVal(ElemInit)) @@ -1715,11 +1724,15 @@ // Either the record variable or the field has to be const qualified. if (RecordVarTy.isConstQualified() || Ty.isConstQualified()) if (const Expr *Init = VD->getInit()) -if (const auto *InitList = dyn_cast(Init)) - if (Index < InitList->getNumInits()) +if (const auto *InitList = dyn_cast(Init)) { + if (Index < InitList->getNumInits()) { if (const Expr *FieldInit = InitList->getInit(Index)) if (Optional V = svalBuilder.getConstantVal(FieldInit)) return *V; + } else { +return svalBuilder.makeZeroVal(Ty); + } +} } return getBindingForFieldOrElementCommon(B, R, Ty); Index: test/Analysis/initialization.c === --- test/Analysis/initialization.c +++ test/Analysis/initialization.c @@ -1,7 +1,28 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_eval(int); void initbug() { const union { float a; } u = {}; (void)u.a; // no-crash } + +int const parr[2] = {1}; +void constarr() { + int i = 2; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} + i = 1; + clang_analyzer_eval(parr[i] == 0); // expected-warning{{TRUE}} + i = -1; + clang_analyzer_eval(parr[i]); // expected-warning{{UNDEFINED}} +} + +struct SM { + int a; + int b; +}; +const struct SM sm = {.a = 1}; +void multinit() { + clang_analyzer_eval(sm.a == 1); // expected-warning{{TRUE}} + clang_analyzer_eval(sm.b == 0); // expected-warning{{TRUE}} +} Index: lib/StaticAnalyzer/Core/RegionStore.cpp === --- lib/StaticAnalyzer/Core/RegionStore.cpp +++ lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1638,9 +1638,18 @@ // The array index has to be known. if (auto CI = R->getIndex().getAs()) { int64_t i = CI->getValue().getSExtValue(); -// Return unknown value if index is out of bounds. -if (i < 0 || i >= InitList->getNumInits()) - return UnknownVal(); +// If it is known that the index is out of bounds, we can return +// an undefined value. +if (i < 0) + return UndefinedVal(); + +if (auto CAT = Ctx.getAsConstantArrayType(VD->getType()))
[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
NoQ added a comment. Yay thanks! I think some cornercases would need to be dealt with. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650 + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) NoQ wrote: > Would this work correctly if the element is not of an integral or enumeration > type? I think this needs an explicit check. What if we have an out-of-bounds access to a variable-length array? I don't think it'd yield zero. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650-1652 +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); Would this work correctly if the element is not of an integral or enumeration type? I think this needs an explicit check. Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1733 + } else { +return svalBuilder.makeZeroVal(Ty); + } Same: would this work correctly if the field is not of an integral or enumeration type? Comment at: test/Analysis/initialization.c:3 + +void clang_analyzer_dump(int); We try to avoid using `dump()` on tests because it makes tests test the dump syntax, which isn't the point. For checking constants, it's easier to do something like `clang_analyzer_eval(parr[i] == 2); // expected-warning{{TRUE}}`. For finding undefined values, you can enable `core.uninitialized` checkers and receive warnings when the argument of `clang_analyzer_eval` is an uninitialized value. Or just increment the value. Repository: rC Clang https://reviews.llvm.org/D46823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately
r.stahl created this revision. r.stahl added reviewers: NoQ, xazax.hun, george.karpenkov. Herald added subscribers: cfe-commits, a.sidorin, rnkovacs, szepet. If the access is out of bounds, return UndefinedVal. If it is missing an explicit init, return the implicit zero value it must have. Repository: rC Clang https://reviews.llvm.org/D46823 Files: lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/initialization.c Index: test/Analysis/initialization.c === --- test/Analysis/initialization.c +++ test/Analysis/initialization.c @@ -1,7 +1,28 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_dump(int); void initbug() { const union { float a; } u = {}; (void)u.a; // no-crash } + +int const parr[2] = {1}; +void constarr() { + int i = 2; + clang_analyzer_dump(parr[i]); // expected-warning{{Undefined}} + i = 1; + clang_analyzer_dump(parr[i]); // expected-warning{{0 S32b}} + i = -1; + clang_analyzer_dump(parr[i]); // expected-warning{{Undefined}} +} + +struct SM { + int a; + int b; +}; +const struct SM sm = {.a = 1}; +void multinit() { + clang_analyzer_dump(sm.a); // expected-warning{{1 S32b}} + clang_analyzer_dump(sm.b); // expected-warning{{0 S32b}} +} Index: lib/StaticAnalyzer/Core/RegionStore.cpp === --- lib/StaticAnalyzer/Core/RegionStore.cpp +++ lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1638,9 +1638,18 @@ // The array index has to be known. if (auto CI = R->getIndex().getAs()) { int64_t i = CI->getValue().getSExtValue(); -// Return unknown value if index is out of bounds. -if (i < 0 || i >= InitList->getNumInits()) - return UnknownVal(); +// If it is known that the index is out of bounds, we can return +// an undefined value. +if (i < 0) + return UndefinedVal(); + +if (auto CAT = Ctx.getAsConstantArrayType(VD->getType())) + if (CAT->getSize().sle(i)) +return UndefinedVal(); + +// If there is a list, but no init, it must be zero. +if (i >= InitList->getNumInits()) + return svalBuilder.makeZeroVal(R->getElementType()); if (const Expr *ElemInit = InitList->getInit(i)) if (Optional V = svalBuilder.getConstantVal(ElemInit)) @@ -1715,11 +1724,15 @@ // Either the record variable or the field has to be const qualified. if (RecordVarTy.isConstQualified() || Ty.isConstQualified()) if (const Expr *Init = VD->getInit()) -if (const auto *InitList = dyn_cast(Init)) - if (Index < InitList->getNumInits()) +if (const auto *InitList = dyn_cast(Init)) { + if (Index < InitList->getNumInits()) { if (const Expr *FieldInit = InitList->getInit(Index)) if (Optional V = svalBuilder.getConstantVal(FieldInit)) return *V; + } else { +return svalBuilder.makeZeroVal(Ty); + } +} } return getBindingForFieldOrElementCommon(B, R, Ty); Index: test/Analysis/initialization.c === --- test/Analysis/initialization.c +++ test/Analysis/initialization.c @@ -1,7 +1,28 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s + +void clang_analyzer_dump(int); void initbug() { const union { float a; } u = {}; (void)u.a; // no-crash } + +int const parr[2] = {1}; +void constarr() { + int i = 2; + clang_analyzer_dump(parr[i]); // expected-warning{{Undefined}} + i = 1; + clang_analyzer_dump(parr[i]); // expected-warning{{0 S32b}} + i = -1; + clang_analyzer_dump(parr[i]); // expected-warning{{Undefined}} +} + +struct SM { + int a; + int b; +}; +const struct SM sm = {.a = 1}; +void multinit() { + clang_analyzer_dump(sm.a); // expected-warning{{1 S32b}} + clang_analyzer_dump(sm.b); // expected-warning{{0 S32b}} +} Index: lib/StaticAnalyzer/Core/RegionStore.cpp === --- lib/StaticAnalyzer/Core/RegionStore.cpp +++ lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1638,9 +1638,18 @@ // The array index has to be known. if (auto CI = R->getIndex().getAs()) { int64_t i = CI->getValue().getSExtValue(); -// Return unknown value if index is out of bounds. -if (i < 0 || i >= InitList->getNumInits()) - return UnknownVal(); +// If it is known that the index is out of bounds, we can