summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Stahl <r.stahl@tum.de>2018-05-29 14:14:22 +0000
committerRafael Stahl <r.stahl@tum.de>2018-05-29 14:14:22 +0000
commit0137aa8679d6675b2440c1e19943b23cee4dc794 (patch)
treec7659e120ba6d9bdabab409664555a469217fb9b
parent48bf43df8a92057feaad1142d0e251f7a160ab12 (diff)
downloadbcm5719-llvm-0137aa8679d6675b2440c1e19943b23cee4dc794.tar.gz
bcm5719-llvm-0137aa8679d6675b2440c1e19943b23cee4dc794.zip
[analyzer] const init: handle non-explicit cases more accurately
Summary: If the access is out of bounds, return UndefinedVal. If it is missing an explicit init, return the implicit zero value it must have. Reviewers: NoQ, xazax.hun, george.karpenkov Reviewed By: NoQ Subscribers: szepet, rnkovacs, a.sidorin, cfe-commits Differential Revision: https://reviews.llvm.org/D46823 llvm-svn: 333417
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp23
-rw-r--r--clang/test/Analysis/initialization.c25
-rw-r--r--clang/test/Analysis/initialization.cpp20
3 files changed, 61 insertions, 7 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index be4b5aa9189..acb6eeab8d9 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1638,9 +1638,18 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
// The array index has to be known.
if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
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<SVal> V = svalBuilder.getConstantVal(ElemInit))
@@ -1715,11 +1724,15 @@ SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
// 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<InitListExpr>(Init))
- if (Index < InitList->getNumInits())
+ if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
+ if (Index < InitList->getNumInits()) {
if (const Expr *FieldInit = InitList->getInit(Index))
if (Optional<SVal> V = svalBuilder.getConstantVal(FieldInit))
return *V;
+ } else {
+ return svalBuilder.makeZeroVal(Ty);
+ }
+ }
}
return getBindingForFieldOrElementCommon(B, R, Ty);
diff --git a/clang/test/Analysis/initialization.c b/clang/test/Analysis/initialization.c
index a6fe9be2b70..c1d6361f124 100644
--- a/clang/test/Analysis/initialization.c
+++ b/clang/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}}
+}
diff --git a/clang/test/Analysis/initialization.cpp b/clang/test/Analysis/initialization.cpp
new file mode 100644
index 00000000000..db765930b6e
--- /dev/null
+++ b/clang/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}}
+}
OpenPOWER on IntegriCloud