]> granicus.if.org Git - clang/commitdiff
Hooked up GRSimpleAPICheck and the simple Objective-C Foundation checks to use
authorTed Kremenek <kremenek@apple.com>
Thu, 3 Apr 2008 17:57:38 +0000 (17:57 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 3 Apr 2008 17:57:38 +0000 (17:57 +0000)
the new BugReporter interface.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49180 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/BugReporter.h
include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
lib/Analysis/BasicObjCFoundationChecks.cpp
lib/Analysis/BugReporter.cpp
lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRSimpleVals.h

index 86bd43a6e15d8af0d4946f9ace8ff358a45dcbd7..a5af327195144d33fddab708ed6e6a76179ed746 100644 (file)
@@ -41,6 +41,9 @@ public:
   
   virtual PathDiagnosticPiece* getEndPath(ASTContext& Ctx,
                                           ExplodedNode<ValueState> *N) const;
+  
+  virtual void getRanges(const SourceRange*& beg,
+                         const SourceRange*& end) const;
 };
   
 class BugReporter {
index 16db80229049fd5d26f02fe296c44c6e02f564a8..16b23c558cc4a7776ca659f2d5b3f6b17810db1c 100644 (file)
@@ -22,12 +22,20 @@ namespace clang {
   
 class ValueState;
 class Diagnostic;
+class BugReporter;
+class ASTContext;
+class GRExprEngine;
+class PathDiagnosticClient;
+template <typename T> class ExplodedGraph;
+  
   
 class GRSimpleAPICheck : public GRAuditor<ValueState> {
 public:
   GRSimpleAPICheck() {}
   virtual ~GRSimpleAPICheck() {}
-  virtual void ReportResults(Diagnostic& D) {}
+  virtual void ReportResults(Diagnostic& Diag, PathDiagnosticClient* PD,
+                             ASTContext& Ctx, BugReporter& BR,
+                             ExplodedGraph<GRExprEngine>& G) = 0;
 };
 
 } // end namespace clang
index 82cabaf7a3fd4587a98182eae80c6f5e47497620..9169492f6d91b7502c8a9c34e43bfc98fab82dc4 100644 (file)
 #include "BasicObjCFoundationChecks.h"
 
 #include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
 #include "clang/Analysis/PathSensitive/ValueState.h"
-#include "clang/Analysis/PathSensitive/AnnotatedPath.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ASTContext.h"
 #include <sstream>
 
 using namespace clang;
+
+static ObjCInterfaceType* GetReceiverType(ObjCMessageExpr* ME) {
+  Expr* Receiver = ME->getReceiver();
+  
+  if (!Receiver)
+    return NULL;
+  
+  assert (Receiver->getType()->isPointerType());
+  
+  const PointerType* T = Receiver->getType()->getAsPointerType();
   
+  return dyn_cast<ObjCInterfaceType>(T->getPointeeType().getTypePtr());
+}
+
+static const char* GetReceiverNameType(ObjCMessageExpr* ME) {
+  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
+  return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName()
+                      : NULL;
+}
+
 namespace {
   
+class VISIBILITY_HIDDEN NilArg : public BugDescription {
+  std::string Msg;
+  const char* s;
+  SourceRange R;
+public:
+  NilArg(ObjCMessageExpr* ME, unsigned Arg);
+  virtual ~NilArg() {}
+  
+  virtual const char* getName() const {
+    return "nil argument";
+  }
+  
+  virtual const char* getDescription() const {
+    return s;
+  }
+  
+  virtual void getRanges(const SourceRange*& beg,
+                         const SourceRange*& end) const {
+    beg = &R;
+    end = beg+1;
+  }
+    
+};
+  
+NilArg::NilArg(ObjCMessageExpr* ME, unsigned Arg) : s(NULL) {
+  
+  Expr* E = ME->getArg(Arg);
+  R = E->getSourceRange();
+  
+  std::ostringstream os;
+  
+  os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
+     << ME->getSelector().getName() << "' cannot be nil.";
+  
+  Msg = os.str();
+  s = Msg.c_str();
+}
+  
+  
 class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
 
   ASTContext &Ctx;
   ValueStateManager* VMgr;
   
-  typedef std::list<AnnotatedPath<ValueState> > ErrorsTy;
+  typedef std::vector<std::pair<NodeTy*,BugDescription*> > ErrorsTy;
   ErrorsTy Errors;
       
   RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); }
