[cfe-commits] r90755 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Checker.h include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/CMakeLists.txt lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.h lib/Analysis/NoReturnFunctionChecker.cpp

Zhongxing Xu xuzhongxing at gmail.com
Mon Dec 7 01:17:35 PST 2009


Author: zhongxingxu
Date: Mon Dec  7 03:17:35 2009
New Revision: 90755

URL: http://llvm.org/viewvc/llvm-project?rev=90755&view=rev
Log:
Add EvalCallExpr interface to checker, and migrate the no-return function
handler to this interface.
GRExprEngine::CheckerEvalCall() will return true if one of the checkers has
processed the node. In the future this might return void when we have some 
default checker.

Added:
    cfe/trunk/lib/Analysis/NoReturnFunctionChecker.cpp
Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/lib/Analysis/CMakeLists.txt
    cfe/trunk/lib/Analysis/GRExprEngine.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=90755&r1=90754&r2=90755&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Checker.h Mon Dec  7 03:17:35 2009
@@ -174,6 +174,14 @@
     return EvalNilReceiver(C, ME);
   }
 
+  bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder,
+                       GRExprEngine &Eng, const CallExpr *CE,
+                       ExplodedNode *Pred, void *tag) {
+    CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
+                     CE);
+    return EvalCallExpr(C, CE);
+  }
+
   // FIXME: Remove the 'tag' option.
   void GR_VisitBind(ExplodedNodeSet &Dst,
                     GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
@@ -229,6 +237,10 @@
   virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
     return false;
   }
+
+  virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
+    return false;
+  }
 };
 } // end clang namespace
 

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Dec  7 03:17:35 2009
@@ -212,6 +212,10 @@
   void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 
                     bool isPrevisit);
 
+  bool CheckerEvalCall(const CallExpr *CE, 
+                       ExplodedNodeSet &Dst, 
+                       ExplodedNode *Pred);
+
   void CheckerEvalNilReceiver(const ObjCMessageExpr *ME, 
                               ExplodedNodeSet &Dst,
                               const GRState *state,

Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=90755&r1=90754&r2=90755&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Mon Dec  7 03:17:35 2009
@@ -36,6 +36,7 @@
   MallocChecker.cpp
   ManagerRegistry.cpp
   MemRegion.cpp
+  NoReturnFunctionChecker.cpp
   NSAutoreleasePoolChecker.cpp
   NSErrorChecker.cpp
   PathDiagnostic.cpp

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Dec  7 03:17:35 2009
@@ -158,6 +158,27 @@
   }
 }
 
+// CheckerEvalCall returns true if one of the checkers processed the node.
+// This may return void when all call evaluation logic goes to some checker
+// in the future.
+bool GRExprEngine::CheckerEvalCall(const CallExpr *CE, 
+                                   ExplodedNodeSet &Dst, 
+                                   ExplodedNode *Pred) {
+  bool Evaluated = false;
+
+  for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
+    void *tag = I->first;
+    Checker *checker = I->second;
+
+    if (checker->GR_EvalCallExpr(Dst, *Builder, *this, CE, Pred, tag)) {
+      Evaluated = true;
+      break;
+    }
+  }
+
+  return Evaluated;
+}
+
 // FIXME: This is largely copy-paste from CheckerVisit().  Need to 
 // unify.
 void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
@@ -220,6 +241,9 @@
   RegisterUndefinedAssignmentChecker(Eng);
   RegisterUndefBranchChecker(Eng);
   RegisterUndefResultChecker(Eng);
+
+  // This is not a checker yet.
+  RegisterNoReturnFunctionChecker(Eng);
 }
 
 GRExprEngine::GRExprEngine(AnalysisManager &mgr)
@@ -1516,45 +1540,6 @@
 //===----------------------------------------------------------------------===//
 // Transfer function: Function calls.
 //===----------------------------------------------------------------------===//
-static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
-                                 const GRState *state,
-                                 GRStmtNodeBuilder *Builder) {
-  if (!FD)
-    return;
-
-  if (FD->getAttr<NoReturnAttr>() ||
-      FD->getAttr<AnalyzerNoReturnAttr>())
-    Builder->BuildSinks = true;
-  else {
-    // HACK: Some functions are not marked noreturn, and don't return.
-    //  Here are a few hardwired ones.  If this takes too long, we can
-    //  potentially cache these results.
-    using llvm::StringRef;
-    bool BuildSinks
-      = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName()))
-          .Case("exit", true)
-          .Case("panic", true)
-          .Case("error", true)
-          .Case("Assert", true)
-          // FIXME: This is just a wrapper around throwing an exception.
-          //  Eventually inter-procedural analysis should handle this easily.
-          .Case("ziperr", true)
-          .Case("assfail", true)
-          .Case("db_error", true)
-          .Case("__assert", true)
-          .Case("__assert_rtn", true)
-          .Case("__assert_fail", true)
-          .Case("dtrace_assfail", true)
-          .Case("yy_fatal_error", true)
-          .Case("_XCAssertionFailureHandler", true)
-          .Case("_DTAssertionFailureHandler", true)
-          .Case("_TSAssertionFailureHandler", true)
-          .Default(false);
-    
-    if (BuildSinks)
-      Builder->BuildSinks = true;
-  }
-}
 
 bool GRExprEngine::EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE,
                                        ExplodedNode *Pred,
