[cfe-commits] r126606 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/CheckerManager.h include/clang/StaticAnalyzer/Core/CheckerV2.h lib/StaticAnalyzer/Checkers/Checkers.td lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp lib/StaticAnalyzer/Checkers/ExprEngine.cpp lib/StaticAnalyzer/Checkers/MallocChecker.cpp lib/StaticAnalyzer/Core/CheckerManager.cpp test/Analysis/additive-folding.c test/Analysis/free.c test/Analysis/malloc.c test/Analysis/misc-ps.m test/Analysis/no-outofbounds.c

Argyrios Kyrtzidis akyrtzi at gmail.com
Sun Feb 27 17:26:35 PST 2011


Author: akirtzidis
Date: Sun Feb 27 19:26:35 2011
New Revision: 126606

URL: http://llvm.org/viewvc/llvm-project?rev=126606&view=rev
Log:
[analyzer] Migrate MallocChecker to CheckerV2.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
    cfe/trunk/test/Analysis/additive-folding.c
    cfe/trunk/test/Analysis/free.c
    cfe/trunk/test/Analysis/malloc.c
    cfe/trunk/test/Analysis/misc-ps.m
    cfe/trunk/test/Analysis/no-outofbounds.c

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Sun Feb 27 19:26:35 2011
@@ -189,6 +189,12 @@
                               const Stmt *S,
                               ExprEngine &Eng);
 
+  /// \brief Run checkers for binding of a value to a location.
+  void runCheckersForBind(ExplodedNodeSet &Dst,
+                          const ExplodedNodeSet &Src,
+                          SVal location, SVal val,
+                          const Stmt *S, ExprEngine &Eng);
+
   /// \brief Run checkers for end of analysis.
   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
                                  ExprEngine &Eng);
@@ -214,6 +220,10 @@
                                              const MemRegion * const *Begin,
                                              const MemRegion * const *End);
 
+  /// \brief Run checkers for handling assumptions on symbolic values.
+  const GRState *runCheckersForEvalAssume(const GRState *state,
+                                          SVal Cond, bool Assumption);
+
   /// \brief Run checkers for evaluating a call.
   void runCheckersForEvalCall(ExplodedNodeSet &Dst,
                               const ExplodedNodeSet &Src,
@@ -243,6 +253,8 @@
   typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
   typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
       CheckLocationFunc;
+  typedef CheckerFn<const SVal &/*location*/, const SVal &/*val*/,
+                    CheckerContext &> CheckBindFunc;
   typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
       CheckEndAnalysisFunc;
   typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
@@ -260,6 +272,8 @@
 
   void _registerForLocation(CheckLocationFunc checkfn);
 
+  void _registerForBind(CheckBindFunc checkfn);
+
   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
 
   void _registerForEndPath(CheckEndPathFunc checkfn);
@@ -298,6 +312,21 @@
   void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
                                  WantsRegionChangeUpdateFunc wantUpdateFn);
 
+  class EvalAssumeFunc {
+    typedef const GRState * (*Func)(void *, const GRState *,
+                                    const SVal &/*cond*/, bool /*assumption*/);
+    Func Fn;
+  public:
+    void *Checker;
+    EvalAssumeFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {}
+    const GRState *operator()(const GRState *state,
+                              const SVal &cond, bool assumption) {
+      return Fn(Checker, state, cond, assumption);
+    }
+  };
+
+  void _registerForEvalAssume(EvalAssumeFunc checkfn);
+
   class EvalCallFunc {
     typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
     Func Fn;
@@ -380,6 +409,8 @@
 
   std::vector<CheckLocationFunc> LocationCheckers;
 
+  std::vector<CheckBindFunc> BindCheckers;
+
   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
 
   std::vector<CheckEndPathFunc> EndPathCheckers;
@@ -394,6 +425,8 @@
   };
   std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
 
+  std::vector<EvalAssumeFunc> EvalAssumeCheckers;
+
   std::vector<EvalCallFunc> EvalCallCheckers;
 };
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h Sun Feb 27 19:26:35 2011
@@ -145,6 +145,21 @@
   }
 };
 