@@ -53,12 +112,26 @@ public:
   BasicObjCFoundationChecks(ASTContext& ctx, ValueStateManager* vmgr) 
     : Ctx(ctx), VMgr(vmgr) {}
       
-  virtual ~BasicObjCFoundationChecks() {}
+  virtual ~BasicObjCFoundationChecks() {
+    for (ErrorsTy::iterator I = Errors.begin(), E = Errors.end(); I!=E; ++I)
+      delete I->second;    
+  }
   
   virtual bool Audit(ExplodedNode<ValueState>* N);
   
-  virtual void ReportResults(Diagnostic& D);
-
+  virtual void ReportResults(Diagnostic& Diag, PathDiagnosticClient* PD,
+                             ASTContext& Ctx, BugReporter& BR,
+                             ExplodedGraph<GRExprEngine>& G);
+  
+private:
+  
+  void AddError(NodeTy* N, BugDescription* D) {
+    Errors.push_back(std::make_pair(N, D));
+  }
+  
+  void WarnNilArg(NodeTy* N, ObjCMessageExpr* ME, unsigned Arg) {
+    AddError(N, new NilArg(ME, Arg));
+  }
 };
   
 } // end anonymous namespace
@@ -71,24 +144,7 @@ clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx,
   return new BasicObjCFoundationChecks(Ctx, VMgr);  
 }
 
-static ObjCInterfaceType* GetReceiverType(ObjCMessageExpr* ME) {
-  Expr* Receiver = ME->getReceiver();
-  
-  if (!Receiver)
-    return NULL;
-  
-  assert (Receiver->getType()->isPointerType());
-  
-  const PointerType* T = Receiver->getType()->getAsPointerType();
-  
-  return dyn_cast<ObjCInterfaceType>(T->getPointeeType().getTypePtr());
-}
 
