]> granicus.if.org Git - clang/commitdiff
Moved registration of basic path-sensitive checks from GRSimpleVals.cpp to GRExprEngi...
authorTed Kremenek <kremenek@apple.com>
Tue, 22 Jul 2008 16:21:24 +0000 (16:21 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 22 Jul 2008 16:21:24 +0000 (16:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53909 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/AnalysisConsumer.cpp
include/clang/Analysis/LocalCheckers.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
lib/Analysis/BasicObjCFoundationChecks.cpp
lib/Analysis/CFRefCount.cpp
lib/Analysis/GRExprEngineInternalChecks.cpp [new file with mode: 0644]
lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRSimpleVals.h

index 45e0918ce0811254c96df39199150a00c225b871..deb7a85006c851f333e2869717d88a2b9b0e8bf3 100644 (file)
@@ -298,7 +298,8 @@ static void ActionWarnUninitVals(AnalysisManager& mgr) {
 }
 
 
-static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf) {
+static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
+                               bool StandardWarnings = true) {
   
   
   llvm::OwningPtr<GRTransferFuncs> TF(tf);
@@ -314,6 +315,11 @@ static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf) {
   GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L);
   Eng.setTransferFunctions(tf);
   
+  if (StandardWarnings) {
+    Eng.RegisterInternalChecks();
+    RegisterAppleChecks(Eng);
+  }
+  
   // Execute the worklist algorithm.
   Eng.ExecuteWorkList();
   
@@ -326,14 +332,13 @@ static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf) {
 }
 
 static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
-                                    bool StandardWarnings) {
-
+                                  bool StandardWarnings) {
+  
   GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
                                          GCEnabled,
-                                         StandardWarnings,
                                          mgr.getLangOptions());
     
-  ActionGRExprEngine(mgr, TF);
+  ActionGRExprEngine(mgr, TF, StandardWarnings);
 }
 
 static void ActionCheckerCFRef(AnalysisManager& mgr) {
index a8669d30a7c43b41a3c090418327d21f027f3d73..8da144ebce112f8fd55e26d7e892958abc1c8605 100644 (file)
@@ -30,6 +30,7 @@ class LiveVariables;
 class BugReporter;
 class ObjCImplementationDecl;
 class LangOptions;
+class GRExprEngine;
   
 void CheckDeadStores(LiveVariables& L, BugReporter& BR); 
   
@@ -38,7 +39,6 @@ void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
   
 GRTransferFuncs* MakeGRSimpleValsTF();
 GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
-                                  bool StandardWarnings,
                                   const LangOptions& lopts); 
   
 void CheckObjCDealloc(ObjCImplementationDecl* D, const LangOptions& L,
@@ -46,6 +46,8 @@ void CheckObjCDealloc(ObjCImplementationDecl* D, const LangOptions& L,
   
 void CheckObjCInstMethSignature(ObjCImplementationDecl* ID, BugReporter& BR);
   
+void RegisterAppleChecks(GRExprEngine& Eng);
+  
 } // end namespace clang
 
 #endif
index 0a0516e6024c5203319a32e5ad89d072b8fa36c3..e9a36af295012f3df41902d0004c00ac76b4ae4d 100644 (file)
@@ -220,6 +220,8 @@ public:
     BugTypes.push_back(B);
   }
   
+  void RegisterInternalChecks();
+  
   void EmitWarnings(BugReporterData& BRData);  
   
   bool isRetStackAddr(const NodeTy* N) const {
index 37cfc280b8f1ab6a5cedff5013c721714f5dafbb..7009e3842500d0d58454b93ef9ff9bf8e2b96c2c 100644 (file)
 
 #include "clang/Analysis/PathSensitive/ExplodedGraph.h"
 #include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "clang/Analysis/PathSensitive/ValueState.h"
 #include "clang/Analysis/PathSensitive/BugReporter.h"
 #include "clang/Analysis/PathDiagnostic.h"
+#include "clang/Analysis/LocalCheckers.h"
+
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ASTContext.h"
@@ -547,3 +550,15 @@ clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
   return new AuditCFNumberCreate(Ctx, VMgr);  
 }
 
