]> granicus.if.org Git - clang/commitdiff
Split warnings from -Wuninitialized-experimental into "must-be-initialized" and ...
authorTed Kremenek <kremenek@apple.com>
Tue, 15 Mar 2011 04:57:38 +0000 (04:57 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 15 Mar 2011 04:57:38 +0000 (04:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127666 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/Analyses/UninitializedValues.h
include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Analysis/UninitializedValues.cpp
lib/Sema/AnalysisBasedWarnings.cpp
test/Sema/uninit-variables.c

index 2c41bbf6d0d35781cb897ea28c06822a452ad174..b966f3a90ffff7831d51f08cf31a0e5ba5aa4c80 100644 (file)
@@ -29,7 +29,8 @@ public:
   virtual ~UninitVariablesHandler();
   
   virtual void handleUseOfUninitVariable(const Expr *ex,
-                                         const VarDecl *vd) {}
+                                         const VarDecl *vd,
+                                         bool isAlwaysUninit) {}
 };
   
 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
index e5cd51c96cf8032509938108c38fc965eeba003a..31d9ef389d78cf3f4160a51dcb58710742b1b8c0 100644 (file)
@@ -136,7 +136,8 @@ def Switch         : DiagGroup<"switch", [SwitchEnum]>;
 def Trigraphs      : DiagGroup<"trigraphs">;
 
 def : DiagGroup<"type-limits">;
-def Uninitialized  : DiagGroup<"uninitialized">;
+
+def UninitializedMaybe : DiagGroup<"uninitialized-maybe">;
 def UnknownPragmas : DiagGroup<"unknown-pragmas">;
 def UnknownAttributes : DiagGroup<"unknown-attributes">;
 def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
@@ -199,6 +200,10 @@ def Unused : DiagGroup<"unused",
                         UnusedValue, UnusedVariable]>,
                         DiagCategory<"Unused Entity Issue">;
 
+def Uninitialized : DiagGroup<"uninitialized",
+                              [UninitializedMaybe]>,
+                              DiagCategory<"Uninitialized Value Issues">;
+
 // Format settings.
 def FormatSecurity : DiagGroup<"format-security">;
 def Format : DiagGroup<"format",
index 3a6c43c269c7a46ef6cb8dc641a430789c67adba..641fa3f07bd6a563ed28a10ce590d31b8aed40e2 100644 (file)
@@ -868,11 +868,17 @@ def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
   InGroup<Uninitialized>;
 def warn_uninit_var : Warning<"variable %0 is possibly uninitialized when used here">,
   InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
+def warn_maybe_uninit_var :
+  Warning<"variable %0 is possibly uninitialized when used here">,
+    InGroup<UninitializedMaybe>, DefaultIgnore;
 def note_uninit_var_def : Note<
   "variable %0 is declared here">;
 def warn_uninit_var_captured_by_block : Warning<
   "variable %0 is possibly uninitialized when captured by block">,
   InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
+def warn_maybe_uninit_var_captured_by_block : Warning<
+  "variable %0 is possibly uninitialized when captured by block">,
+  InGroup<UninitializedMaybe>, DefaultIgnore;
 def note_var_fixit_add_initialization : Note<
   "add initialization to silence this warning">;
 def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
index 4aa62254da081c80738311d00e3d27bafe7de093..f651b474a0ac011641286f6f8f3a5f3c0f858dc0 100644 (file)
@@ -74,14 +74,26 @@ llvm::Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) {
 // CFGBlockValues: dataflow values for CFG blocks.
 //====------------------------------------------------------------------------//
 
-enum Value { Initialized = 0, Uninitialized = 1 };
+// These values are defined in such a way that a merge can be done using
+// a bitwise OR.
+enum Value { Unknown = 0x0,         /* 00 */
+             Initialized = 0x1,     /* 01 */
+             Uninitialized = 0x2,   /* 10 */
+             MayUninitialized = 0x3 /* 11 */ };
+
+static bool isUninitialized(const Value v) {
+  return v >= Uninitialized;
+}
+static bool isAlwaysUninit(const Value v) {
+  return v == Uninitialized;
+}
 
 class ValueVector {
   llvm::BitVector vec;
 public:
   ValueVector() {}
-  ValueVector(unsigned size) : vec(size) {}
-  void resize(unsigned n) { vec.resize(n); }
+  ValueVector(unsigned size) : vec(size << 1) {}
+  void resize(unsigned n) { vec.resize(n << 1); }
   void merge(const ValueVector &rhs) { vec |= rhs.vec; }
   bool operator!=(const ValueVector &rhs) const { return vec != rhs.vec; }
   void reset() { vec.reset(); }
@@ -96,11 +108,17 @@ public:
     ~reference() {}
     
     reference &operator=(Value v) {
-      vv.vec[idx] = (v == Initialized ? false : true);
+      vv.vec[idx << 1] = (((unsigned) v) & 0x1) ? true : false;
+      vv.vec[(idx << 1) | 1] = (((unsigned) v) & 0x2) ? true : false;
       return *this;
     }
+    operator Value() {
+      unsigned x = (vv.vec[idx << 1] ? 1 : 0) | (vv.vec[(idx << 1) | 1] ? 2 :0);
+      return (Value) x;      
+    }
+    
     bool operator==(Value v) {
-      return vv.vec[idx] == (v == Initialized ? false : true);      
+      return v = operator Value();
     }
   };
     
@@ -346,7 +364,8 @@ public:
       currentVoidCast(0), flagBlockUses(flagBlockUses) {}
   
   const CFG &getCFG() { return cfg; }
-  void reportUninit(const DeclRefExpr *ex, const VarDecl *vd);
+  void reportUninit(const DeclRefExpr *ex, const VarDecl *vd,
+                    bool isAlwaysUninit);
 
   void VisitBlockExpr(BlockExpr *be);
   void VisitDeclStmt(DeclStmt *ds);
@@ -366,8 +385,8 @@ public:
 }
 
 void TransferFunctions::reportUninit(const DeclRefExpr *ex,
-                                     const VarDecl *vd) {
-  if (handler) handler->handleUseOfUninitVariable(ex, vd);
+                                     const VarDecl *vd, bool isAlwaysUnit) {
+  if (handler) handler->handleUseOfUninitVariable(ex, vd, isAlwaysUnit);
 }
 
 FindVarResult TransferFunctions::findBlockVarDecl(Expr* ex) {
@@ -416,8 +435,9 @@ void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
     if (vd->getAttr<BlocksAttr>() || !vd->hasLocalStorage() || 
         !isTrackedVar(vd))
       continue;
-    if (vals[vd] == Uninitialized)
-      handler->handleUseOfUninitVariable(be, vd);
+    Value v = vals[vd];
+    if (isUninitialized(v))
+      handler->handleUseOfUninitVariable(be, vd, isAlwaysUninit(v));
   }
 }
 
