[cfe-commits] r163353 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp test/Analysis/dead-stores.cpp

Ted Kremenek kremenek at apple.com
Thu Sep 6 15:32:49 PDT 2012


Author: kremenek
Date: Thu Sep  6 17:32:48 2012
New Revision: 163353

URL: http://llvm.org/viewvc/llvm-project?rev=163353&view=rev
Log:
Tweak DeadStoresChecker to not warn about dead stores to variables that
are used in EH code.  Right now the CFG doesn't support exceptions well,
so we need this hack to avoid bogus dead store warnings.

Fixes <rdar://problem/12147586>

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
    cfe/trunk/test/Analysis/dead-stores.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp?rev=163353&r1=163352&r2=163353&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp Thu Sep  6 17:32:48 2012
@@ -22,13 +22,47 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ParentMap.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/Support/SaveAndRestore.h"
 
 using namespace clang;
 using namespace ento;
 
-namespace {
+namespace {  
+  
+/// A simple visitor to record what VarDecls occur in EH-handling code.
+class EHCodeVisitor : public RecursiveASTVisitor<EHCodeVisitor> {
+public:
+  bool inEH;
+  llvm::DenseSet<const VarDecl *> &S;
+  
+  bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+    SaveAndRestore<bool> inFinally(inEH, true);
+    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtFinallyStmt(S);
+  }
+  
+  bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+    SaveAndRestore<bool> inCatch(inEH, true);
+    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtCatchStmt(S);
+  }
+  
+  bool TraverseCXXCatchStmt(CXXCatchStmt *S) {
+    SaveAndRestore<bool> inCatch(inEH, true);
+    return TraverseStmt(S->getHandlerBlock());
+  }
+  
+  bool VisitDeclRefExpr(DeclRefExpr *DR) {
+    if (inEH)
+      if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
+        S.insert(D);
+    return true;
+  }
+  
+  EHCodeVisitor(llvm::DenseSet<const VarDecl *> &S) :
+  inEH(false), S(S) {}
+};
 
 // FIXME: Eventually migrate into its own file, and have it managed by
 // AnalysisManager.
@@ -93,6 +127,7 @@
   llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
   OwningPtr<ReachableCode> reachableCode;
   const CFGBlock *currentBlock;
+  llvm::OwningPtr<llvm::DenseSet<const VarDecl *> > InEH;
 
   enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
 
@@ -105,6 +140,23 @@
 
   virtual ~DeadStoreObs() {}
 
+  bool isLive(const LiveVariables::LivenessValues &Live, const VarDecl *D) {
+    if (Live.isLive(D))
+      return true;
+    // Lazily construct the set that records which VarDecls are in
+    // EH code.
+    if (!InEH.get()) {
+      InEH.reset(new llvm::DenseSet<const VarDecl *>());
+      EHCodeVisitor V(*InEH.get());
+      V.TraverseStmt(AC->getBody());
+    }
+    // Treat all VarDecls that occur in EH code as being "always live"
+    // when considering to suppress dead stores.  Frequently stores
+    // are followed by reads in EH code, but we don't have the ability
+    // to analyze that yet.
+    return InEH->count(D);
+  }
+  
   void Report(const VarDecl *V, DeadStoreKind dsk,
               PathDiagnosticLocation L, SourceRange R) {
     if (Escaped.count(V))
@@ -159,7 +211,7 @@
     if (VD->getType()->getAs<ReferenceType>())
       return;
 
-    if (!Live.isLive(VD) && 
+    if (!isLive(Live, VD) &&
         !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) {
 
       PathDiagnosticLocation ExLoc =
@@ -285,7 +337,7 @@
             // A dead initialization is a variable that is dead after it
             // is initialized.  We don't flag warnings for those variables
             // marked 'unused'.
-            if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) {
+            if (!isLive(Live, V) && V->getAttr<UnusedAttr>() == 0) {
               // Special case: check for initializations with constants.
               //
               //  e.g. : int x = 0;

Modified: cfe/trunk/test/Analysis/dead-stores.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.cpp?rev=163353&r1=163352&r2=163353&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.cpp (original)
+++ cfe/trunk/test/Analysis/dead-stores.cpp Thu Sep  6 17:32:48 2012
@@ -109,3 +109,20 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+// Dead stores in with EH code.
+//===----------------------------------------------------------------------===//
+
+void test_5_Aux();
+int test_5() {
+  int x = 0;
+  try {
+    x = 2; // no-warning
+    test_5_Aux();
+  }
+  catch (int z) {
+    return x + z;
+  }
+  return 1;
+}
+





More information about the cfe-commits mailing list