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 | 94b1b4d785bc0f09f6af4be394e59d51f35dda60 (patch) | |
tree | 0c4bd4d1e4199400b2dfb08fe87183dca7b445a6 /lib/Sema/AnalysisBasedWarnings.cpp | |
parent | cc15f010672a13b38104a32e3cefc7adc07ffbf7 (diff) |
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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123994 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index eb8590d60c..67ddbf5bf9 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/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; } }; } |