summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-09-01 17:39:00 +0000
committerJordan Rose <jordan_rose@apple.com>2012-09-01 17:39:00 +0000
commit2da564380a0efe084ede1e5ed7d22348c79aeb0e (patch)
tree1a9640df96768bf4b518dc86f9900e2ce10db2c9 /clang/lib/StaticAnalyzer
parent2117ac40c9dd5854f4653244fdcff8f8454e3f34 (diff)
downloadbcm5719-llvm-2da564380a0efe084ede1e5ed7d22348c79aeb0e.tar.gz
bcm5719-llvm-2da564380a0efe084ede1e5ed7d22348c79aeb0e.zip
[analyzer] Always derive a CallEvent's return type from its origin expr.
Previously, we preferred to get a result type by looking at the callee's declared result type. This allowed us to handlereferences, which are represented in the AST as lvalues of their pointee type. (That is, a call to a function returning 'int &' has type 'int' and value kind 'lvalue'.) However, this results in us preferring the original type of a function over a casted type. This is a problem when a function pointer is casted to another type, because the conjured result value will have the wrong type. AdjustedReturnValueChecker is supposed to handle this, but still doesn't handle the case where there is no "original function" at all, i.e. where the callee is unknown. Now, we instead look at the call expression's value kind (lvalue, xvalue, or prvalue), and adjust the expr's type accordingly. This will have no effect when the function is inlined, and will conjure the value that will actually be used when it is not. This makes AdjustedReturnValueChecker /nearly/ unnecessary; unfortunately, the cases where it would still be useful are where we need to cast the result of an inlined function or a checker-evaluated function, and in these cases we don't know what we're casting /from/ by the time we can do post- call checks. In light of that, remove AdjustedReturnValueChecker, which was already not checking quite a few calls. llvm-svn: 163065
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp92
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt1
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/Checkers.td4
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp47
4 files changed, 19 insertions, 125 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
deleted file mode 100644
index 84ea8c709dd..00000000000
--- a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-//== 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 "ClangSACheckers.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-
-using namespace clang;
-using namespace ento;
-
-namespace {
-class AdjustedReturnValueChecker :
- public Checker< check::PostStmt<CallExpr> > {
-public:
- void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
-};
-}
-
-void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
- CheckerContext &C) const {
-
- // Get the result type of the call.
- QualType expectedResultTy = CE->getType();
-
- // Fetch the signature of the called function.
- ProgramStateRef state = C.getState();
- const LocationContext *LCtx = C.getLocationContext();
-
- SVal V = state->getSVal(CE, LCtx);
-
- if (V.isUnknown())
- return;
-
- // Casting to void? Discard the value.
- if (expectedResultTy->isVoidType()) {
- C.addTransition(state->BindExpr(CE, LCtx, UnknownVal()));
- return;
- }
-
- const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).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()->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;
-
-
- // 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.
- SValBuilder &svalBuilder = C.getSValBuilder();
- V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
- C.addTransition(state->BindExpr(CE, LCtx, V));
- }
-}
-
-void ento::registerAdjustedReturnValueChecker(CheckerManager &mgr) {
- mgr.registerChecker<AdjustedReturnValueChecker>();
-}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 7fe51d3a4ce..ba39ccc4560 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -4,7 +4,6 @@ clang_tablegen(Checkers.inc -gen-clang-sa-checkers
TARGET ClangSACheckers)
add_clang_library(clangStaticAnalyzerCheckers
- AdjustedReturnValueChecker.cpp
AnalyzerStatsChecker.cpp
ArrayBoundChecker.cpp
ArrayBoundCheckerV2.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/clang/lib/StaticAnalyzer/Checkers/Checkers.td
index 7949637ec61..92b5a16d702 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -60,10 +60,6 @@ def CallAndMessageChecker : Checker<"CallAndMessage">,
HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)">,
DescFile<"CallAndMessageChecker.cpp">;
-def AdjustedReturnValueChecker : Checker<"AdjustedReturnValue">,
- HelpText<"Check to see if the return value of a function call is different than the caller expects (e.g., from calls through function pointers)">,
- DescFile<"AdjustedReturnValueChecker.cpp">;
-
def AttrNonNullChecker : Checker<"AttributeNonNull">,
HelpText<"Check for null pointers passed as arguments to a function whose arguments are marked with the 'nonnull' attribute">,
DescFile<"AttrNonNullChecker.cpp">;
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 32a66c3b270..aed0f55982a 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -23,10 +23,26 @@ using namespace clang;
using namespace ento;
QualType CallEvent::getResultType() const {
- QualType ResultTy = getDeclaredResultType();
+ const Expr *E = getOriginExpr();
+ assert(E && "Calls without origin expressions do not have results");
+ QualType ResultTy = E->getType();
- if (ResultTy.isNull())
- ResultTy = getOriginExpr()->getType();
+ ASTContext &Ctx = getState()->getStateManager().getContext();
+
+ // A function that returns a reference to 'int' will have a result type
+ // of simply 'int'. Check the origin expr's value kind to recover the
+ // proper type.
+ switch (E->getValueKind()) {
+ case VK_LValue:
+ ResultTy = Ctx.getLValueReferenceType(ResultTy);
+ break;
+ case VK_XValue:
+ ResultTy = Ctx.getRValueReferenceType(ResultTy);
+ break;
+ case VK_RValue:
+ // No adjustment is necessary.
+ break;
+ }
return ResultTy;
}
@@ -285,14 +301,6 @@ void AnyFunctionCall::getInitialStackFrameContents(
D->param_begin(), D->param_end());
}
-QualType AnyFunctionCall::getDeclaredResultType() const {
- const FunctionDecl *D = getDecl();
- if (!D)
- return QualType();
-
- return D->getResultType();
-}
-
bool AnyFunctionCall::argumentsMayEscape() const {
if (hasNonZeroCallbackArg())
return true;
@@ -501,15 +509,6 @@ void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
}
-QualType BlockCall::getDeclaredResultType() const {
- const BlockDataRegion *BR = getBlockRegion();
- if (!BR)
- return QualType();
- QualType BlockTy = BR->getCodeRegion()->getLocationType();
- return cast<FunctionType>(BlockTy->getPointeeType())->getResultType();
-}
-
-
SVal CXXConstructorCall::getCXXThisVal() const {
if (Data)
return loc::MemRegionVal(static_cast<const MemRegion *>(Data));
@@ -566,14 +565,6 @@ ObjCMethodCall::getExtraInvalidatedRegions(RegionList &Regions) const {
Regions.push_back(R);
}
-QualType ObjCMethodCall::getDeclaredResultType() const {
- const ObjCMethodDecl *D = getDecl();
- if (!D)
- return QualType();
-
- return D->getResultType();
-}
-
SVal ObjCMethodCall::getSelfSVal() const {
const LocationContext *LCtx = getLocationContext();
const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
OpenPOWER on IntegriCloud