diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Analysis/UninitializedValues.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 52 |
2 files changed, 59 insertions, 11 deletions
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index 6c6804fe9eb..332c02cf185 100644 --- a/clang/lib/Analysis/UninitializedValues.cpp +++ b/clang/lib/Analysis/UninitializedValues.cpp @@ -527,12 +527,28 @@ public: SuccsVisited[block->getBlockID()] = block->succ_size(); while (!Queue.empty()) { const CFGBlock *B = Queue.pop_back_val(); + + // If the use is always reached from the entry block, make a note of that. + if (B == &cfg.getEntry()) + Use.setUninitAfterCall(); + for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end(); I != E; ++I) { const CFGBlock *Pred = *I; - if (vals.getValue(Pred, B, vd) == Initialized) + Value AtPredExit = vals.getValue(Pred, B, vd); + if (AtPredExit == Initialized) // This block initializes the variable. continue; + if (AtPredExit == MayUninitialized && + vals.getValue(B, 0, vd) == Uninitialized) { + // This block declares the variable (uninitialized), and is reachable + // from a block that initializes the variable. We can't guarantee to + // give an earlier location for the diagnostic (and it appears that + // this code is intended to be reachable) so give a diagnostic here + // and go no further down this path. + Use.setUninitAfterDecl(); + continue; + } unsigned &SV = SuccsVisited[Pred->getBlockID()]; if (!SV) { diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 599c4861267..7893a459c19 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -493,6 +493,31 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, bool IsCapturedByBlock) { bool Diagnosed = false; + switch (Use.getKind()) { + case UninitUse::Always: + S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var) + << VD->getDeclName() << IsCapturedByBlock + << Use.getUser()->getSourceRange(); + return; + + case UninitUse::AfterDecl: + case UninitUse::AfterCall: + S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var) + << VD->getDeclName() << IsCapturedByBlock + << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5) + << const_cast<DeclContext*>(VD->getLexicalDeclContext()) + << VD->getSourceRange(); + S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use) + << IsCapturedByBlock << Use.getUser()->getSourceRange(); + return; + + case UninitUse::Maybe: + case UninitUse::Sometimes: + // Carry on to report sometimes-uninitialized branches, if possible, + // or a 'may be used uninitialized' diagnostic otherwise. + break; + } + // Diagnose each branch which leads to a sometimes-uninitialized use. for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); I != E; ++I) { @@ -515,14 +540,10 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, : (I->Output ? "1" : "0"); FixItHint Fixit1, Fixit2; - switch (Term->getStmtClass()) { + switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) { default: // Don't know how to report this. Just fall back to 'may be used - // uninitialized'. This happens for range-based for, which the user - // can't explicitly fix. - // FIXME: This also happens if the first use of a variable is always - // uninitialized, eg "for (int n; n < 10; ++n)". We should report that - // with the 'is uninitialized' diagnostic. + // uninitialized'. FIXME: Can this happen? continue; // "condition is true / condition is false". @@ -583,6 +604,17 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, else Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); break; + case Stmt::CXXForRangeStmtClass: + if (I->Output == 1) { + // The use occurs if a range-based for loop's body never executes. + // That may be impossible, and there's no syntactic fix for this, + // so treat it as a 'may be uninitialized' case. + continue; + } + DiagKind = 1; + Str = "for"; + Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange(); + break; // "condition is true / loop is exited". case Stmt::DoStmtClass: @@ -619,9 +651,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, } if (!Diagnosed) - S.Diag(Use.getUser()->getLocStart(), - Use.getKind() == UninitUse::Always ? diag::warn_uninit_var - : diag::warn_maybe_uninit_var) + S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var) << VD->getDeclName() << IsCapturedByBlock << Use.getUser()->getSourceRange(); } @@ -1233,7 +1263,9 @@ public: private: static bool hasAlwaysUninitializedUse(const UsesVec* vec) { for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { - if (i->getKind() == UninitUse::Always) { + if (i->getKind() == UninitUse::Always || + i->getKind() == UninitUse::AfterCall || + i->getKind() == UninitUse::AfterDecl) { return true; } } |

