xazax.hun updated this revision to Diff 44322.
xazax.hun marked 4 inline comments as done.
xazax.hun added a comment.

- Removed support for matching ObjC messages. It might be added in a later.
- Addressed review comments.


http://reviews.llvm.org/D15921

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
  lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
  lib/StaticAnalyzer/Core/CheckerContext.cpp

Index: lib/StaticAnalyzer/Core/CheckerContext.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Lex/Lexer.h"
 
@@ -35,6 +36,16 @@
   return funI->getName();
 }
 
+bool CheckerContext::isCalled(const CallEvent &Call,
+                              const CallDescription &CD) {
+  assert(Call.getKind() != CE_ObjCMessage && "Obj-C methods are not supported");
+  if (!CD.II)
+    CD.II = &getASTContext().Idents.get(CD.FuncName);
+  if (Call.getCalleeIdentifier() != CD.II)
+    return false;
+  return (CD.RequiredArgs == CallDescription::NoArgRequirement ||
+          CD.RequiredArgs == Call.getNumArgs());
+}
 
 bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
                                         StringRef Name) {
Index: lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -51,14 +51,11 @@
                                            check::PreCall,
                                            check::DeadSymbols,
                                            check::PointerEscape> {
-
-  mutable IdentifierInfo *IIfopen, *IIfclose;
+  CallDescription OpenFn, CloseFn;
 
   std::unique_ptr<BugType> DoubleCloseBugType;
   std::unique_ptr<BugType> LeakBugType;
 
-  void initIdentifierInfo(ASTContext &Ctx) const;
-
   void reportDoubleClose(SymbolRef FileDescSym,
                          const CallEvent &Call,
                          CheckerContext &C) const;
@@ -106,7 +103,7 @@
 } // end anonymous namespace
 
 SimpleStreamChecker::SimpleStreamChecker()
-    : IIfopen(nullptr), IIfclose(nullptr) {
+    : OpenFn("fopen"), CloseFn("fclose", 1) {
   // Initialize the bug types.
   DoubleCloseBugType.reset(
       new BugType(this, "Double fclose", "Unix Stream API Error"));
@@ -119,12 +116,10 @@
 
 void SimpleStreamChecker::checkPostCall(const CallEvent &Call,
                                         CheckerContext &C) const {
-  initIdentifierInfo(C.getASTContext());
-
   if (!Call.isGlobalCFunction())
     return;
 
-  if (Call.getCalleeIdentifier() != IIfopen)
+  if (!C.isCalled(Call, OpenFn))
     return;
 
   // Get the symbolic value corresponding to the file handle.
@@ -140,15 +135,10 @@
 
 void SimpleStreamChecker::checkPreCall(const CallEvent &Call,
                                        CheckerContext &C) const {
-  initIdentifierInfo(C.getASTContext());
-
   if (!Call.isGlobalCFunction())
     return;
 
-  if (Call.getCalleeIdentifier() != IIfclose)
-    return;
-
-  if (Call.getNumArgs() != 1)
+  if (!C.isCalled(Call, CloseFn))
     return;
 
   // Get the symbolic value corresponding to the file handle.
@@ -275,13 +265,6 @@
   return State;
 }
 
-void SimpleStreamChecker::initIdentifierInfo(ASTContext &Ctx) const {
-  if (IIfopen)
-    return;
-  IIfopen = &Ctx.Idents.get("fopen");
-  IIfclose = &Ctx.Idents.get("fclose");
-}
-
 void ento::registerSimpleStreamChecker(CheckerManager &mgr) {
   mgr.registerChecker<SimpleStreamChecker>();
 }
Index: include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -66,6 +66,28 @@
   #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
 
+/// This class represents a description of a function call using the number of
+/// arguments and the name of the function. It can also represent descriptions
+/// of Obj-C message expressions.
+class CallDescription {
+  friend class CheckerContext;
+  mutable IdentifierInfo *II;
+  StringRef FuncName;
+  unsigned RequiredArgs;
+
+public:
+  const static unsigned NoArgRequirement = ~0;
+  /// \brief Constructs a CallDescription object.
+  ///
+  /// @param FuncName The name of the function or the selector that will be
+  /// matched.
+  ///
+  /// @param RequiredArgs The number of arguments that is expected to match a
+  /// call. Omit this parameter to match every occurance of call with a given
+  /// name regardless the number of arguments.
+  CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement)
+      : FuncName(FuncName), RequiredArgs(RequiredArgs) {}
+};
 
 class CheckerContext {
   ExprEngine &Eng;
@@ -284,6 +306,13 @@
     return getCalleeName(FunDecl);
   }
 
+  /// \brief Returns true if the CallEvent is a call to a function that matches
+  /// the CallDescription.
+  ///
+  /// Note that this overload is not intended to be used to match Obj-C method
+  /// calls. Use the corresponding overload for that case.
+  bool isCalled(const CallEvent &Call, const CallDescription &CD);
+
   /// \brief Returns true if the callee is an externally-visible function in the
   /// top-level namespace, such as \c malloc.
   ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to