diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-10-13 18:50:06 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-10-13 18:50:06 +0000 |
commit | 9e7617220135a6f6226cf09cb242cc1b905aedb4 (patch) | |
tree | 703b7cb666fab0230627c8deb01dcfefae2d3912 /lib/Sema/AnalysisBasedWarnings.cpp | |
parent | 64a371ff8d525880e519a43fc522cbdc79fc4a89 (diff) |
Tweak -Wuninitialized's handling of 'int x = x' to report that as the root cause of an uninitialized variable IFF there are other uses of that uninitialized variable. Fixes <rdar://problem/9259237>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141881 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index f461772ba7..babb8af18b 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -470,7 +470,8 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { /// as a warning. If a pariticular use is one we omit warnings for, returns /// false. static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, - const Expr *E, bool isAlwaysUninit) { + const Expr *E, bool isAlwaysUninit, + bool alwaysReportSelfInit = false) { bool isSelfInit = false; if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { @@ -490,7 +491,7 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, // TODO: Should we suppress maybe-uninitialized warnings for // variables initialized in this way? if (const Expr *Initializer = VD->getInit()) { - if (DRE == Initializer->IgnoreParenImpCasts()) + if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) return false; ContainsReference CR(S.Context, DRE); @@ -541,7 +542,7 @@ struct SLocSort { class UninitValsDiagReporter : public UninitVariablesHandler { Sema &S; typedef SmallVector<UninitUse, 2> UsesVec; - typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap; + typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap; UsesMap *uses; public: @@ -549,17 +550,26 @@ public: ~UninitValsDiagReporter() { flushDiagnostics(); } - - void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, - bool isAlwaysUninit) { + + std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) { if (!uses) uses = new UsesMap(); - - UsesVec *&vec = (*uses)[vd]; + + UsesMap::mapped_type &V = (*uses)[vd]; + UsesVec *&vec = V.first; if (!vec) vec = new UsesVec(); - vec->push_back(std::make_pair(ex, isAlwaysUninit)); + return V; + } + + void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, + bool isAlwaysUninit) { + getUses(vd).first->push_back(std::make_pair(ex, isAlwaysUninit)); + } + + void handleSelfInit(const VarDecl *vd) { + getUses(vd).second = true; } void flushDiagnostics() { @@ -568,22 +578,34 @@ public: for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { const VarDecl *vd = i->first; - UsesVec *vec = i->second; - - // 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) { - if (DiagnoseUninitializedUse(S, vd, vi->first, - /*isAlwaysUninit=*/vi->second)) - // Skip further diagnostics for this variable. We try to warn only on - // the first point at which a variable is used uninitialized. - break; + const UsesMap::mapped_type &V = i->second; + + UsesVec *vec = V.first; + bool hasSelfInit = V.second; + + // Specially handle the case where we have uses of an uninitialized + // variable, but the root cause is an idiomatic self-init. We want + // to report the diagnostic at the self-init since that is the root cause. + if (!vec->empty() && hasSelfInit) + DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(), + true, /* alwaysReportSelfInit */ true); + else { + // 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) { + if (DiagnoseUninitializedUse(S, vd, vi->first, + /*isAlwaysUninit=*/vi->second)) + // Skip further diagnostics for this variable. We try to warn only + // on the first point at which a variable is used uninitialized. + break; + } } - + + // Release the uses vector. delete vec; } delete uses; |