+//===----------------------------------------------------------------------===//
+// Check registration.
+
+void clang::RegisterAppleChecks(GRExprEngine& Eng) {
+  ASTContext& Ctx = Eng.getContext();
+  ValueStateManager* VMgr = &Eng.getStateManager();
+
+  Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, VMgr),
+               Stmt::ObjCMessageExprClass);
+
+  Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, VMgr), Stmt::CallExprClass);
+}
index bd9ac40f98181d54f5e24db43fc4eea9fddc6b06..edcddd22a5580c3ab6a8b2b5ecfc31d661cda55f 100644 (file)
@@ -1244,7 +1244,6 @@ private:
   // Instance variables.
   
   RetainSummaryManager Summaries;  
-  const bool           EmitStandardWarnings;  
   const LangOptions&   LOpts;
   RefBFactoryTy        RefBFactory;
      
@@ -1293,10 +1292,8 @@ private:
   
 public:
   
-  CFRefCount(ASTContext& Ctx, bool gcenabled, bool StandardWarnings,
-             const LangOptions& lopts)
+  CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
     : Summaries(Ctx, gcenabled),
-      EmitStandardWarnings(StandardWarnings),
       LOpts(lopts),
       RetainSelector(GetNullarySelector("retain", Ctx)),
       ReleaseSelector(GetNullarySelector("release", Ctx)),
@@ -2223,7 +2220,6 @@ namespace {
 } // end anonymous namespace
 
 void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
-  if (EmitStandardWarnings) GRSimpleVals::RegisterChecks(Eng);
   Eng.Register(new UseAfterRelease(*this));
   Eng.Register(new BadRelease(*this));
   Eng.Register(new Leak(*this));
