[cfe-commits] r95268 - in /cfe/trunk: lib/Checker/AdjustedReturnValueChecker.cpp lib/Checker/CMakeLists.txt lib/Checker/GRExprEngine.cpp lib/Checker/GRExprEngineInternalChecks.h test/Analysis/misc-ps.m

Ted Kremenek kremenek at apple.com
Wed Feb 3 16:47:49 PST 2010


Author: kremenek
Date: Wed Feb  3 18:47:48 2010
New Revision: 95268

URL: http://llvm.org/viewvc/llvm-project?rev=95268&view=rev
Log:
static analyzer: handle casts of a function to a function pointer with
a different return type.  While we don't emit any errors (yet), at
least we avoid cases where we might crash because of an assertion
failure later on (when the return type differs from what is expected).

Added:
    cfe/trunk/lib/Checker/AdjustedReturnValueChecker.cpp
Modified:
    cfe/trunk/lib/Checker/CMakeLists.txt
    cfe/trunk/lib/Checker/GRExprEngine.cpp
    cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h
    cfe/trunk/test/Analysis/misc-ps.m

Added: cfe/trunk/lib/Checker/AdjustedReturnValueChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/AdjustedReturnValueChecker.cpp?rev=95268&view=auto

==============================================================================
--- cfe/trunk/lib/Checker/AdjustedReturnValueChecker.cpp (added)
+++ cfe/trunk/lib/Checker/AdjustedReturnValueChecker.cpp Wed Feb  3 18:47:48 2010
@@ -0,0 +1,90 @@
+//== AdjustedReturnValueChecker.cpp -----------------------------*- 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 AdjustedReturnValueChecker, a simple check to see if the
+// return value of a function call is different than the one the caller thinks
+// it is.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Checker/PathSensitive/GRExprEngine.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+
+namespace {
+class AdjustedReturnValueChecker : 
+    public CheckerVisitor<AdjustedReturnValueChecker> {      
+public:
+  AdjustedReturnValueChecker() {}
+
+  void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+      
+  static void *getTag() {
+    static int x = 0; return &x;
+  }      
+};
+}
+
+void clang::RegisterAdjustedReturnValueChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new AdjustedReturnValueChecker());
+}
+
+void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C,
+                                                   const CallExpr *CE) {
+  
+  // Fetch the signature of the called function.
+  const GRState *state = C.getState();
+
+  SVal V = state->getSVal(CE);
+  if (V.isUnknown())
+    return;
+
+  const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
+  if (!callee)
+    return;
+
+  QualType actualResultTy;
+  
+  if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) {
+    const FunctionDecl *FD = FT->getDecl();
+    actualResultTy = FD->getResultType();
+  }
+  else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
+    const BlockTextRegion *BR = BD->getCodeRegion();
+    const BlockPointerType *BT =
+      BR->getLocationType(C.getASTContext())->getAs<BlockPointerType>();
+    const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
+    actualResultTy = FT->getResultType();
+  }
+
+  // Can this happen?
+  if (actualResultTy.isNull())
+    return;
+
+  // For now, ignore references.
+  if (actualResultTy->getAs<ReferenceType>())
+    return;
+  
+  // Get the result type of the call.
+  QualType expectedResultTy = CE->getType();
+
+  // Are they the same?
+  if (expectedResultTy != actualResultTy) {
+    // FIXME: Do more checking and actual emit an error. At least performing
+    // the cast avoids some assertion failures elsewhere.
+    SValuator &SVator = C.getSValuator();
+    const SValuator::CastResult &R = SVator.EvalCast(V, state, expectedResultTy, actualResultTy);
+    C.GenerateNode(R.getState()->BindExpr(CE, R.getSVal()));
+  }
+}

Modified: cfe/trunk/lib/Checker/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/CMakeLists.txt?rev=95268&r1=95267&r2=95268&view=diff

==============================================================================
--- cfe/trunk/lib/Checker/CMakeLists.txt (original)
+++ cfe/trunk/lib/Checker/CMakeLists.txt Wed Feb  3 18:47:48 2010
@@ -1,6 +1,7 @@
 set(LLVM_NO_RTTI 1)
 
 add_clang_library(clangChecker
+  AdjustedReturnValueChecker.cpp
   ArrayBoundChecker.cpp
   AttrNonNullChecker.cpp
   BasicConstraintManager.cpp
@@ -26,8 +27,8 @@
   DivZeroChecker.cpp
   Environment.cpp
   ExplodedGraph.cpp
-  FlatStore.cpp
   FixedAddressChecker.cpp
+  FlatStore.cpp
   GRBlockCounter.cpp
   GRCoreEngine.cpp
   GRExprEngine.cpp

Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=95268&r1=95267&r2=95268&view=diff

==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Wed Feb  3 18:47:48 2010
@@ -301,6 +301,7 @@
   // their associated BugType will get registered with the BugReporter
   // automatically.  Note that the check itself is owned by the GRExprEngine
   // object.  
+  RegisterAdjustedReturnValueChecker(Eng);
   RegisterAttrNonNullChecker(Eng);
   RegisterCallAndMessageChecker(Eng);
   RegisterDereferenceChecker(Eng);

Modified: cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h?rev=95268&r1=95267&r2=95268&view=diff

==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Checker/GRExprEngineInternalChecks.h Wed Feb  3 18:47:48 2010
@@ -19,6 +19,7 @@
 
 class GRExprEngine;
 
+void RegisterAdjustedReturnValueChecker(GRExprEngine &Eng);
 void RegisterAttrNonNullChecker(GRExprEngine &Eng);
 void RegisterDereferenceChecker(GRExprEngine &Eng);
 void RegisterDivZeroChecker(GRExprEngine &Eng);

Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=95268&r1=95267&r2=95268&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Wed Feb  3 18:47:48 2010
@@ -879,3 +879,17 @@
   **x = 1; // no-warning
 }
 
+//===----------------------------------------------------------------------===//
+// Handle casts of a function to a function pointer with a different return
+// value.  We don't yet emit an error for such cases, but we now we at least
+// don't crash when the return value gets interpreted in a way that
+// violates our invariants.
+//===----------------------------------------------------------------------===//
+
+void *foo_rev95267();
+int bar_rev95267() {
+  char (*Callback_rev95267)(void) = (char (*)(void)) foo_rev95267;
+  if ((*Callback_rev95267)() == (char) 0)
+    return 1;
+  return 0;
+}





More information about the cfe-commits mailing list