From: Ted Kremenek Date: Thu, 20 Jan 2011 21:25:31 +0000 (+0000) Subject: Relax CFG assertions in UninitializedValuesV2 when X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2d4bed140f65d713673d2d32ec3adadc960078c6;p=clang 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 55769bd2db..121dcf909e 100644 --- a/lib/Analysis/UninitializedValuesV2.cpp +++ b/lib/Analysis/UninitializedValuesV2.cpp @@ -156,7 +156,7 @@ static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) { 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 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg, 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 e971357ca7..0d6920ceb3 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -13,3 +13,31 @@ int test2_aux() { 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'}} +} +