blob: b92f2e70562591e393d263798f4f11227dde4a06 [file] [log] [blame]
Ted Kremenek40c37e12010-02-04 00:47:48 +00001//== AdjustedReturnValueChecker.cpp -----------------------------*- C++ -*--==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
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
12// it is.
13//
14//===----------------------------------------------------------------------===//
15
16#include "GRExprEngineInternalChecks.h"
Ted Kremenek40c37e12010-02-04 00:47:48 +000017#include "clang/Checker/BugReporter/BugReporter.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000018#include "clang/Checker/PathSensitive/GRExprEngine.h"
Ted Kremenek40c37e12010-02-04 00:47:48 +000019#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Ted Kremenek40c37e12010-02-04 00:47:48 +000020
21using namespace clang;
22
23namespace {
24class AdjustedReturnValueChecker :
25 public CheckerVisitor<AdjustedReturnValueChecker> {
26public:
27 AdjustedReturnValueChecker() {}
28
29 void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
30
31 static void *getTag() {
32 static int x = 0; return &x;
33 }
34};
35}
36
37void clang::RegisterAdjustedReturnValueChecker(GRExprEngine &Eng) {
38 Eng.registerCheck(new AdjustedReturnValueChecker());
39}
40
41void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C,
42 const CallExpr *CE) {
43
Ted Kremenek95a01122010-02-04 04:18:55 +000044 // Get the result type of the call.
45 QualType expectedResultTy = CE->getType();
46
Ted Kremenek40c37e12010-02-04 00:47:48 +000047 // Fetch the signature of the called function.
48 const GRState *state = C.getState();
49
Ted Kremenek13976632010-02-08 16:18:51 +000050 SVal V = state->getSVal(CE);
Zhongxing Xu814e6b92010-02-04 04:56:43 +000051
Ted Kremenek40c37e12010-02-04 00:47:48 +000052 if (V.isUnknown())
53 return;
Ted Kremenek95a01122010-02-04 04:18:55 +000054
55 // Casting to void? Discard the value.
56 if (expectedResultTy->isVoidType()) {
57 C.GenerateNode(state->BindExpr(CE, UnknownVal()));
58 return;
59 }
Ted Kremenek40c37e12010-02-04 00:47:48 +000060
Ted Kremenek13976632010-02-08 16:18:51 +000061 const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
Ted Kremenek40c37e12010-02-04 00:47:48 +000062 if (!callee)
63 return;
64
65 QualType actualResultTy;
66
67 if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) {
68 const FunctionDecl *FD = FT->getDecl();
69 actualResultTy = FD->getResultType();
70 }
71 else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
72 const BlockTextRegion *BR = BD->getCodeRegion();
73 const BlockPointerType *BT =
74 BR->getLocationType(C.getASTContext())->getAs<BlockPointerType>();
75 const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
76 actualResultTy = FT->getResultType();
77 }
78
79 // Can this happen?
80 if (actualResultTy.isNull())
81 return;
82
83 // For now, ignore references.
84 if (actualResultTy->getAs<ReferenceType>())
85 return;
86
Ted Kremenek40c37e12010-02-04 00:47:48 +000087
88 // Are they the same?
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 SValuator &SVator = C.getSValuator();
Zhongxing Xu814e6b92010-02-04 04:56:43 +000093 V = SVator.EvalCast(V, expectedResultTy, actualResultTy);
94 C.GenerateNode(state->BindExpr(CE, V));
Ted Kremenek40c37e12010-02-04 00:47:48 +000095 }
96}