Relax CFG assertions in UninitializedValuesV2 when
handling pseudo-path sensitivity, and instead
use those assertion conditions as dynamic checks.
These assertions would be violated when analyzing
a CFG where some branches where optimized away
during CFG construction because their branch
conditions could be trivially determined.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123943 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/UninitializedValuesV2.cpp b/lib/Analysis/UninitializedValuesV2.cpp
index 55769bd..121dcf9 100644
--- a/lib/Analysis/UninitializedValuesV2.cpp
+++ b/lib/Analysis/UninitializedValuesV2.cpp
@@ -156,7 +156,7 @@
llvm::BitVector &CFGBlockValues::getBitVector(const CFGBlock *block,
const CFGBlock *dstBlock) {
unsigned idx = block->getBlockID();
- if (dstBlock && block->succ_size() == 2) {
+ if (dstBlock && block->succ_size() == 2 && block->pred_size() == 2) {
assert(block->getTerminator());
if (getLogicalOperatorInChain(block)) {
if (*block->succ_begin() == dstBlock)
@@ -460,20 +460,19 @@
UninitVariablesHandler *handler = 0) {
if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
- assert(block->pred_size() == 2);
- assert(block->succ_size() == 2);
- assert(block->getTerminatorCondition() == b);
-
- BVPair valsAB = vals.getPredBitVectors(block);
- vals.mergeIntoScratch(*valsAB.first, true);
- vals.mergeIntoScratch(*valsAB.second, false);
- valsAB.second = &vals.getScratch();
- if (b->getOpcode() == BO_LOr) {
- // Ensure the invariant that 'first' corresponds to the true
- // branch and 'second' to the false.
- std::swap(valsAB.first, valsAB.second);
+ if (block->pred_size() == 2 && block->succ_size() == 2) {
+ assert(block->getTerminatorCondition() == b);
+ BVPair valsAB = vals.getPredBitVectors(block);
+ vals.mergeIntoScratch(*valsAB.first, true);
+ vals.mergeIntoScratch(*valsAB.second, false);
+ valsAB.second = &vals.getScratch();
+ if (b->getOpcode() == BO_LOr) {
+ // Ensure the invariant that 'first' corresponds to the true
+ // branch and 'second' to the false.
+ std::swap(valsAB.first, valsAB.second);
+ }
+ return vals.updateBitVectors(block, valsAB);
}
- return vals.updateBitVectors(block, valsAB);
}
// Default behavior: merge in values of predecessor blocks.
diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp
index e971357..0d6920c 100644
--- a/test/SemaCXX/uninit-variables.cpp
+++ b/test/SemaCXX/uninit-variables.cpp
@@ -13,3 +13,31 @@
return x; // no-warning
}
+// Handle cases where the CFG may constant fold some branches, thus
+// mitigating the need for some path-sensitivity in the analysis.
+unsigned test3_aux();
+unsigned test3() {
+ unsigned x = 0;
+ const bool flag = true;
+ if (flag && (x = test3_aux()) == 0) {
+ return x;
+ }
+ return x;
+}
+unsigned test3_b() {
+ unsigned x ;
+ const bool flag = true;
+ if (flag && (x = test3_aux()) == 0) {
+ x = 1;
+ }
+ return x; // no-warning
+}
+unsigned test3_c() {
+ unsigned x ;
+ const bool flag = false;
+ if (flag && (x = test3_aux()) == 0) {
+ x = 1;
+ }
+ return x; // expected-warning{{use of uninitialized variable 'x'}}
+}
+