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);
}
}
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.