[cfe-commits] r141881 - in /cfe/trunk: include/clang/Analysis/Analyses/UninitializedValues.h lib/Analysis/UninitializedValues.cpp lib/Sema/AnalysisBasedWarnings.cpp test/Sema/uninit-variables.c
Ted Kremenek
kremenek at apple.com
Thu Oct 13 11:50:06 PDT 2011
Author: kremenek
Date: Thu Oct 13 13:50:06 2011
New Revision: 141881
URL: http://llvm.org/viewvc/llvm-project?rev=141881&view=rev
Log:
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>.
Modified:
cfe/trunk/include/clang/Analysis/Analyses/UninitializedValues.h
cfe/trunk/lib/Analysis/UninitializedValues.cpp
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/test/Sema/uninit-variables.c
Modified: cfe/trunk/include/clang/Analysis/Analyses/UninitializedValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/UninitializedValues.h?rev=141881&r1=141880&r2=141881&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/UninitializedValues.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/UninitializedValues.h Thu Oct 13 13:50:06 2011
@@ -27,10 +27,16 @@
public:
UninitVariablesHandler() {}
virtual ~UninitVariablesHandler();
-
+
+ /// Called when the uninitialized variable is used at the given expression.
virtual void handleUseOfUninitVariable(const Expr *ex,
const VarDecl *vd,
bool isAlwaysUninit) {}
+
+ /// Called when the uninitialized variable analysis detects the
+ /// idiom 'int x = x'. All other uses of 'x' within the initializer
+ /// are handled by handleUseOfUninitVariable.
+ virtual void handleSelfInit(const VarDecl *vd) {}
};
struct UninitVariablesAnalysisStats {
Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=141881&r1=141880&r2=141881&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Thu Oct 13 13:50:06 2011
@@ -484,11 +484,17 @@
vals[vd] = Uninitialized;
lastLoad = 0;
lastDR = 0;
+ if (handler)
+ handler->handleSelfInit(vd);
return;
}
}
// All other cases: treat the new variable as initialized.
+ // This is a minor optimization to reduce the propagation
+ // of the analysis, since we will have already reported
+ // the use of the uninitialized value (which visiting the
+ // initializer).
vals[vd] = Initialized;
}
}
Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=141881&r1=141880&r2=141881&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Thu Oct 13 13:50:06 2011
@@ -470,7 +470,8 @@
/// 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 @@
// 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 @@
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 @@
~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 @@
for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
const VarDecl *vd = i->first;
- UsesVec *vec = i->second;
+ const UsesMap::mapped_type &V = 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;
- }
+ 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;
Modified: cfe/trunk/test/Sema/uninit-variables.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/uninit-variables.c?rev=141881&r1=141880&r2=141881&view=diff
==============================================================================
--- cfe/trunk/test/Sema/uninit-variables.c (original)
+++ cfe/trunk/test/Sema/uninit-variables.c Thu Oct 13 13:50:06 2011
@@ -94,10 +94,15 @@
for (;;) {}
}
-int test15() {
- int x = x; // no-warning: signals intended lack of initialization. \
- // expected-note{{variable 'x' is declared here}}
- return x; // expected-warning{{variable 'x' is uninitialized when used here}}
+void test15() {
+ int x = x; // no-warning: signals intended lack of initialization.
+}
+
+int test15b() {
+ // Warn here with the self-init, since it does result in a use of
+ // an unintialized variable and this is the root cause.
+ int x = x; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+ return x;
}
// Don't warn in the following example; shows dataflow confluence.
More information about the cfe-commits
mailing list