+class Bind {
+  template <typename CHECKER>
+  static void _checkBind(void *checker, const SVal &location, const SVal &val,
+                         CheckerContext &C) {
+    ((const CHECKER *)checker)->checkBind(location, val, C);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForBind(
+           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
+  }
+};
+
 class EndAnalysis {
   template <typename CHECKER>
   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
@@ -232,6 +247,21 @@
 
 namespace eval {
 
+class Assume {
+  template <typename CHECKER>
+  static const GRState *_evalAssume(void *checker, const GRState *state,
+                                    const SVal &cond, bool assumption) {
+    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForEvalAssume(
+                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
+  }
+};
+
 class Call {
   template <typename CHECKER>
   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Sun Feb 27 19:26:35 2011
@@ -129,6 +129,11 @@
 
 let Group = AllExperimental in {
 
+def MallocChecker : Checker<"Malloc">,
+  InPackage<CoreExperimental>,
+  HelpText<"Check for potential memory leaks, double free, and use-after-free problems">,
+  DescFile<"MallocChecker.cpp">;
+
 def CStringChecker : Checker<"CString">,
   InPackage<CoreExperimental>,
   HelpText<"Check calls to functions in <string.h>">,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp Sun Feb 27 19:26:35 2011
@@ -22,5 +22,4 @@
 void ento::RegisterExperimentalChecks(ExprEngine &Eng) {
   // These are checks that never belong as internal checks
   // within ExprEngine.
-  RegisterMallocChecker(Eng); // ArrayBoundChecker depends on this.
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Sun Feb 27 19:26:35 2011
@@ -267,10 +267,12 @@
                                     SVal val, bool isPrevisit) {
 
   if (Checkers.empty()) {
-    Dst.insert(Src);
+    getCheckerManager().runCheckersForBind(Dst, Src, location, val, StoreE,
+                                           *this);
     return;
   }
 
+  ExplodedNodeSet CheckerV1Tmp;
   ExplodedNodeSet Tmp;
   ExplodedNodeSet *PrevSet = &Src;
 
@@ -278,7 +280,7 @@
   {
     ExplodedNodeSet *CurrSet = 0;
     if (I+1 == E)
-      CurrSet = &Dst;
+      CurrSet = &CheckerV1Tmp;
     else {
       CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
       CurrSet->clear();
@@ -296,6 +298,9 @@
     PrevSet = CurrSet;
   }
 
+  getCheckerManager().runCheckersForBind(Dst, CheckerV1Tmp, location, val,
+                                         StoreE, *this);
+  
   // Don't autotransition.  The CheckerContext objects should do this
   // automatically.
 }
@@ -493,6 +498,8 @@
       CO_Ref = NewCO.take();
   }
 
+  state = getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
+
   // If the state is infeasible at this point, bail out.
   if (!state)
     return NULL;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Sun Feb 27 19:26:35 2011
@@ -12,9 +12,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ExperimentalChecks.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -62,55 +64,52 @@
 
 class RegionState {};
 
-class MallocChecker : public CheckerVisitor<MallocChecker> {
-  BuiltinBug *BT_DoubleFree;
-  BuiltinBug *BT_Leak;
-  BuiltinBug *BT_UseFree;
-  BuiltinBug *BT_UseRelinquished;
-  BuiltinBug *BT_BadFree;
-  IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
+class MallocChecker : public CheckerV2<eval::Call, check::DeadSymbols, check::EndPath, check::PreStmt<ReturnStmt>, check::Location,
+                               check::Bind, eval::Assume> {
+  mutable llvm::OwningPtr<BuiltinBug> BT_DoubleFree;
+  mutable llvm::OwningPtr<BuiltinBug> BT_Leak;
+  mutable llvm::OwningPtr<BuiltinBug> BT_UseFree;
+  mutable llvm::OwningPtr<BuiltinBug> BT_UseRelinquished;
+  mutable llvm::OwningPtr<BuiltinBug> BT_BadFree;
+  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
 
 public:
-  MallocChecker() 
-    : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_UseRelinquished(0),
-      BT_BadFree(0),
-      II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
-  static void *getTag();
-  bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
-  void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
-  void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
-  void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
-  const GRState *evalAssume(const GRState *state, SVal Cond, bool Assumption,
-                            bool *respondsToCallback);
-  void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
-  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
-                            SVal location, SVal val);
+  MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
+
+  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+  void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
+  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+  const GRState *evalAssume(const GRState *state, SVal Cond,
+                            bool Assumption) const;
+  void checkLocation(SVal l, bool isLoad, CheckerContext &C) const;
+  void checkBind(SVal location, SVal val, CheckerContext &C) const;
 
 private:
-  void MallocMem(CheckerContext &C, const CallExpr *CE);
-  void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
-                            const OwnershipAttr* Att);
-  const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
-                              const Expr *SizeEx, SVal Init,
-                              const GRState *state) {
+  static void MallocMem(CheckerContext &C, const CallExpr *CE);
+  static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+                                   const OwnershipAttr* Att);
+  static const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
+                                     const Expr *SizeEx, SVal Init,
+                                     const GRState *state) {
     return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state);
   }
-  const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
-                              SVal SizeEx, SVal Init,
-                              const GRState *state);
+  static const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
+                                     SVal SizeEx, SVal Init,
+                                     const GRState *state);
 
-  void FreeMem(CheckerContext &C, const CallExpr *CE);
+  void FreeMem(CheckerContext &C, const CallExpr *CE) const;
   void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
-                   const OwnershipAttr* Att);
+                   const OwnershipAttr* Att) const;
   const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
