aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/UninitializedValuesV2.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-02-01 17:43:18 +0000
committerTed Kremenek <kremenek@apple.com>2011-02-01 17:43:18 +0000
commit9fcbceed43e5610fdff43defe533934733453ae2 (patch)
tree7cb229b6eb6fcbe4932142a3aaeca0335c9d0c1d /lib/Analysis/UninitializedValuesV2.cpp
parentd880f52be3e4a8ccad92ac31932eeae5e0870a93 (diff)
Enhance -Wuninitialized to better reason about || and &&, tracking dual dataflow facts and properly merging them.
Fixes PR 9076. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124666 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/UninitializedValuesV2.cpp')
-rw-r--r--lib/Analysis/UninitializedValuesV2.cpp99
1 files changed, 61 insertions, 38 deletions
diff --git a/lib/Analysis/UninitializedValuesV2.cpp b/lib/Analysis/UninitializedValuesV2.cpp
index 0867b5e7f3..75eccbf7a3 100644
--- a/lib/Analysis/UninitializedValuesV2.cpp
+++ b/lib/Analysis/UninitializedValuesV2.cpp
@@ -92,10 +92,8 @@ public:
llvm::BitVector &getBitVector(const CFGBlock *block,
const CFGBlock *dstBlock);
- BVPair &getBitVectors(const CFGBlock *block);
+ BVPair &getBitVectors(const CFGBlock *block, bool shouldLazyCreate);
- BVPair getPredBitVectors(const CFGBlock *block);
-
void mergeIntoScratch(llvm::BitVector const &source, bool isFirst);
bool updateBitVectorWithScratch(const CFGBlock *block);
bool updateBitVectors(const CFGBlock *block, const BVPair &newVals);
@@ -147,46 +145,44 @@ llvm::BitVector &CFGBlockValues::lazyCreate(llvm::BitVector *&bv) {
static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) {
if (block->empty())
return 0;
-
+
CFGStmt cstmt = block->front().getAs<CFGStmt>();
BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt.getStmt());
- if (!b || !b->isLogicalOp() || block->getTerminatorCondition() != b)
+
+ if (!b || !b->isLogicalOp())
return 0;
- return b;
+
+ if (block->pred_size() == 2 &&
+ ((block->succ_size() == 2 && block->getTerminatorCondition() == b) ||
+ block->size() == 1))
+ return b;
+
+ return 0;
}
llvm::BitVector &CFGBlockValues::getBitVector(const CFGBlock *block,
const CFGBlock *dstBlock) {
unsigned idx = block->getBlockID();
- if (dstBlock && block->succ_size() == 2 && block->pred_size() == 2 &&
- block->getTerminator()) {
- if (getLogicalOperatorInChain(block)) {
- if (*block->succ_begin() == dstBlock)
- return lazyCreate(vals[idx].first);
- assert(*(block->succ_begin()+1) == dstBlock);
- return lazyCreate(vals[idx].second);
- }
+ if (dstBlock && getLogicalOperatorInChain(block)) {
+ if (*block->succ_begin() == dstBlock)
+ return lazyCreate(vals[idx].first);
+ assert(*(block->succ_begin()+1) == dstBlock);
+ return lazyCreate(vals[idx].second);
}
assert(vals[idx].second == 0);
return lazyCreate(vals[idx].first);
}
-BVPair &CFGBlockValues::getBitVectors(const clang::CFGBlock *block) {
+BVPair &CFGBlockValues::getBitVectors(const clang::CFGBlock *block,
+ bool shouldLazyCreate) {
unsigned idx = block->getBlockID();
lazyCreate(vals[idx].first);
- lazyCreate(vals[idx].second);
+ if (shouldLazyCreate)
+ lazyCreate(vals[idx].second);
return vals[idx];
}
-BVPair CFGBlockValues::getPredBitVectors(const clang::CFGBlock *block) {
- assert(block->pred_size() == 2);
- CFGBlock::const_pred_iterator itr = block->pred_begin();
- llvm::BitVector &bvA = getBitVector(*itr, block);
- ++itr;
- return BVPair(&bvA, &getBitVector(*itr, block));
-}
-
void CFGBlockValues::mergeIntoScratch(llvm::BitVector const &source,
bool isFirst) {
if (isFirst)
@@ -194,23 +190,40 @@ void CFGBlockValues::mergeIntoScratch(llvm::BitVector const &source,
else
scratch |= source;
}
+#if 0
+static void printVector(const CFGBlock *block, llvm::BitVector &bv,
+ unsigned num) {
+
+ llvm::errs() << block->getBlockID() << " :";
+ for (unsigned i = 0; i < bv.size(); ++i) {
+ llvm::errs() << ' ' << bv[i];
+ }
+ llvm::errs() << " : " << num << '\n';
+}
+#endif
bool CFGBlockValues::updateBitVectorWithScratch(const CFGBlock *block) {
llvm::BitVector &dst = getBitVector(block, 0);
bool changed = (dst != scratch);
if (changed)
dst = scratch;
-
+#if 0
+ printVector(block, scratch, 0);
+#endif
return changed;
}
bool CFGBlockValues::updateBitVectors(const CFGBlock *block,
const BVPair &newVals) {
- BVPair &vals = getBitVectors(block);
+ BVPair &vals = getBitVectors(block, true);
bool changed = *newVals.first != *vals.first ||
*newVals.second != *vals.second;
*vals.first = *newVals.first;
*vals.second = *newVals.second;
+#if 0
+ printVector(block, *vals.first, 1);
+ printVector(block, *vals.second, 2);
+#endif
return changed;
}
@@ -522,22 +535,32 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
bool flagBlockUses = false) {
if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
- 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);
+ CFGBlock::const_pred_iterator itr = block->pred_begin();
+ BVPair vA = vals.getBitVectors(*itr, false);
+ ++itr;
+ BVPair vB = vals.getBitVectors(*itr, false);
+
+ BVPair valsAB;
+
+ if (b->getOpcode() == BO_LAnd) {
+ // Merge the 'F' bits from the first and second.
+ vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true);
+ vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false);
+ valsAB.first = vA.first;
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);
}
+ else {
+ // Merge the 'T' bits from the first and second.
+ assert(b->getOpcode() == BO_LOr);
+ vals.mergeIntoScratch(*vA.first, true);
+ vals.mergeIntoScratch(*vB.first, false);
+ valsAB.first = &vals.getScratch();
+ valsAB.second = vA.second ? vA.second : vA.first;
+ }
+ return vals.updateBitVectors(block, valsAB);
}
- // Default behavior: merge in values of predecessor blocks.
+ // Default behavior: merge in values of predecessor blocks.
vals.resetScratch();
bool isFirst = true;
for (CFGBlock::const_pred_iterator I = block->pred_begin(),