@@ -1666,32 +1651,41 @@
     SaveAndRestore<bool> OldSink(Builder->BuildSinks);
     const FunctionDecl* FD = L.getAsFunctionDecl();
 
-    MarkNoReturnFunction(FD, CE, state, Builder);
+    ExplodedNodeSet DstTmp3, DstChecker, DstOther;
 
-    // Evaluate the call.
-    if (EvalBuiltinFunction(FD, CE, *DI, Dst))
-      continue;
+    // If the callee is processed by a checker, skip the rest logic.
+    if (CheckerEvalCall(CE, DstChecker, *DI))
+      DstTmp3 = DstChecker;
+    else {
+      //MarkNoReturnFunction(FD, CE, state, Builder);
 
-    // Dispatch to the plug-in transfer function.
-    SaveOr OldHasGen(Builder->HasGeneratedNode);
-    Pred = *DI;
+      // Evaluate the call.
+      if (EvalBuiltinFunction(FD, CE, *DI, Dst))
+        continue;
 
-    // Dispatch to transfer function logic to handle the call itself.
-    // FIXME: Allow us to chain together transfer functions.
-    assert(Builder && "GRStmtNodeBuilder must be defined.");
-    ExplodedNodeSet DstTmp;
+      // Dispatch to the plug-in transfer function.
+      SaveOr OldHasGen(Builder->HasGeneratedNode);
+      Pred = *DI;
+
+      // Dispatch to transfer function logic to handle the call itself.
+      // FIXME: Allow us to chain together transfer functions.
+      assert(Builder && "GRStmtNodeBuilder must be defined.");
     
-    if (!EvalOSAtomic(DstTmp, *this, *Builder, CE, L, Pred))
-      getTF().EvalCall(DstTmp, *this, *Builder, CE, L, Pred);
-
-    // Handle the case where no nodes where generated.  Auto-generate that
-    // contains the updated state if we aren't generating sinks.
-    if (!Builder->BuildSinks && DstTmp.empty() &&
-        !Builder->HasGeneratedNode)
-      MakeNode(DstTmp, CE, Pred, state);
     
+      if (!EvalOSAtomic(DstOther, *this, *Builder, CE, L, Pred))
+        getTF().EvalCall(DstOther, *this, *Builder, CE, L, Pred);
+
+      // Handle the case where no nodes where generated.  Auto-generate that
+      // contains the updated state if we aren't generating sinks.
+      if (!Builder->BuildSinks && DstTmp3.empty() &&
+          !Builder->HasGeneratedNode)
+        MakeNode(DstOther, CE, Pred, state);
+
+      DstTmp3 = DstOther;
+    }
+
     // Perform the post-condition check of the CallExpr.
-    CheckerVisit(CE, Dst, DstTmp, false);
+    CheckerVisit(CE, Dst, DstTmp3, false);
   }
 }
 

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h Mon Dec  7 03:17:35 2009
@@ -37,5 +37,7 @@
 void RegisterUndefBranchChecker(GRExprEngine &Eng);
 void RegisterUndefResultChecker(GRExprEngine &Eng);
 
+void RegisterNoReturnFunctionChecker(GRExprEngine &Eng);
+
 } // end clang namespace
 #endif

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

==============================================================================
--- cfe/trunk/lib/Analysis/NoReturnFunctionChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/NoReturnFunctionChecker.cpp Mon Dec  7 03:17:35 2009
@@ -0,0 +1,80 @@
+//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines NoReturnFunctionChecker, which evaluates functions that do not
+// return to the caller.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/Checker.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+
+namespace {
+
+class NoReturnFunctionChecker : public Checker {
+public:
+  static void *getTag() { static int tag = 0; return &tag; }
+  virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+
+void clang::RegisterNoReturnFunctionChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new NoReturnFunctionChecker());
+}
+
+bool NoReturnFunctionChecker::EvalCallExpr(CheckerContext &C, 
+                                           const CallExpr *CE) {
+  const GRState *state = C.getState();
+  const Expr *Callee = CE->getCallee();
+  SVal L = state->getSVal(Callee);
+  const FunctionDecl *FD = L.getAsFunctionDecl();
+  if (!FD)
+    return false;
+
+  bool BuildSinks = false;
+
+  if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>())
+    BuildSinks = true;
+  else {
+    // HACK: Some functions are not marked noreturn, and don't return.
+    //  Here are a few hardwired ones.  If this takes too long, we can
+    //  potentially cache these results.
+    using llvm::StringRef;
+    BuildSinks 
+      = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName()))
+          .Case("exit", true)
+          .Case("panic", true)
+          .Case("error", true)
+          .Case("Assert", true)
+          // FIXME: This is just a wrapper around throwing an exception.
+          //  Eventually inter-procedural analysis should handle this easily.
+          .Case("ziperr", true)
+          .Case("assfail", true)
+          .Case("db_error", true)
+          .Case("__assert", true)
+          .Case("__assert_rtn", true)
+          .Case("__assert_fail", true)
+          .Case("dtrace_assfail", true)
+          .Case("yy_fatal_error", true)
+          .Case("_XCAssertionFailureHandler", true)
+          .Case("_DTAssertionFailureHandler", true)
+          .Case("_TSAssertionFailureHandler", true)
+          .Default(false);
+  }
+  
+  if (!BuildSinks)
+    return false;
+
+  C.GenerateSink(CE);
+  return true;
+}





More information about the cfe-commits mailing list