-                            const GRState *state, unsigned Num, bool Hold);
+                           const GRState *state, unsigned Num, bool Hold) const;
 
-  void ReallocMem(CheckerContext &C, const CallExpr *CE);
-  void CallocMem(CheckerContext &C, const CallExpr *CE);
+  void ReallocMem(CheckerContext &C, const CallExpr *CE) const;
+  static void CallocMem(CheckerContext &C, const CallExpr *CE);
   
-  bool SummarizeValue(llvm::raw_ostream& os, SVal V);
-  bool SummarizeRegion(llvm::raw_ostream& os, const MemRegion *MR);
-  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range);
+  static bool SummarizeValue(llvm::raw_ostream& os, SVal V);
+  static bool SummarizeRegion(llvm::raw_ostream& os, const MemRegion *MR);
+  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const;
 };
 } // end anonymous namespace
 
@@ -121,21 +120,12 @@
   template <>
   struct GRStateTrait<RegionState> 
     : public GRStatePartialTrait<RegionStateTy> {
-    static void *GDMIndex() { return MallocChecker::getTag(); }
+    static void *GDMIndex() { static int x; return &x; }
   };
 }
 }
 
-void ento::RegisterMallocChecker(ExprEngine &Eng) {
-  Eng.registerCheck(new MallocChecker());
-}
-
-void *MallocChecker::getTag() {
-  static int x;
-  return &x;
-}
-
-bool MallocChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
   const GRState *state = C.getState();
   const Expr *Callee = CE->getCallee();
   SVal L = state->getSVal(Callee);
@@ -256,7 +246,7 @@
   return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE));
 }
 
-void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
+void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const {
   const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false);
 
   if (state)
@@ -264,7 +254,7 @@
 }
 
 void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
-                                const OwnershipAttr* Att) {
+                                const OwnershipAttr* Att) const {
   if (Att->getModule() != "malloc")
     return;
 
@@ -279,7 +269,7 @@
 
 const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
                                          const GRState *state, unsigned Num,
-                                         bool Hold) {
+                                         bool Hold) const {
   const Expr *ArgExpr = CE->getArg(Num);
   SVal ArgVal = state->getSVal(ArgExpr);
 
@@ -357,9 +347,9 @@
   if (RS->isReleased()) {
     if (ExplodedNode *N = C.generateSink()) {
       if (!BT_DoubleFree)
-        BT_DoubleFree
-          = new BuiltinBug("Double free",
-                         "Try to free a memory block that has been released");
+        BT_DoubleFree.reset(
+          new BuiltinBug("Double free",
+                         "Try to free a memory block that has been released"));
       // FIXME: should find where it's freed last time.
       BugReport *R = new BugReport(*BT_DoubleFree, 
                                    BT_DoubleFree->getDescription(), N);
@@ -463,10 +453,10 @@
 }
 
 void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
-                                  SourceRange range) {
+                                  SourceRange range) const {
   if (ExplodedNode *N = C.generateSink()) {
     if (!BT_BadFree)
-      BT_BadFree = new BuiltinBug("Bad free");
+      BT_BadFree.reset(new BuiltinBug("Bad free"));
     
     llvm::SmallString<100> buf;
     llvm::raw_svector_ostream os(buf);
@@ -500,7 +490,7 @@
   }
 }
 
-void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
+void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
   const GRState *state = C.getState();
   const Expr *arg0Expr = CE->getArg(0);
   DefinedOrUnknownSVal arg0Val 
@@ -562,7 +552,8 @@
   C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state));
 }
 
