diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-01-21 19:41:41 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-01-21 19:41:41 +0000 |
commit | 39fa05634287190fa5898715dc66ac68ce5028ef (patch) | |
tree | 013592f1b6250b363089e10c095e9d9d222c61fc /clang/lib/Sema/AnalysisBasedWarnings.cpp | |
parent | a834200dbe3ca1164198d8b79454c0f21c1c5a0d (diff) | |
download | bcm5719-llvm-39fa05634287190fa5898715dc66ac68ce5028ef.tar.gz bcm5719-llvm-39fa05634287190fa5898715dc66ac68ce5028ef.zip |
Enhance -Wuninitialized-experimental diagnostics
to issue the warning at an uninitialized variable's
declaration, but to issue notes at possible
uninitialized uses (which could be multiple).
llvm-svn: 123994
Diffstat (limited to 'clang/lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index eb8590d60cb..67ddbf5bf98 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -364,14 +364,62 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, //===----------------------------------------------------------------------===// namespace { +struct SLocSort { + bool operator()(const DeclRefExpr *a, const DeclRefExpr *b) { + SourceLocation aLoc = a->getLocStart(); + SourceLocation bLoc = b->getLocStart(); + return aLoc.getRawEncoding() < bLoc.getRawEncoding(); + } +}; + class UninitValsDiagReporter : public UninitVariablesHandler { Sema &S; + typedef llvm::SmallVector<const DeclRefExpr *, 2> UsesVec; + typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap; + UsesMap *uses; + public: - UninitValsDiagReporter(Sema &S) : S(S) {} + UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} + ~UninitValsDiagReporter() { + flushDiagnostics(); + } void handleUseOfUninitVariable(const DeclRefExpr *dr, const VarDecl *vd) { - S.Diag(dr->getLocStart(), diag::warn_var_is_uninit) - << vd->getDeclName() << dr->getSourceRange(); + if (!uses) + uses = new UsesMap(); + + UsesVec *&vec = (*uses)[vd]; + if (!vec) + vec = new UsesVec(); + + vec->push_back(dr); + } + + void flushDiagnostics() { + if (!uses) + return; + + for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { + const VarDecl *vd = i->first; + UsesVec *vec = i->second; + + S.Diag(vd->getLocStart(), diag::warn_var_is_uninit) + << vd->getDeclName() << vd->getSourceRange(); + + // Sort the uses by their SourceLocations. While not strictly + // guaranteed to produce them in line/column order, this will provide + // a stable ordering. + std::sort(vec->begin(), vec->end(), SLocSort()); + + for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi) + { + const DeclRefExpr *dr = *vi; + S.Diag(dr->getLocStart(), diag::note_var_is_uninit) + << vd->getDeclName() << dr->getSourceRange(); + } + delete vec; + } + delete uses; } }; } |