1 //== AdjustedReturnValueChecker.cpp -----------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines AdjustedReturnValueChecker, a simple check to see if the
11 // return value of a function call is different than the one the caller thinks
14 //===----------------------------------------------------------------------===//
16 #include "GRExprEngineInternalChecks.h"
17 #include "clang/Checker/BugReporter/BugReporter.h"
18 #include "clang/Checker/PathSensitive/GRExprEngine.h"
19 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
21 using namespace clang
;
24 class AdjustedReturnValueChecker
:
25 public CheckerVisitor
<AdjustedReturnValueChecker
> {
27 AdjustedReturnValueChecker() {}
29 void PostVisitCallExpr(CheckerContext
&C
, const CallExpr
*CE
);
31 static void *getTag() {
32 static int x
= 0; return &x
;
37 void clang::RegisterAdjustedReturnValueChecker(GRExprEngine
&Eng
) {
38 Eng
.registerCheck(new AdjustedReturnValueChecker());
41 void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext
&C
,
44 // Get the result type of the call.
45 QualType expectedResultTy
= CE
->getType();
47 // Fetch the signature of the called function.
48 const GRState
*state
= C
.getState();
50 SVal V
= state
->getSVal(CE
);
55 // Casting to void? Discard the value.
56 if (expectedResultTy
->isVoidType()) {
57 C
.GenerateNode(state
->BindExpr(CE
, UnknownVal()));
61 const MemRegion
*callee
= state
->getSVal(CE
->getCallee()).getAsRegion();
65 QualType actualResultTy
;
67 if (const FunctionTextRegion
*FT
= dyn_cast
<FunctionTextRegion
>(callee
)) {
68 const FunctionDecl
*FD
= FT
->getDecl();
69 actualResultTy
= FD
->getResultType();
71 else if (const BlockDataRegion
*BD
= dyn_cast
<BlockDataRegion
>(callee
)) {
72 const BlockTextRegion
*BR
= BD
->getCodeRegion();
73 const BlockPointerType
*BT
=BR
->getLocationType()->getAs
<BlockPointerType
>();
74 const FunctionType
*FT
= BT
->getPointeeType()->getAs
<FunctionType
>();
75 actualResultTy
= FT
->getResultType();
79 if (actualResultTy
.isNull())
82 // For now, ignore references.
83 if (actualResultTy
->getAs
<ReferenceType
>())
88 if (expectedResultTy
!= actualResultTy
) {
89 // FIXME: Do more checking and actual emit an error. At least performing
90 // the cast avoids some assertion failures elsewhere.
91 SValBuilder
&svalBuilder
= C
.getSValBuilder();
92 V
= svalBuilder
.EvalCast(V
, expectedResultTy
, actualResultTy
);
93 C
.GenerateNode(state
->BindExpr(CE
, V
));