[cfe-commits] r124213 - in /cfe/trunk: include/clang/Analysis/Analyses/UninitializedValuesV2.h include/clang/Basic/DiagnosticSemaKinds.td lib/Analysis/UninitializedValuesV2.cpp lib/Sema/AnalysisBasedWarnings.cpp test/Sema/uninit-variables.c

Ted Kremenek kremenek at apple.com
Tue Jan 25 11:13:48 PST 2011


Author: kremenek
Date: Tue Jan 25 13:13:48 2011
New Revision: 124213

URL: http://llvm.org/viewvc/llvm-project?rev=124213&view=rev
Log:
Teach -Wuninitialized-experimental to also warn
about uninitialized variables captured by blocks.

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/UninitializedValuesV2.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp
    cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
    cfe/trunk/test/Sema/uninit-variables.c

Modified: cfe/trunk/include/clang/Analysis/Analyses/UninitializedValuesV2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/UninitializedValuesV2.h?rev=124213&r1=124212&r2=124213&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/UninitializedValuesV2.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/UninitializedValuesV2.h Tue Jan 25 13:13:48 2011
@@ -17,9 +17,10 @@
 
 namespace clang {
 
+class AnalysisContext;
 class CFG;  
 class DeclContext;
-class DeclRefExpr;
+class Expr;
 class VarDecl;
   
 class UninitVariablesHandler {
@@ -27,11 +28,12 @@
   UninitVariablesHandler() {}
   virtual ~UninitVariablesHandler();
   
-  virtual void handleUseOfUninitVariable(const DeclRefExpr *dr,
+  virtual void handleUseOfUninitVariable(const Expr *ex,
                                          const VarDecl *vd) {}
 };
   
 void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
+                                       AnalysisContext &ac,
                                        UninitVariablesHandler &handler);
 
 }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=124213&r1=124212&r2=124213&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jan 25 13:13:48 2011
@@ -822,10 +822,12 @@
   "uninitialized reference member is here">;
 def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
   InGroup<DiagGroup<"uninitialized">>;
-def warn_var_is_uninit : Warning<"use of uninitialized variable %0">,
+def warn_uninit_var : Warning<"use of uninitialized variable %0">,
   InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore;
-def note_var_is_uninit : Note<
+def note_uninit_var : Note<
   "variable %0 is possibly uninitialized when used here">;
+def note_uninit_var_captured_by_block : Note<
+  "variable %0 is possibly uninitialized when captured by block">;
 def note_var_fixit_add_initialization : Note<
   "add initialization to silence this warning">;
 def err_init_incomplete_type : Error<"initialization of incomplete type %0">;

Modified: cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp?rev=124213&r1=124212&r2=124213&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValuesV2.cpp Tue Jan 25 13:13:48 2011
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "clang/AST/Decl.h"
 #include "clang/Analysis/CFG.h"
+#include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
 #include "clang/Analysis/Analyses/UninitializedValuesV2.h"
 #include "clang/Analysis/Support/SaveAndRestore.h"
@@ -287,16 +288,22 @@
 class TransferFunctions : public CFGRecStmtVisitor<TransferFunctions> {
   CFGBlockValues &vals;
   const CFG &cfg;
+  AnalysisContext ∾
   UninitVariablesHandler *handler;
   const DeclRefExpr *currentDR;
+  const bool flagBlockUses;
 public:
   TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
-                    UninitVariablesHandler *handler)
-    : vals(vals), cfg(cfg), handler(handler), currentDR(0) {}
+                    AnalysisContext &ac,
+                    UninitVariablesHandler *handler,
+                    bool flagBlockUses)
+    : vals(vals), cfg(cfg), ac(ac), handler(handler), currentDR(0),
+      flagBlockUses(flagBlockUses) {}
   
   const CFG &getCFG() { return cfg; }
   void reportUninit(const DeclRefExpr *ex, const VarDecl *vd);
-  
+
+  void VisitBlockExpr(BlockExpr *be);
   void VisitDeclStmt(DeclStmt *ds);
   void VisitDeclRefExpr(DeclRefExpr *dr);
   void VisitUnaryOperator(UnaryOperator *uo);
@@ -311,6 +318,20 @@
   if (handler) handler->handleUseOfUninitVariable(ex, vd);
 }
 