-static const char* GetReceiverNameType(ObjCMessageExpr* ME) {
-  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
-  return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName()
-                      : NULL;
-}
 
 bool BasicObjCFoundationChecks::Audit(ExplodedNode<ValueState>* N) {
   
@@ -127,43 +183,13 @@ static inline bool isNil(RVal X) {
 //===----------------------------------------------------------------------===//
 
 
-void BasicObjCFoundationChecks::Warn(NodeTy* N, Expr* E, const std::string& s) {  
-  Errors.push_back(AnnotatedPath<ValueState>());
-  Errors.back().push_back(N, s, E);
-}
-
-void BasicObjCFoundationChecks::ReportResults(Diagnostic& D) {
-  
-  // FIXME: Expand errors into paths.  For now, just issue warnings.
-  
-  for (ErrorsTy::iterator I=Errors.begin(), E=Errors.end(); I!=E; ++I) {
-      
-    AnnotatedNode<ValueState>& AN = I->back();
-    
-    unsigned diag = D.getCustomDiagID(Diagnostic::Warning,
-                                      AN.getString().c_str());
-    
-    Stmt* S = cast<PostStmt>(AN.getNode()->getLocation()).getStmt();
-    FullSourceLoc L(S->getLocStart(), Ctx.getSourceManager());
-    
-    SourceRange R = AN.getExpr()->getSourceRange();
+void BasicObjCFoundationChecks::ReportResults(Diagnostic& Diag,
+                                              PathDiagnosticClient* PD,
+                                              ASTContext& Ctx, BugReporter& BR,
+                                              ExplodedGraph<GRExprEngine>& G) {
     
-    D.Report(L, diag, &AN.getString(), 1, &R, 1);
-  }
-}
-
-void BasicObjCFoundationChecks::WarnNilArg(NodeTy* N, Expr* E) {
-
-  ObjCMessageExpr* ME =
-    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());    
-  
-  std::ostringstream os;
-  
-  os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
-    << ME->getSelector().getName()
-    << "' cannot be nil.";
-  
-  Warn(N, E, os.str());
+  for (ErrorsTy::iterator I=Errors.begin(), E=Errors.end(); I!=E; ++I)
+    BR.EmitPathWarning(Diag, PD, Ctx, *I->second, G, I->first);
 }
 
 bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
@@ -173,7 +199,7 @@ bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
   Expr * E = ME->getArg(Arg);
   
   if (isNil(GetRVal(N->getState(), E))) {
-    WarnNilArg(N, E);
+    WarnNilArg(N, ME, Arg);
     return true;
   }
   
index c5a59e20d8747f6b574e12b5e69348785ccb4b43..9954298165a6b7df4e7692cebb2637388c6f8b37 100644 (file)
@@ -43,8 +43,7 @@ static inline Stmt* GetStmt(const ProgramPoint& P) {
 
 
 PathDiagnosticPiece*
-BugDescription::getEndPath(ASTContext& Ctx,
-                           ExplodedNode<ValueState> *N) const {
+BugDescription::getEndPath(ASTContext& Ctx, ExplodedNode<ValueState> *N) const {
   
   Stmt* S = GetStmt(N->getLocation());
   
@@ -60,6 +59,12 @@ BugDescription::getEndPath(ASTContext& Ctx,
   return P;
 }
 
+void BugDescription::getRanges(const SourceRange*& beg,
+                               const SourceRange*& end) const {
+  beg = NULL;
+  end = NULL;
+}
+
 void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
                                          const BugDescription& B,
                                          ExplodedGraph<GRExprEngine>& G,
@@ -266,7 +271,7 @@ void BugReporter::EmitWarning(Diagnostic& Diag, ASTContext& Ctx,
     return;
   
   std::ostringstream os;
-  os << "[CHECKER] " << B.getName();
+  os << "[CHECKER] " << B.getDescription();
   
   unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning,
                                             os.str().c_str());
index 36ffe33c6f007c51a2d9a38ffc43d5ceeb2a7baf..208e7cb7ae1ffdf3c02803fd1871a94ee55f51b4 100644 (file)
@@ -164,8 +164,8 @@ static void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD,
 namespace clang {
   
 unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
-                                Diagnostic& Diag, PathDiagnosticClient* PD,
-                                bool Visualize, bool TrimGraph) {
+                         Diagnostic& Diag, PathDiagnosticClient* PD,
+                         bool Visualize, bool TrimGraph) {
   
   GRCoreEngine<GRExprEngine> Eng(cfg, CD, Ctx);
   GRExprEngine* CS = &Eng.getCheckerState();
@@ -217,7 +217,8 @@ unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
   EmitWarning(Diag, PD, Ctx, BR, RetStack(), G,
               CS->ret_stackaddr_begin(), CS->ret_stackaddr_end());
 
-  FoundationCheck.get()->ReportResults(Diag);
+  
+  FoundationCheck.get()->ReportResults(Diag, PD, Ctx, BR, G);
 #ifndef NDEBUG
   if (Visualize) CS->ViewGraph(TrimGraph);
 #endif
index 2b3d0fd00a27285e59ecd0245781e6461f86f6eb..74f7fd81ea760fc3844024eb9c701b4a049ad199 100644 (file)
@@ -21,6 +21,9 @@
 
 namespace clang {
   
+class PathDiagnostic;
+class ASTContext;
+  
 class GRSimpleVals : public GRTransferFuncs {
 public:
   GRSimpleVals() {}
@@ -58,6 +61,9 @@ public:
                         CallExpr* CE, LVal L,
                         ExplodedNode<ValueState>* Pred);
   
+  static void GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
+                                     ExplodedNode<ValueState>* N);
+  
 protected:
   
   // Equality operators for LVals.