don't use #pragma mark, it isn't portable.
[clang.git] / lib / StaticAnalyzer / EntoSA / Checkers / AdjustedReturnValueChecker.cpp
blob46e2de5c26d92a3ec05a19060fbdc57858180a46
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 "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;
22 using namespace ento;
24 namespace {
25 class AdjustedReturnValueChecker :
26 public CheckerVisitor<AdjustedReturnValueChecker> {
27 public:
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,
43 const CallExpr *CE) {
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);
53 if (V.isUnknown())
54 return;
56 // Casting to void? Discard the value.
57 if (expectedResultTy->isVoidType()) {
58 C.generateNode(state->BindExpr(CE, UnknownVal()));
59 return;
62 const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
63 if (!callee)
64 return;
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();
79 // Can this happen?
80 if (actualResultTy.isNull())
81 return;
83 // For now, ignore references.
84 if (actualResultTy->getAs<ReferenceType>())
85 return;
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 SValBuilder &svalBuilder = C.getSValBuilder();
93 V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
94 C.generateNode(state->BindExpr(CE, V));