]> granicus.if.org Git - clang/commitdiff
Begin refactoring the uninitialized warning code that I uglied up. This
authorChandler Carruth <chandlerc@gmail.com>
Tue, 5 Apr 2011 18:18:05 +0000 (18:18 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Tue, 5 Apr 2011 18:18:05 +0000 (18:18 +0000)
extracts a function to handle the emission of the diagnostic separately
from the walking over the set of uninitialized uses.

Also updates the naming used within this extracted function to be a bit
more consistent with the rest of Clang's naming patterns.

The next step will be breaking this apart so that we can go through
different functions rather than tracking so many boolean variables.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128898 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/AnalysisBasedWarnings.cpp

index df73fc6da3a74dd1c771239c94370a0c4955e5be..bd5416f5f7617127fc4b5e946e9d3cb9662cb7f5 100644 (file)
@@ -410,6 +410,98 @@ public:
 };
 }
 
+static void DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
+                                     const Expr *E, bool &fixitIssued,
+                                     bool isAlwaysUninit) {
+  bool isSelfInit = false;
+
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (isAlwaysUninit) {
+      // Inspect the initializer of the variable declaration which is
+      // being referenced prior to its initialization. We emit
+      // specialized diagnostics for self-initialization, and we
+      // specifically avoid warning about self references which take the
+      // form of:
+      //
+      //   int x = x;
+      //
+      // This is used to indicate to GCC that 'x' is intentionally left
+      // uninitialized. Proven code paths which access 'x' in
+      // an uninitialized state after this will still warn.
+      //
+      // TODO: Should we suppress maybe-uninitialized warnings for
+      // variables initialized in this way?
+      if (const Expr *Initializer = VD->getInit()) {
+        if (DRE == Initializer->IgnoreParenImpCasts())
+          return;
+
+        ContainsReference CR(S.Context, DRE);
+        CR.Visit(const_cast<Expr*>(Initializer));
+        isSelfInit = CR.doesContainReference();
+      }
+      if (isSelfInit) {
+        S.Diag(DRE->getLocStart(),
+               diag::warn_uninit_self_reference_in_init)
+        << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
+      } else {
+        S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
+          << VD->getDeclName() << DRE->getSourceRange();
+      }
+    } else {
+      S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
+        << VD->getDeclName() << DRE->getSourceRange();
+    }
+  } else {
+    const BlockExpr *BE = cast<BlockExpr>(E);
+    S.Diag(BE->getLocStart(),
+           isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
+                          : diag::warn_maybe_uninit_var_captured_by_block)
+      << VD->getDeclName();
+  }
+
+  // Report where the variable was declared when the use wasn't within
+  // the initializer of that declaration.
+  if (!isSelfInit)
+    S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
+      << VD->getDeclName();
+
+  // Only report the fixit once.
+  if (fixitIssued)
+    return;
+
+  fixitIssued = true;
+
+  // Don't issue a fixit if there is already an initializer.
+  if (VD->getInit())
+    return;
+
+  // Suggest possible initialization (if any).
+  const char *initialization = 0;
+  QualType VariableTy = VD->getType().getCanonicalType();
+
+  if (VariableTy->getAs<ObjCObjectPointerType>()) {
+    // Check if 'nil' is defined.
+    if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
+      initialization = " = nil";
+    else
+      initialization = " = 0";
+  }
+  else if (VariableTy->isRealFloatingType())
+    initialization = " = 0.0";
+  else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
+    initialization = " = false";
+  else if (VariableTy->isEnumeralType())
+    return;
+  else if (VariableTy->isScalarType())
+    initialization = " = 0";
+
+  if (initialization) {
+    SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
+    S.Diag(loc, diag::note_var_fixit_add_initialization)
+      << FixItHint::CreateInsertion(loc, initialization);
+  }
+}
+
 typedef std::pair<const Expr*, bool> UninitUse;
 
 namespace {
@@ -461,98 +553,9 @@ public:
       std::sort(vec->begin(), vec->end(), SLocSort());
       
       for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
-      {
-        const bool isAlwaysUninit = vi->second;
-        bool isSelfInit = false;
-
-        if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(vi->first)) {
-          if (isAlwaysUninit) {
-            // Inspect the initializer of the variable declaration which is
-            // being referenced prior to its initialization. We emit
-            // specialized diagnostics for self-initialization, and we
-            // specifically avoid warning about self references which take the
-            // form of:
-            //
-            //   int x = x;
-            //
-            // This is used to indicate to GCC that 'x' is intentionally left
-            // uninitialized. Proven code paths which access 'x' in
-            // an uninitialized state after this will still warn.
-            //
-            // TODO: Should we suppress maybe-uninitialized warnings for
-            // variables initialized in this way?
-            if (const Expr *E = vd->getInit()) {
-              if (dr == E->IgnoreParenImpCasts())
-                continue;
-
-              ContainsReference CR(S.Context, dr);
-              CR.Visit(const_cast<Expr*>(E));
-              isSelfInit = CR.doesContainReference();
-            }
-            if (isSelfInit) {
-              S.Diag(dr->getLocStart(), 
-                     diag::warn_uninit_self_reference_in_init)
-              << vd->getDeclName() << vd->getLocation() << dr->getSourceRange();             
-            } else {
-              S.Diag(dr->getLocStart(), diag::warn_uninit_var)
-                << vd->getDeclName() << dr->getSourceRange();          
-            }
-          }
-          else {
-            S.Diag(dr->getLocStart(), diag::warn_maybe_uninit_var)
-              << vd->getDeclName() << dr->getSourceRange();          
-          }          
-        }
-        else {
-          const BlockExpr *be = cast<BlockExpr>(vi->first);
-          S.Diag(be->getLocStart(),
-                 isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
-                                : diag::warn_maybe_uninit_var_captured_by_block)
-            << vd->getDeclName();
-        }
-        
-        // Report where the variable was declared when the use wasn't within
-        // the initializer of that declaration.
-        if (!isSelfInit)
-          S.Diag(vd->getLocStart(), diag::note_uninit_var_def)
-            << vd->getDeclName();
-
-        // Only report the fixit once.
-        if (fixitIssued)
-          continue;
-      
-        fixitIssued = true;
-        
-        // Don't issue a fixit if there is already an initializer.
-        if (vd->getInit())
-          continue;
+        DiagnoseUninitializedUse(S, vd, vi->first, fixitIssued,
+                                 /*isAlwaysUninit=*/vi->second);
 
-        // Suggest possible initialization (if any).
-        const char *initialization = 0;
-        QualType vdTy = vd->getType().getCanonicalType();
-
-        if (vdTy->getAs<ObjCObjectPointerType>()) {
-          // Check if 'nil' is defined.
-          if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
-            initialization = " = nil";
-          else
-            initialization = " = 0";
-        }
-        else if (vdTy->isRealFloatingType())
-          initialization = " = 0.0";
-        else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
-          initialization = " = false";
-        else if (vdTy->isEnumeralType())
-          continue;
-        else if (vdTy->isScalarType())
-          initialization = " = 0";
-      
-        if (initialization) {
-          SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd());
-          S.Diag(loc, diag::note_var_fixit_add_initialization)
-            << FixItHint::CreateInsertion(loc, initialization);
-        }
-      }
       delete vec;
     }
     delete uses;