-void MallocChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper)
+void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                     CheckerContext &C) const
 {
   if (!SymReaper.hasDeadSymbols())
     return;
@@ -576,8 +567,8 @@
       if (I->second.isAllocated()) {
         if (ExplodedNode *N = C.generateNode()) {
           if (!BT_Leak)
-            BT_Leak = new BuiltinBug("Memory leak",
-                     "Allocated memory never released. Potential memory leak.");
+            BT_Leak.reset(new BuiltinBug("Memory leak",
+                    "Allocated memory never released. Potential memory leak."));
           // FIXME: where it is allocated.
           BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
           C.EmitReport(R);
@@ -591,8 +582,8 @@
   C.generateNode(state->set<RegionState>(RS));
 }
 
-void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
-                                ExprEngine &Eng) {
+void MallocChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
+                                 ExprEngine &Eng) const {
   const GRState *state = B.getState();
   RegionStateTy M = state->get<RegionState>();
 
@@ -602,8 +593,8 @@
       ExplodedNode *N = B.generateNode(state);
       if (N) {
         if (!BT_Leak)
-          BT_Leak = new BuiltinBug("Memory leak",
-                     "Allocated memory never released. Potential memory leak.");
+          BT_Leak.reset(new BuiltinBug("Memory leak",
+                    "Allocated memory never released. Potential memory leak."));
         BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
         Eng.getBugReporter().EmitReport(R);
       }
@@ -611,7 +602,7 @@
   }
 }
 
-void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
   const Expr *retExpr = S->getRetValue();
   if (!retExpr)
     return;
@@ -634,8 +625,7 @@
 }
 
 const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond, 
-                                         bool Assumption,
-                                         bool * /* respondsToCallback */) {
+                                         bool Assumption) const {
   // If a symblic region is assumed to NULL, set its state to AllocateFailed.
   // FIXME: should also check symbols assumed to non-null.
 
@@ -650,16 +640,15 @@
 }
 
 // Check if the location is a freed symbolic region.
-void MallocChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
-                                  bool isLoad) {
+void MallocChecker::checkLocation(SVal l, bool isLoad,CheckerContext &C) const {
   SymbolRef Sym = l.getLocSymbolInBase();
   if (Sym) {
     const RefState *RS = C.getState()->get<RegionState>(Sym);
     if (RS && RS->isReleased()) {
       if (ExplodedNode *N = C.generateNode()) {
         if (!BT_UseFree)
-          BT_UseFree = new BuiltinBug("Use dynamically allocated memory after"
-                                      " it is freed.");
+          BT_UseFree.reset(new BuiltinBug("Use dynamically allocated memory "
+                                          "after it is freed."));
 
         BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),
                                      N);
@@ -669,10 +658,7 @@
   }
 }
 
-void MallocChecker::PreVisitBind(CheckerContext &C,
-                                 const Stmt *StoreE,
-                                 SVal location,
-                                 SVal val) {
+void MallocChecker::checkBind(SVal location, SVal val,CheckerContext &C) const {
   // The PreVisitBind implements the same algorithm as already used by the 
   // Objective C ownership checker: if the pointer escaped from this scope by 
   // assignment, let it go.  However, assigning to fields of a stack-storage 
@@ -721,7 +707,7 @@
           // We no longer own this pointer.
           notNullState =
             notNullState->set<RegionState>(Sym,
-                                           RefState::getRelinquished(StoreE));
+                                        RefState::getRelinquished(C.getStmt()));
         }
         while (false);
       }
@@ -729,3 +715,7 @@
     }
   }
 }
+
+void ento::registerMallocChecker(CheckerManager &mgr) {
+  mgr.registerChecker<MallocChecker>();
+}

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Sun Feb 27 19:26:35 2011
@@ -205,6 +205,40 @@
   expandGraphWithCheckers(C, Dst, Src);
 }
 
