diff options
-rw-r--r-- | lib/Analysis/UninitializedValues.cpp | 20 | ||||
-rw-r--r-- | test/Sema/uninit-variables.c | 6 |
2 files changed, 20 insertions, 6 deletions
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 3dde41f227..062857d86e 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -472,12 +472,24 @@ void TransferFunctions::VisitDeclStmt(DeclStmt *ds) { DI != DE; ++DI) { if (VarDecl *vd = dyn_cast<VarDecl>(*DI)) { if (isTrackedVar(vd)) { - if (Stmt *init = vd->getInit()) { + if (Expr *init = vd->getInit()) { Visit(init); - vals[vd] = Initialized; + + // If the initializer consists solely of a reference to itself, we + // explicitly mark the variable as uninitialized. This allows code + // like the following: + // + // int x = x; + // + // to deliberately leave a variable uninitialized. Different analysis + // clients can detect this pattern and adjust their reporting + // appropriately, but we need to continue to analyze subsequent uses + // of the variable. + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(init->IgnoreParenImpCasts()); + vals[vd] = (DRE && DRE->getDecl() == vd) ? Uninitialized + : Initialized; } - } - else if (Stmt *init = vd->getInit()) { + } else if (Stmt *init = vd->getInit()) { Visit(init); } } diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c index ee3e88a49c..f09d44ca44 100644 --- a/test/Sema/uninit-variables.c +++ b/test/Sema/uninit-variables.c @@ -91,8 +91,10 @@ void test14() { for (;;) {} } -void test15() { - int x = x; // no-warning: signals intended lack of initialization. +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 possibly uninitialized when used here}} } // Don't warn in the following example; shows dataflow confluence. |