diff options
Diffstat (limited to 'clang/lib/Analysis/UninitializedValuesV2.cpp')
-rw-r--r-- | clang/lib/Analysis/UninitializedValuesV2.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/clang/lib/Analysis/UninitializedValuesV2.cpp b/clang/lib/Analysis/UninitializedValuesV2.cpp index 4c548854131..4edc1a965bd 100644 --- a/clang/lib/Analysis/UninitializedValuesV2.cpp +++ b/clang/lib/Analysis/UninitializedValuesV2.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMap.h" #include "clang/AST/Decl.h" #include "clang/Analysis/CFG.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" #include "clang/Analysis/Analyses/UninitializedValuesV2.h" #include "clang/Analysis/Support/SaveAndRestore.h" @@ -287,16 +288,22 @@ public: class TransferFunctions : public CFGRecStmtVisitor<TransferFunctions> { CFGBlockValues &vals; const CFG &cfg; + AnalysisContext ∾ UninitVariablesHandler *handler; const DeclRefExpr *currentDR; + const bool flagBlockUses; public: TransferFunctions(CFGBlockValues &vals, const CFG &cfg, - UninitVariablesHandler *handler) - : vals(vals), cfg(cfg), handler(handler), currentDR(0) {} + AnalysisContext &ac, + UninitVariablesHandler *handler, + bool flagBlockUses) + : vals(vals), cfg(cfg), ac(ac), handler(handler), currentDR(0), + flagBlockUses(flagBlockUses) {} const CFG &getCFG() { return cfg; } void reportUninit(const DeclRefExpr *ex, const VarDecl *vd); - + + void VisitBlockExpr(BlockExpr *be); void VisitDeclStmt(DeclStmt *ds); void VisitDeclRefExpr(DeclRefExpr *dr); void VisitUnaryOperator(UnaryOperator *uo); @@ -311,6 +318,20 @@ void TransferFunctions::reportUninit(const DeclRefExpr *ex, if (handler) handler->handleUseOfUninitVariable(ex, vd); } +void TransferFunctions::VisitBlockExpr(BlockExpr *be) { + if (!flagBlockUses || !handler) + return; + AnalysisContext::referenced_decls_iterator i, e; + llvm::tie(i, e) = ac.getReferencedBlockVars(be->getBlockDecl()); + for ( ; i != e; ++i) { + const VarDecl *vd = *i; + if (vd->getAttr<BlocksAttr>() || !vd->hasLocalStorage()) + continue; + if (vals[vd] == Uninitialized) + handler->handleUseOfUninitVariable(be, vd); + } +} + void TransferFunctions::VisitDeclStmt(DeclStmt *ds) { for (DeclStmt::decl_iterator DI = ds->decl_begin(), DE = ds->decl_end(); DI != DE; ++DI) { @@ -450,8 +471,9 @@ void TransferFunctions::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se) { //====------------------------------------------------------------------------// static bool runOnBlock(const CFGBlock *block, const CFG &cfg, - CFGBlockValues &vals, - UninitVariablesHandler *handler = 0) { + AnalysisContext &ac, CFGBlockValues &vals, + UninitVariablesHandler *handler = 0, + bool flagBlockUses = false) { if (const BinaryOperator *b = getLogicalOperatorInChain(block)) { if (block->pred_size() == 2 && block->succ_size() == 2) { @@ -478,7 +500,7 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg, isFirst = false; } // Apply the transfer function. - TransferFunctions tf(vals, cfg, handler); + TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses); for (CFGBlock::const_iterator I = block->begin(), E = block->end(); I != E; ++I) { if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) { @@ -490,6 +512,7 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg, void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, + AnalysisContext &ac, UninitVariablesHandler &handler) { CFGBlockValues vals(cfg); vals.computeSetOfDeclarations(dc); @@ -502,7 +525,7 @@ void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, while (const CFGBlock *block = worklist.dequeue()) { // Did the block change? - bool changed = runOnBlock(block, cfg, vals); + bool changed = runOnBlock(block, cfg, ac, vals); if (changed || !previouslyVisited[block->getBlockID()]) worklist.enqueueSuccessors(block); previouslyVisited[block->getBlockID()] = true; @@ -510,7 +533,7 @@ void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, // Run through the blocks one more time, and report uninitialized variabes. for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { - runOnBlock(*BI, cfg, vals, &handler); + runOnBlock(*BI, cfg, ac, vals, &handler, /* flagBlockUses */ true); } } |