Rename 'SValuator' to 'SValBuilder'. The new name
[clang.git] / lib / Checker / AdjustedReturnValueChecker.cpp
blob5f564014131bb66254f02f72d3fc0ad79ca3a7b5
1 //== 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.
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;
23 namespace {
24 class AdjustedReturnValueChecker :
25 public CheckerVisitor<AdjustedReturnValueChecker> {
26 public:
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,
42 const CallExpr *CE) {
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);
52 if (V.isUnknown())
53 return;
55 // Casting to void? Discard the value.
56 if (expectedResultTy->isVoidType()) {
57 C.GenerateNode(state->BindExpr(CE, UnknownVal()));
58 return;
61 const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
62 if (!callee)
63 return;
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();
78 // Can this happen?
79 if (actualResultTy.isNull())
80 return;
82 // For now, ignore references.
83 if (actualResultTy->getAs<ReferenceType>())
84 return;
87 // Are they the same?
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));