@@ -2593,7 +2589,6 @@ bool Leak::isCached(BugReport& R) {
 //===----------------------------------------------------------------------===//
 
 GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
-                                         bool StandardWarnings,
                                          const LangOptions& lopts) {
-  return new CFRefCount(Ctx, GCEnabled, StandardWarnings, lopts);
+  return new CFRefCount(Ctx, GCEnabled, lopts);
 }  
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
new file mode 100644 (file)
index 0000000..c1128cc
--- /dev/null
@@ -0,0 +1,332 @@
+//=-- GRExprEngineInternalChecks.cpp - Builtin GRExprEngine Checks---*- 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 the BugType classes used by GRExprEngine to report
+//  bugs derived from builtin checks in the path-sensitive engine.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "llvm/Support/Compiler.h"
+
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
+template <typename ITERATOR> inline
+ExplodedNode<ValueState>* GetNode(ITERATOR I) {
+  return *I;
+}
+
+template <> inline
+ExplodedNode<ValueState>* GetNode(GRExprEngine::undef_arg_iterator I) {
+  return I->first;
+}
+
+//===----------------------------------------------------------------------===//
+// Bug Descriptions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VISIBILITY_HIDDEN BuiltinBug : public BugTypeCacheLocation {
+  const char* name;
+  const char* desc;
+public:
+  BuiltinBug(const char* n, const char* d) : name(n), desc(d) {}  
+  virtual const char* getName() const { return name; }
+  virtual const char* getDescription() const { return desc; }
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) = 0;
+  virtual void EmitWarnings(BugReporter& BR) {
+    EmitBuiltinWarnings(BR, cast<GRBugReporter>(BR).getEngine());
+  }
+  
+  template <typename ITER>
+  void Emit(BugReporter& BR, ITER I, ITER E) {
+    for (; I != E; ++I) {
+      BugReport R(*this, GetNode(I));
+      BR.EmitWarning(R);
+    }
+  }
+};
+  
+class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
+public:
+  NullDeref() : BuiltinBug("null dereference",
+                           "Dereference of null pointer.") {}
+
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
+  }
+};
+  
+class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
+public:
+  UndefinedDeref() : BuiltinBug("bad dereference",
+                                "Dereference of undefined value.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
+  }
+};
+
+class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
+public:
+  DivZero() : BuiltinBug("divide-by-zero",
+                         "Division by zero/undefined value.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
+  }
+};
+  
+class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
+public:
+  UndefResult() : BuiltinBug("undefined result",
+                             "Result of operation is undefined.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
+  }
+};
+  
+class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
+public:
+  BadCall()
+  : BuiltinBug("invalid function call",
+        "Called function is a NULL or undefined function pointer value.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
+  }
+};
+
+class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
+public:
+  BadArg() : BuiltinBug("bad argument",  
+    "Pass-by-value argument in function is undefined.") {}
+
+  BadArg(const char* d) : BuiltinBug("bad argument", d) {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
+         E = Eng.undef_arg_end(); I!=E; ++I) {
+
+      // Generate a report for this bug.
+      RangedBugReport report(*this, I->first);
+      report.addRange(I->second->getSourceRange());
+
+      // Emit the warning.
+      BR.EmitWarning(report);
+    }
+  }
+};
+  
+class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
+public:
+  BadMsgExprArg() 
+    : BadArg("Pass-by-value argument in message expression is undefined.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
+         E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
+      
+      // Generate a report for this bug.
+      RangedBugReport report(*this, I->first);
+      report.addRange(I->second->getSourceRange());
+      
+      // Emit the warning.
+      BR.EmitWarning(report);
+    }    
+  }
+};
+  
+class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
+public:  
+  BadReceiver()
+  : BuiltinBug("bad receiver",
+               "Receiver in message expression is an uninitialized value.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
+         End = Eng.undef_receivers_end(); I!=End; ++I) {
+      
+      // Generate a report for this bug.
+      RangedBugReport report(*this, *I);
+      
+      ExplodedNode<ValueState>* N = *I;
+      Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
+      Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
+      assert (E && "Receiver cannot be NULL");
+      report.addRange(E->getSourceRange());
+      
+      // Emit the warning.
+      BR.EmitWarning(report);
+    }    
+  }
+};
+  
+class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
+public:
+  RetStack() : BuiltinBug("return of stack address",
+                          "Address of stack-allocated variable returned.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    Emit(BR, Eng.ret_stackaddr_begin(), Eng.ret_stackaddr_end());
+  }
+};
+
+
+class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
+  struct VISIBILITY_HIDDEN FindUndefExpr {
+    ValueStateManager& VM;
+    const ValueState* St;
+    
+    FindUndefExpr(ValueStateManager& V, const ValueState* S) : VM(V), St(S) {}
+    
+    Expr* FindExpr(Expr* Ex) {
+      
+      if (!MatchesCriteria(Ex))
+        return 0;    
+      
+      for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end(); I!=E; ++I)
+        if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
+          Expr* E2 = FindExpr(ExI);
+          if (E2) return E2;
+        }
+      
+      return Ex;
+    }
+    
+    bool MatchesCriteria(Expr* Ex) { return VM.GetRVal(St, Ex).isUndef(); }
+  };
+  
+public:
+  UndefBranch()
+    : BuiltinBug("uninitialized value",
+                 "Branch condition evaluates to an uninitialized value.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
+         E=Eng.undef_branches_end(); I!=E; ++I) {
+
+      // What's going on here: we want to highlight the subexpression of the
+      // condition that is the most likely source of the "uninitialized
+      // branch condition."  We do a recursive walk of the condition's
+      // subexpressions and roughly look for the most nested subexpression
+      // that binds to Undefined.  We then highlight that expression's range.
+
+      BlockEdge B = cast<BlockEdge>((*I)->getLocation());
+      Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
+      assert (Ex && "Block must have a terminator.");
+
+      // Get the predecessor node and check if is a PostStmt with the Stmt
+      // being the terminator condition.  We want to inspect the state
+      // of that node instead because it will contain main information about
+      // the subexpressions.
+
+      assert (!(*I)->pred_empty());
+
+      // Note: any predecessor will do.  They should have identical state,
+      // since all the BlockEdge did was act as an error sink since the value
+      // had to already be undefined.
+      ExplodedNode<ValueState> *N = *(*I)->pred_begin();
+      ProgramPoint P = N->getLocation();
+
+      const ValueState* St = (*I)->getState();
+
+      if (PostStmt* PS = dyn_cast<PostStmt>(&P))
+        if (PS->getStmt() == Ex)
+          St = N->getState();
+
+      FindUndefExpr FindIt(Eng.getStateManager(), St);
+      Ex = FindIt.FindExpr(Ex);
+
+      RangedBugReport R(*this, *I);
+      R.addRange(Ex->getSourceRange());
+
+      BR.EmitWarning(R);
+    }
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// __attribute__(nonnull) checking
+
+class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
+  SimpleBugType BT;
+  std::list<RangedBugReport> Reports;
+  
+public:
+  CheckAttrNonNull() :
+  BT("'nonnull' argument passed null",
+     "Null pointer passed as an argument to a 'nonnull' parameter") {}
+
+  virtual bool Audit(ExplodedNode<ValueState>* N, ValueStateManager& VMgr) {
+    CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
+    const ValueState* state = N->getState();
+    
+    RVal X = VMgr.GetRVal(state, CE->getCallee());
+    
+    if (!isa<lval::FuncVal>(X))
+      return false;
+    
+    FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
+    const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+    
+    if (!Att)
+      return false;
+    
+    // Iterate through the arguments of CE and check them for null.
+    
+    unsigned idx = 0;
+    bool hasError = false;
+    
+    for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
+         ++I, ++idx) {
+      
+      if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
+        continue;
+      
+      RangedBugReport R(BT, N);
+      R.addRange((*I)->getSourceRange());
+      Reports.push_back(R);
+      hasError = true;
+    }
+    
+    return hasError;
+  }
+  
+  virtual void EmitWarnings(BugReporter& BR) {
+    for (std::list<RangedBugReport>::iterator I=Reports.begin(),
+         E=Reports.end(); I!=E; ++I)
+      BR.EmitWarning(*I);
+  }
+};
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Check registration.
+
+void GRExprEngine::RegisterInternalChecks() {
+  Register(new NullDeref());
+  Register(new UndefinedDeref());
+  Register(new UndefBranch());
+  Register(new DivZero());
+  Register(new UndefResult());
+  Register(new BadCall());
+  Register(new RetStack());
+  Register(new BadArg());
+  Register(new BadMsgExprArg());
+  Register(new BadReceiver());
+  AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass); 
+}
index 38327cbad5b2351dcaad61e5c8a623358a9dd9d9..395252006432b3255db0bd79f1528e355f711d0a 100644 (file)
 
 using namespace clang;
 
