[cfe-commits] r89640 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Checker.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp lib/Analysis/GRExprEngineInternalChecks.h lib/Analysis/UndefBranchChecker.cpp

Zhongxing Xu xuzhongxing at gmail.com
Sun Nov 22 19:20:54 PST 2009


Author: zhongxingxu
Date: Sun Nov 22 21:20:54 2009
New Revision: 89640

URL: http://llvm.org/viewvc/llvm-project?rev=89640&view=rev
Log:
Initial refactor of UndefBranchChecker. We still use GRBranchNodeBuilder
in the checker directly. But I don't have a better approach for now.

Added:
    cfe/trunk/lib/Analysis/UndefBranchChecker.cpp
Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
    cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h?rev=89640&r1=89639&r2=89640&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h Sun Nov 22 21:20:54 2009
@@ -172,6 +172,10 @@
                                SymbolReaper &SymReaper) {}
   virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
                            GRExprEngine &Eng) {}
+
+  virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
+                                    GRExprEngine &Eng,
+                                    Stmt *Condition, void *tag) {}
 };
 } // end clang namespace
 

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=89640&r1=89639&r2=89640&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Sun Nov 22 21:20:54 2009
@@ -771,55 +771,49 @@
                                 Condition->getLocStart(),
                                 "Error evaluating branch");
 
-  const GRState* PrevState = builder.getState();
-  SVal X = PrevState->getSVal(Condition);
-  DefinedSVal *V = NULL;
-  
-  while (true) {
-    V = dyn_cast<DefinedSVal>(&X);
-
-    if (!V) {
-      if (X.isUnknown()) {
-        if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
-          if (Ex->getType()->isIntegerType()) {
-            // Try to recover some path-sensitivity.  Right now casts of symbolic
-            // integers that promote their values are currently not tracked well.
-            // If 'Condition' is such an expression, try and recover the
-            // underlying value and use that instead.
-            SVal recovered = RecoverCastedSymbol(getStateManager(),
-                                                 builder.getState(), Condition,
-                                                 getContext());
-
-            if (!recovered.isUnknown()) {
-              X = recovered;
-              continue;
-            }
-          }
-        }    
+  for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
+    void *tag = I->first;
+    Checker *checker = I->second;
+    checker->VisitBranchCondition(builder, *this, Condition, tag);
+  }
 
-        builder.generateNode(MarkBranch(PrevState, Term, true), true);
-        builder.generateNode(MarkBranch(PrevState, Term, false), false);
-        return;
-      }
+  // If the branch condition is undefined, return;
+  if (!builder.isFeasible(true) && !builder.isFeasible(false))
+    return;
 
-      assert(X.isUndef());
-      ExplodedNode *N = builder.generateNode(PrevState, true);
+  const GRState* PrevState = builder.getState();
+  SVal X = PrevState->getSVal(Condition);
 
-      if (N) {
-        N->markAsSink();
-        UndefBranches.insert(N);
+  if (X.isUnknown()) {
+    // Give it a chance to recover from unknown.
+    if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
+      if (Ex->getType()->isIntegerType()) {
+        // Try to recover some path-sensitivity.  Right now casts of symbolic
+        // integers that promote their values are currently not tracked well.
+        // If 'Condition' is such an expression, try and recover the
+        // underlying value and use that instead.
+        SVal recovered = RecoverCastedSymbol(getStateManager(),
+                                             builder.getState(), Condition,
+                                             getContext());
+        
+        if (!recovered.isUnknown()) {
+          X = recovered;
+        }
       }
-
-      builder.markInfeasible(false);
+    }
+    // If the condition is still unknown, give up.
+    if (X.isUnknown()) {
+      builder.generateNode(MarkBranch(PrevState, Term, true), true);
+      builder.generateNode(MarkBranch(PrevState, Term, false), false);
       return;
     }
-    
-    break;
   }
 
+  DefinedSVal V = cast<DefinedSVal>(X);
+
   // Process the true branch.
   if (builder.isFeasible(true)) {
-    if (const GRState *state = PrevState->Assume(*V, true))
+    if (const GRState *state = PrevState->Assume(V, true))
       builder.generateNode(MarkBranch(state, Term, true), true);
     else
       builder.markInfeasible(true);
@@ -827,7 +821,7 @@
 
   // Process the false branch.
   if (builder.isFeasible(false)) {
-    if (const GRState *state = PrevState->Assume(*V, false))
+    if (const GRState *state = PrevState->Assume(V, false))
       builder.generateNode(MarkBranch(state, Term, false), false);
     else
       builder.markInfeasible(false);

Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=89640&r1=89639&r2=89640&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Sun Nov 22 21:20:54 2009
@@ -306,7 +306,6 @@
   // create BugReports on-the-fly but instead wait until GRExprEngine finishes
   // analyzing a function.  Generation of BugReport objects is done via a call
   // to 'FlushReports' from BugReporter.
-  BR.Register(new UndefBranch(this));
   BR.Register(new UndefResult(this));
   BR.Register(new NilReceiverStructRet(this));
   BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
@@ -325,4 +324,5 @@
   RegisterReturnUndefChecker(*this);
   RegisterUndefinedArraySubscriptChecker(*this);
   RegisterUndefinedAssignmentChecker(*this);
+  RegisterUndefBranchChecker(*this);
 }

Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h?rev=89640&r1=89639&r2=89640&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h Sun Nov 22 21:20:54 2009
@@ -34,6 +34,7 @@
 void RegisterArrayBoundChecker(GRExprEngine &Eng);
 void RegisterUndefinedArraySubscriptChecker(GRExprEngine &Eng);
 void RegisterUndefinedAssignmentChecker(GRExprEngine &Eng);
+void RegisterUndefBranchChecker(GRExprEngine &Eng);
 
 } // end clang namespace
 #endif

Added: cfe/trunk/lib/Analysis/UndefBranchChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UndefBranchChecker.cpp?rev=89640&view=auto

==============================================================================
--- cfe/trunk/lib/Analysis/UndefBranchChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/UndefBranchChecker.cpp Sun Nov 22 21:20:54 2009
@@ -0,0 +1,63 @@
+//=== UndefBranchChecker.cpp -----------------------------------*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines UndefBranchChecker, which checks for undefined branch
+// condition.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/Checker.h"
+
+using namespace clang;
+
+namespace {
+
+class VISIBILITY_HIDDEN UndefBranchChecker : public Checker {
+  BuiltinBug *BT;
+public:
+  UndefBranchChecker() : BT(0) {}
+  static void *getTag();
+  void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng,
+                            Stmt *Condition, void *tag);
+};
+
+}
+
+void clang::RegisterUndefBranchChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new UndefBranchChecker());
+}
+
+void *UndefBranchChecker::getTag() {
+  static int x;
+  return &x;
+}
+
+void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder, 
+                                              GRExprEngine &Eng,
+                                              Stmt *Condition, void *tag) {
+  const GRState *state = Builder.getState();
+  SVal X = state->getSVal(Condition);
+  if (X.isUndef()) {
+    ExplodedNode *N = Builder.generateNode(state, true);
+    if (N) {
+      N->markAsSink();
+      if (!BT)
+        BT = new BuiltinBug("Undefined branch",
+                 "Branch condition evaluates to an undefined or garbage value");
+      EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(),N);
+      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, 
+                           Condition);
+      Eng.getBugReporter().EmitReport(R);
+    }
+
+    Builder.markInfeasible(true);
+    Builder.markInfeasible(false);
+  }
+}





More information about the cfe-commits mailing list