sammccall created this revision.

In VirtualCallChecker, handle indirect calls.

getDirectCallee() can be nullptr, and dyn_cast(nullptr) is UB


https://reviews.llvm.org/D29303

Files:
  lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp

Index: lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -1,3 +1,4 @@
+#include <iostream>
 //=======- VirtualCallChecker.cpp --------------------------------*- C++ -*-==//
 //
 //                     The LLVM Compiler Infrastructure
@@ -44,7 +45,7 @@
   /// may result in unexpected behavior).
   bool ReportPureOnly = false;
 
-  typedef const CallExpr * WorkListUnit;
+  typedef const CallExpr *WorkListUnit;
   typedef SmallVector<WorkListUnit, 20> DFSWorkList;
 
   /// A vector representing the worklist which has a chain of CallExprs.
@@ -54,12 +55,13 @@
   // body has not been visited yet.
   // PostVisited : A CallExpr to this FunctionDecl is in the worklist, and the
   // body has been visited.
-  enum Kind { NotVisited,
-              PreVisited,  /**< A CallExpr to this FunctionDecl is in the
-                                worklist, but the body has not yet been
-                                visited. */
-              PostVisited  /**< A CallExpr to this FunctionDecl is in the
-                                worklist, and the body has been visited. */
+  enum Kind {
+    NotVisited,
+    PreVisited, /**< A CallExpr to this FunctionDecl is in the
+                     worklist, but the body has not yet been
+                     visited. */
+    PostVisited /**< A CallExpr to this FunctionDecl is in the
+                     worklist, and the body has been visited. */
   };
 
   /// A DenseMap that records visited states of FunctionDecls.
@@ -135,7 +137,6 @@
   void VisitChildren(Stmt *S);
 
   void ReportVirtualCall(const CallExpr *CE, bool isPure);
-
 };
 } // end anonymous namespace
 
@@ -179,7 +180,8 @@
   }
 
   // Get the callee.
-  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CE->getDirectCallee());
+  const CXXMethodDecl *MD =
+      dyn_cast_or_null<CXXMethodDecl>(CE->getDirectCallee());
   if (MD && MD->isVirtual() && !callIsNonVirtual && !MD->hasAttr<FinalAttr>() &&
       !MD->getParent()->hasAttr<FinalAttr>())
     ReportVirtualCall(CE, MD->isPure());
@@ -208,8 +210,9 @@
       os << " <-- " << *visitingCallExpr->getDirectCallee();
     // Names of FunctionDecls in worklist with state PostVisited.
     for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(),
-         E = WList.begin(); I != E; --I) {
-      const FunctionDecl *FD = (*(I-1))->getDirectCallee();
+                                                     E = WList.begin();
+         I != E; --I) {
+      const FunctionDecl *FD = (*(I - 1))->getDirectCallee();
       assert(FD);
       if (VisitedFunctions[FD] == PostVisited)
         os << " <-- " << *FD;
@@ -219,7 +222,7 @@
   }
 
   PathDiagnosticLocation CELoc =
-    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
+      PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
   SourceRange R = CE->getCallee()->getSourceRange();
 
   os << "Call to ";
@@ -249,12 +252,12 @@
 //===----------------------------------------------------------------------===//
 
 namespace {
-class VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl> > {
+class VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl>> {
 public:
   DefaultBool isInterprocedural;
   DefaultBool isPureOnly;
 
-  void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager& mgr,
+  void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager &mgr,
                     BugReporter &BR) const {
     AnalysisDeclContext *ADC = mgr.getAnalysisDeclContext(RD);
 
@@ -281,11 +284,9 @@
 
 void ento::registerVirtualCallChecker(CheckerManager &mgr) {
   VirtualCallChecker *checker = mgr.registerChecker<VirtualCallChecker>();
-  checker->isInterprocedural =
-      mgr.getAnalyzerOptions().getBooleanOption("Interprocedural", false,
-                                                checker);
+  checker->isInterprocedural = mgr.getAnalyzerOptions().getBooleanOption(
+      "Interprocedural", false, checker);
 
   checker->isPureOnly =
-      mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false,
-                                                checker);
+      mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false, checker);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to