-//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-template <typename ITERATOR> inline
-ExplodedNode<ValueState>* GetNode(ITERATOR I) {
-  return *I;
-}
-
-template <> inline
-ExplodedNode<ValueState>* GetNode(GRExprEngine::undef_arg_iterator I) {
-  return I->first;
-}
-
-template <typename ITER>
-void GenericEmitWarnings(BugReporter& BR, BugType& D, ITER I, ITER E) {
-  
-  for (; I != E; ++I) {
-    BugReport R(D, GetNode(I));    
-    BR.EmitWarning(R);
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Bug Descriptions.
-//===----------------------------------------------------------------------===//
-
-namespace {
-  
-class VISIBILITY_HIDDEN NullDeref : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "null dereference";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Dereference of null pointer.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    GenericEmitWarnings(BR, *this, Eng.null_derefs_begin(),
-                        Eng.null_derefs_end());
-  }
-};
-
-class VISIBILITY_HIDDEN UndefDeref : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "bad dereference";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Dereference of undefined value.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    GenericEmitWarnings(BR, *this, Eng.undef_derefs_begin(),
-                        Eng.undef_derefs_end());
-  }
-};
-  
-class VISIBILITY_HIDDEN UndefBranch : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "uninitialized value";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Branch condition evaluates to an uninitialized value.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR);
-};
-  
-class VISIBILITY_HIDDEN DivZero : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "divide-by-zero";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Division by zero/undefined value.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    GenericEmitWarnings(BR, *this, Eng.explicit_bad_divides_begin(),
-                        Eng.explicit_bad_divides_end());
-  }
-};
-
-class VISIBILITY_HIDDEN UndefResult : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "undefined result";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Result of operation is undefined.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    GenericEmitWarnings(BR, *this, Eng.undef_results_begin(),
-                        Eng.undef_results_end());
-  }
-};
-  
-class VISIBILITY_HIDDEN BadCall : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "invalid function call";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Called function is a NULL or undefined function pointer value.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    GenericEmitWarnings(BR, *this, Eng.bad_calls_begin(),
-                        Eng.bad_calls_end());
-  }
-};
-  
-  
-class VISIBILITY_HIDDEN BadArg : public BugTypeCacheLocation {
-public:
-  
-  virtual ~BadArg() {}
-  
-  virtual const char* getName() const {
-    return "bad argument";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Pass-by-value argument in function is undefined.";
-  }  
-
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-
-    for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
-         E = Eng.undef_arg_end(); I!=E; ++I) {
-      
-      // Generate a report for this bug.
-      RangedBugReport report(*this, I->first);
-      report.addRange(I->second->getSourceRange());
-
-      // Emit the warning.
-      BR.EmitWarning(report);
-    }
-
-  }
-};
-  
-class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
-public:
-  virtual const char* getName() const {
-    return "bad argument";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Pass-by-value argument in message expression is undefined.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    
-    for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
-         E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
-      
-      // Generate a report for this bug.
-      RangedBugReport report(*this, I->first);
-      report.addRange(I->second->getSourceRange());
-      
-      // Emit the warning.
-      BR.EmitWarning(report);
-    }    
-  }
-};
-
-class VISIBILITY_HIDDEN BadReceiver : public BugTypeCacheLocation {
-public:  
-  virtual const char* getName() const {
-    return "bad receiver";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Receiver in message expression is an uninitialized value.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    
-    for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
-         End = Eng.undef_receivers_end(); I!=End; ++I) {
-          
-      // Generate a report for this bug.
-      RangedBugReport report(*this, *I);
-      
-      ExplodedNode<ValueState>* N = *I;
-      Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
-      Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
-      assert (E && "Receiver cannot be NULL");
-      report.addRange(E->getSourceRange());
-      
-      // Emit the warning.
-      BR.EmitWarning(report);
-    }    
-  }
-};
-  
-class VISIBILITY_HIDDEN RetStack : public BugTypeCacheLocation {
-public:
-  virtual const char* getName() const {
-    return "return of stack address";
-  }
-  
-  virtual const char* getDescription() const {
-    return "Address of stack-allocated variable returned.";
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-    GenericEmitWarnings(BR, *this, Eng.ret_stackaddr_begin(),
-                        Eng.ret_stackaddr_end());
-  }
-};
-  
-} // end anonymous namespace
-
-
-namespace {
-
-struct VISIBILITY_HIDDEN FindUndefExpr {
-  ValueStateManager& VM;
-  const ValueState* St;
-  
-  FindUndefExpr(ValueStateManager& V, const ValueState* S) : VM(V), St(S) {}
-  
-  Expr* FindExpr(Expr* Ex) {
-    
-    if (!MatchesCriteria(Ex))
-      return 0;    
-        
-    for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end(); I!=E; ++I)
-      if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
-        Expr* E2 = FindExpr(ExI);
-        if (E2) return E2;
-      }
-    
-    return Ex;
-  }
-  
-  bool MatchesCriteria(Expr* Ex) { return VM.GetRVal(St, Ex).isUndef(); }  
-};
-  
-} // end anonymous namespace
-  
-  
-void UndefBranch::EmitWarnings(BugReporter& BR) {
-
-  GRExprEngine& Eng = cast<GRBugReporter>(BR).getEngine();
-  
-  for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
-       E=Eng.undef_branches_end(); I!=E; ++I) {
-
-    // What's going on here: we want to highlight the subexpression of the
-    // condition that is the most likely source of the "uninitialized
-    // branch condition."  We do a recursive walk of the condition's
-    // subexpressions and roughly look for the most nested subexpression
-    // that binds to Undefined.  We then highlight that expression's range.
-    
-    BlockEdge B = cast<BlockEdge>((*I)->getLocation());
-    Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
-    assert (Ex && "Block must have a terminator.");
-    
-    // Get the predecessor node and check if is a PostStmt with the Stmt
-    // being the terminator condition.  We want to inspect the state
-    // of that node instead because it will contain main information about
-    // the subexpressions.
-    
-    assert (!(*I)->pred_empty());
-    
-    // Note: any predecessor will do.  They should have identical state,
-    // since all the BlockEdge did was act as an error sink since the value
-    // had to already be undefined.
-    ExplodedNode<ValueState> *N = *(*I)->pred_begin();
-    ProgramPoint P = N->getLocation();
-
-    const ValueState* St = (*I)->getState();
-    
-    if (PostStmt* PS = dyn_cast<PostStmt>(&P))
-      if (PS->getStmt() == Ex)
-        St = N->getState();
-        
-    FindUndefExpr FindIt(Eng.getStateManager(), St);
-    Ex = FindIt.FindExpr(Ex);
-    
-    RangedBugReport R(*this, *I);
-    R.addRange(Ex->getSourceRange());
-    
-    BR.EmitWarning(R);
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// __attribute__(nonnull) checking
-
-class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
-  SimpleBugType BT;
-  std::list<RangedBugReport> Reports;
-
-public:
-  CheckAttrNonNull() :
-    BT("'nonnull' argument passed null",
-       "Null pointer passed as an argument to a 'nonnull' parameter") {}
-  
-
-  virtual bool Audit(ExplodedNode<ValueState>* N, ValueStateManager& VMgr) {
-    CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
-    const ValueState* state = N->getState();
-    
-    RVal X = VMgr.GetRVal(state, CE->getCallee());
-
-    if (!isa<lval::FuncVal>(X))
-      return false;
-    
-    FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
-    const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
-    
-    if (!Att)
-      return false;
-    
-    // Iterate through the arguments of CE and check them for null.
-    
-    unsigned idx = 0;
-    bool hasError = false;
-    
-    for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
-         ++I, ++idx) {
-    
-      if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
-        continue;
-      
-      RangedBugReport R(BT, N);
-      R.addRange((*I)->getSourceRange());
-      Reports.push_back(R);
-      hasError = true;
-    }
-    
-    return hasError;
-  }
-  
-  virtual void EmitWarnings(BugReporter& BR) {
-    for (std::list<RangedBugReport>::iterator I=Reports.begin(),
-         E=Reports.end(); I!=E; ++I)
-      BR.EmitWarning(*I);
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// Check registration.
-
-void GRSimpleVals::RegisterChecks(GRExprEngine& Eng) {
-  
-  // Path-sensitive checks.
-  Eng.Register(new NullDeref());
-  Eng.Register(new UndefDeref());
-  Eng.Register(new UndefBranch());
-  Eng.Register(new DivZero());
-  Eng.Register(new UndefResult());
-  Eng.Register(new BadCall());
-  Eng.Register(new RetStack());
-  Eng.Register(new BadArg());
-  Eng.Register(new BadMsgExprArg());
-  Eng.Register(new BadReceiver());
-  
-  // Add extra checkers.
-  ASTContext& Ctx = Eng.getContext();
-  ValueStateManager* VMgr = &Eng.getStateManager();
-
-  GRSimpleAPICheck* Check = CreateBasicObjCFoundationChecks(Ctx, VMgr);
-  Eng.AddCheck(Check, Stmt::ObjCMessageExprClass);
-  
-  Check = CreateAuditCFNumberCreate(Ctx, VMgr);
-  Eng.AddCheck(Check, Stmt::CallExprClass);
-  
-  Eng.AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);  
-}
-
 //===----------------------------------------------------------------------===//
 // Transfer Function creation for External clients.
 //===----------------------------------------------------------------------===//
index ac07f8b32416e7146b3015540d0f535fd520e04d..8ad4958345127243dab934985bba3f3c6972be5b 100644 (file)
@@ -35,8 +35,6 @@ public:
   GRSimpleVals() {}
   virtual ~GRSimpleVals() {}
   
-  virtual void RegisterChecks(GRExprEngine& Eng);
-  
   // Casts.
   
   virtual RVal EvalCast(GRExprEngine& Engine, NonLVal V, QualType CastT);