@@ -468,9 +488,9 @@ void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) {
       Visit(bo->getLHS());
 
       ValueVector::reference val = vals[vd];
-      if (val == Uninitialized) {
+      if (isUninitialized(val)) {
         if (bo->getOpcode() != BO_Assign)
-          reportUninit(res.getDeclRefExpr(), vd);
+          reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
         val = Initialized;
       }
       return;
@@ -496,10 +516,11 @@ void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) {
                                                   res.getDeclRefExpr());
         Visit(uo->getSubExpr());
 
-        ValueVector::reference bit = vals[vd];
-        if (bit == Uninitialized) {
-          reportUninit(res.getDeclRefExpr(), vd);
-          bit = Initialized;
+        ValueVector::reference val = vals[vd];
+        if (isUninitialized(val)) {
+          reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
+          // Don't cascade warnings.
+          val = Initialized;
         }
         return;
       }
@@ -526,10 +547,13 @@ void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) {
       SaveAndRestore<const DeclRefExpr*> lastDR(currentDR, 
                                                 res.getDeclRefExpr());
       Visit(ce->getSubExpr());
-      if (currentVoidCast != ce && vals[vd] == Uninitialized) {
-        reportUninit(res.getDeclRefExpr(), vd);
-        // Don't cascade warnings.
-        vals[vd] = Initialized;
+      if (currentVoidCast != ce) {
+        Value val = vals[vd];
+        if (isUninitialized(val)) {
+          reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
+          // Don't cascade warnings.
+          vals[vd] = Initialized;
+        }
       }
       return;
     }
index 2da100ec824503fa09cc7b234603a718793cff71..e71f2dfb866a9fb18ac1f1a671aff29764298644 100644 (file)
@@ -377,18 +377,20 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
 // -Wuninitialized
 //===----------------------------------------------------------------------===//
 
+typedef std::pair<const Expr*, bool> UninitUse;
+
 namespace {
 struct SLocSort {
-  bool operator()(const Expr *a, const Expr *b) {
-    SourceLocation aLoc = a->getLocStart();
-    SourceLocation bLoc = b->getLocStart();
+  bool operator()(const UninitUse &a, const UninitUse &b) {
+    SourceLocation aLoc = a.first->getLocStart();
+    SourceLocation bLoc = b.first->getLocStart();
     return aLoc.getRawEncoding() < bLoc.getRawEncoding();
   }
 };
 
 class UninitValsDiagReporter : public UninitVariablesHandler {
   Sema &S;
-  typedef llvm::SmallVector<const Expr *, 2> UsesVec;
+  typedef llvm::SmallVector<UninitUse, 2> UsesVec;
   typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
   UsesMap *uses;
   
@@ -398,7 +400,8 @@ public:
     flushDiagnostics();
   }
   
-  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd) {
+  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd,
+                                 bool isAlwaysUninit) {
     if (!uses)
       uses = new UsesMap();
     
@@ -406,7 +409,7 @@ public:
     if (!vec)
       vec = new UsesVec();
     
-    vec->push_back(ex);
+    vec->push_back(std::make_pair(ex, isAlwaysUninit));
   }
   
   void flushDiagnostics() {
@@ -426,13 +429,18 @@ public:
       
       for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
       {
-        if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(*vi)) {
-          S.Diag(dr->getLocStart(), diag::warn_uninit_var)
+        const bool isAlwaysUninit = vi->second;
+        if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(vi->first)) {
+          S.Diag(dr->getLocStart(),
+                 isAlwaysUninit ? diag::warn_uninit_var
+                                : diag::warn_maybe_uninit_var)
             << vd->getDeclName() << dr->getSourceRange();          
         }
         else {
-          const BlockExpr *be = cast<BlockExpr>(*vi);
-          S.Diag(be->getLocStart(), diag::warn_uninit_var_captured_by_block)
+          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();
         }
         
index bb2955290145037bce98954be70b5aa5d4b0d369..79dbfa8895343e6b06f6e4431aaa100c5e6ebfcf 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-experimental -fsyntax-only -fblocks %s -verify
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-experimental -Wuninitialized-maybe -fsyntax-only -fblocks %s -verify
 
 int test1() {
   int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}}