+namespace {
+  struct CheckBindContext {
+    typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
+    const CheckersTy &Checkers;
+    SVal Loc;
+    SVal Val;
+    const Stmt *S;
+    ExprEngine &Eng;
+
+    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+    CheckBindContext(const CheckersTy &checkers,
+                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng)
+      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { }
+
+    void runChecker(CheckerManager::CheckBindFunc checkFn,
+                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+                       ProgramPoint::PreStmtKind, 0, S);
+      checkFn(Loc, Val, C);
+    }
+  };
+}
+
+/// \brief Run checkers for binding of a value to a location.
+void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
+                                        const ExplodedNodeSet &Src,
+                                        SVal location, SVal val,
+                                        const Stmt *S, ExprEngine &Eng) {
+  CheckBindContext C(BindCheckers, location, val, S, Eng);
+  expandGraphWithCheckers(C, Dst, Src);
+}
+
 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
                                                BugReporter &BR,
                                                ExprEngine &Eng) {
@@ -287,6 +321,20 @@
   return state;
 }
 
+/// \brief Run checkers for handling assumptions on symbolic values.
+const GRState *
+CheckerManager::runCheckersForEvalAssume(const GRState *state,
+                                         SVal Cond, bool Assumption) {
+  for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
+    // If any checker declares the state infeasible (or if it starts that way),
+    // bail out.
+    if (!state)
+      return NULL;
+    state = EvalAssumeCheckers[i](state, Cond, Assumption);
+  }
+  return state;
+}
+
 /// \brief Run checkers for evaluating a call.
 /// Only one checker will evaluate the call.
 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
@@ -371,6 +419,10 @@
   LocationCheckers.push_back(checkfn);
 }
 
+void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
+  BindCheckers.push_back(checkfn);
+}
+
 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
   EndAnalysisCheckers.push_back(checkfn);
 }
@@ -393,6 +445,10 @@
   RegionChangesCheckers.push_back(info);
 }
 
+void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
+  EvalAssumeCheckers.push_back(checkfn);
+}
+
 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
   EvalCallCheckers.push_back(checkfn);
 }

Modified: cfe/trunk/test/Analysis/additive-folding.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding.c?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/additive-folding.c (original)
+++ cfe/trunk/test/Analysis/additive-folding.c Sun Feb 27 19:26:35 2011
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-checker=core.experimental.UnreachableCode -verify -analyzer-constraints=basic %s
-// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-checker=core.experimental.UnreachableCode -verify -analyzer-constraints=range %s
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.experimental.UnreachableCode,core.experimental.Malloc -verify -analyzer-constraints=basic %s
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core.experimental.UnreachableCode,core.experimental.Malloc -verify -analyzer-constraints=range %s
 
 // These are used to trigger warnings.
 typedef typeof(sizeof(int)) size_t;

Modified: cfe/trunk/test/Analysis/free.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/free.c?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/free.c (original)
+++ cfe/trunk/test/Analysis/free.c Sun Feb 27 19:26:35 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-checker=core.experimental.Malloc -fblocks -verify %s
 void free(void *);
 
 void t1 () {

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Sun Feb 27 19:26:35 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.UnreachableCode,core.experimental.CastSize -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.experimental.UnreachableCode,core.experimental.CastSize,core.experimental.Malloc -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store=region -verify %s
 typedef __typeof(sizeof(int)) size_t;
 void *malloc(size_t);
 void free(void *);

Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Sun Feb 27 19:26:35 2011
@@ -1,10 +1,10 @@
 // NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued.
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-disable-checker=core.experimental.Malloc -analyzer-check-objc-mem -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-disable-checker=core.experimental.Malloc -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s
 // RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s
 // RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-disable-checker=core.experimental.Malloc -analyzer-check-objc-mem -analyzer-store=basic -fobjc-gc -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-disable-checker=core.experimental.Malloc -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify -fblocks -Wno-unreachable-code %s
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core.experimental,cocoa.AtSync -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code %s
 

Modified: cfe/trunk/test/Analysis/no-outofbounds.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/no-outofbounds.c?rev=126606&r1=126605&r2=126606&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/no-outofbounds.c (original)
+++ cfe/trunk/test/Analysis/no-outofbounds.c Sun Feb 27 19:26:35 2011
@@ -25,7 +25,9 @@
 
 void field() {
   struct vec { size_t len; int data[0]; };
-  struct vec *a = malloc(sizeof(struct vec) + 10);
+  // FIXME: Not warn for this.
+  struct vec *a = malloc(sizeof(struct vec) + 10); // expected-warning {{Cast a region whose size is not a multiple of the destination type size}}
   a->len = 10;
   a->data[1] = 5; // no-warning
+  free(a);
 }





More information about the cfe-commits mailing list