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 "ExprEngineInternalChecks.h"
17 #include "clang/StaticAnalyzer/BugReporter/BugReporter.h"
18 #include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"
19 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
21 using namespace clang
;
25 class AdjustedReturnValueChecker
:
26 public CheckerVisitor
<AdjustedReturnValueChecker
> {
28 AdjustedReturnValueChecker() {}
30 void PostVisitCallExpr(CheckerContext
&C
, const CallExpr
*CE
);
32 static void *getTag() {
33 static int x
= 0; return &x
;
38 void ento::RegisterAdjustedReturnValueChecker(ExprEngine
&Eng
) {
39 Eng
.registerCheck(new AdjustedReturnValueChecker());
42 void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext
&C
,
45 // Get the result type of the call.
46 QualType expectedResultTy
= CE
->getType();
48 // Fetch the signature of the called function.
49 const GRState
*state
= C
.getState();
51 SVal V
= state
->getSVal(CE
);
56 // Casting to void? Discard the value.
57 if (expectedResultTy
->isVoidType()) {
58 C
.generateNode(state
->BindExpr(CE
, UnknownVal()));
62 const MemRegion
*callee
= state
->getSVal(CE
->getCallee()).getAsRegion();
66 QualType actualResultTy
;
68 if (const FunctionTextRegion
*FT
= dyn_cast
<FunctionTextRegion
>(callee
)) {
69 const FunctionDecl
*FD
= FT
->getDecl();
70 actualResultTy
= FD
->getResultType();
72 else if (const BlockDataRegion
*BD
= dyn_cast
<BlockDataRegion
>(callee
)) {
73 const BlockTextRegion
*BR
= BD
->getCodeRegion();
74 const BlockPointerType
*BT
=BR
->getLocationType()->getAs
<BlockPointerType
>();
75 const FunctionType
*FT
= BT
->getPointeeType()->getAs
<FunctionType
>();
76 actualResultTy
= FT
->getResultType();
80 if (actualResultTy
.isNull())
83 // For now, ignore references.
84 if (actualResultTy
->getAs
<ReferenceType
>())
89 if (expectedResultTy
!= actualResultTy
) {
90 // FIXME: Do more checking and actual emit an error. At least performing
91 // the cast avoids some assertion failures elsewhere.
92 SValBuilder
&svalBuilder
= C
.getSValBuilder();
93 V
= svalBuilder
.evalCast(V
, expectedResultTy
, actualResultTy
);
94 C
.generateNode(state
->BindExpr(CE
, V
));