+void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
+  if (!flagBlockUses || !handler)
+    return;
+  AnalysisContext::referenced_decls_iterator i, e;
+  llvm::tie(i, e) = ac.getReferencedBlockVars(be->getBlockDecl());
+  for ( ; i != e; ++i) {
+    const VarDecl *vd = *i;
+    if (vd->getAttr<BlocksAttr>() || !vd->hasLocalStorage())
+      continue;
+    if (vals[vd] == Uninitialized)
+      handler->handleUseOfUninitVariable(be, vd);      
+  }
+}
+
 void TransferFunctions::VisitDeclStmt(DeclStmt *ds) {
   for (DeclStmt::decl_iterator DI = ds->decl_begin(), DE = ds->decl_end();
        DI != DE; ++DI) {
@@ -450,8 +471,9 @@
 //====------------------------------------------------------------------------//
 
 static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
-                       CFGBlockValues &vals,
-                       UninitVariablesHandler *handler = 0) {
+                       AnalysisContext &ac, CFGBlockValues &vals,
+                       UninitVariablesHandler *handler = 0,
+                       bool flagBlockUses = false) {
   
   if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
     if (block->pred_size() == 2 && block->succ_size() == 2) {
@@ -478,7 +500,7 @@
     isFirst = false;
   }
   // Apply the transfer function.
-  TransferFunctions tf(vals, cfg, handler);
+  TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses);
   for (CFGBlock::const_iterator I = block->begin(), E = block->end(); 
        I != E; ++I) {
     if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) {
@@ -490,6 +512,7 @@
 
 void clang::runUninitializedVariablesAnalysis(const DeclContext &dc,
                                               const CFG &cfg,
+                                              AnalysisContext &ac,
                                               UninitVariablesHandler &handler) {
   CFGBlockValues vals(cfg);
   vals.computeSetOfDeclarations(dc);
@@ -502,7 +525,7 @@
 
   while (const CFGBlock *block = worklist.dequeue()) {
     // Did the block change?
-    bool changed = runOnBlock(block, cfg, vals);    
+    bool changed = runOnBlock(block, cfg, ac, vals);    
     if (changed || !previouslyVisited[block->getBlockID()])
       worklist.enqueueSuccessors(block);    
     previouslyVisited[block->getBlockID()] = true;
@@ -510,7 +533,7 @@
   
   // Run through the blocks one more time, and report uninitialized variabes.
   for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
-    runOnBlock(*BI, cfg, vals, &handler);
+    runOnBlock(*BI, cfg, ac, vals, &handler, /* flagBlockUses */ true);
   }
 }
 

Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=124213&r1=124212&r2=124213&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Tue Jan 25 13:13:48 2011
@@ -366,7 +366,7 @@
 
 namespace {
 struct SLocSort {
-  bool operator()(const DeclRefExpr *a, const DeclRefExpr *b) {
+  bool operator()(const Expr *a, const Expr *b) {
     SourceLocation aLoc = a->getLocStart();
     SourceLocation bLoc = b->getLocStart();
     return aLoc.getRawEncoding() < bLoc.getRawEncoding();
@@ -375,7 +375,7 @@
 
 class UninitValsDiagReporter : public UninitVariablesHandler {
   Sema &S;
-  typedef llvm::SmallVector<const DeclRefExpr *, 2> UsesVec;
+  typedef llvm::SmallVector<const Expr *, 2> UsesVec;
   typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
   UsesMap *uses;
   
@@ -385,7 +385,7 @@
     flushDiagnostics();
   }
   
-  void handleUseOfUninitVariable(const DeclRefExpr *dr, const VarDecl *vd) {
+  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd) {
     if (!uses)
       uses = new UsesMap();
     
@@ -393,7 +393,7 @@
     if (!vec)
       vec = new UsesVec();
     
-    vec->push_back(dr);    
+    vec->push_back(ex);
   }
   
   void flushDiagnostics() {
@@ -404,7 +404,7 @@
       const VarDecl *vd = i->first;
       UsesVec *vec = i->second;
       
-      S.Diag(vd->getLocStart(), diag::warn_var_is_uninit)
+      S.Diag(vd->getLocStart(), diag::warn_uninit_var)
         << vd->getDeclName() << vd->getSourceRange();
       
       // Sort the uses by their SourceLocations.  While not strictly
@@ -414,9 +414,15 @@
       
       for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
       {
-        const DeclRefExpr *dr = *vi;
-        S.Diag(dr->getLocStart(), diag::note_var_is_uninit)
-          << vd->getDeclName() << dr->getSourceRange();
+        if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(*vi)) {
+          S.Diag(dr->getLocStart(), diag::note_uninit_var)
+            << vd->getDeclName() << dr->getSourceRange();
+        }
+        else {
+          const BlockExpr *be = cast<BlockExpr>(*vi);
+          S.Diag(be->getLocStart(), diag::note_uninit_var_captured_by_block)
+            << vd->getDeclName();
+        }
       }
 
       // Suggest possible initialization (if any).
@@ -514,11 +520,12 @@
   if (P.enableCheckUnreachable)
     CheckUnreachable(S, AC);
   
-  if (Diags.getDiagnosticLevel(diag::warn_var_is_uninit, D->getLocStart())
+  if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
       != Diagnostic::Ignored) {
     if (CFG *cfg = AC.getCFG()) {
       UninitValsDiagReporter reporter(S);
-      runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, reporter);
+      runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
+                                        reporter);
     }
   }
 }

Modified: cfe/trunk/test/Sema/uninit-variables.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/uninit-variables.c?rev=124213&r1=124212&r2=124213&view=diff
==============================================================================
--- cfe/trunk/test/Sema/uninit-variables.c (original)
+++ cfe/trunk/test/Sema/uninit-variables.c Tue Jan 25 13:13:48 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-experimental -fsyntax-only %s -verify
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized-experimental -fsyntax-only -fblocks %s -verify
 
 int test1() {
   int x; // expected-warning{{use of uninitialized variable 'x'}} expected-note{{add initialization to silence this warning}}
@@ -192,3 +192,23 @@
   return sizeof(int[len]); // expected-note{{variable 'len' is possibly uninitialized when used here}}
 }
 
+void test29() {
+  int x; // expected-warning{{use of uninitialized variable 'x'}} expected-note{{add initialization to silence this warning}}
+  (void) ^{ (void) x; }; // expected-note{{variable 'x' is possibly uninitialized when captured by block}}
+}
+
+void test30() {
+  static int x; // no-warning
+  (void) ^{ (void) x; };
+}
+
+void test31() {
+  __block int x; // no-warning
+  (void) ^{ (void) x; };
+}
+
+int test32_x;
+void test32() {
+  (void) ^{ (void) test32_x; }; // no-warning
+}
+





More information about the cfe-commits mailing list