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 "ClangSACheckers.h"
17 #include "clang/StaticAnalyzer/Core/Checker.h"
18 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
22 using namespace clang;
26 class AdjustedReturnValueChecker :
27 public Checker< check::PostStmt<CallExpr> > {
29 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
33 void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
34 CheckerContext &C) const {
36 // Get the result type of the call.
37 QualType expectedResultTy = CE->getType();
39 // Fetch the signature of the called function.
40 ProgramStateRef state = C.getState();
41 const LocationContext *LCtx = C.getLocationContext();
43 SVal V = state->getSVal(CE, LCtx);
48 // Casting to void? Discard the value.
49 if (expectedResultTy->isVoidType()) {
50 C.addTransition(state->BindExpr(CE, LCtx, UnknownVal()));
54 const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion();
58 QualType actualResultTy;
60 if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) {
61 const FunctionDecl *FD = FT->getDecl();
62 actualResultTy = FD->getResultType();
64 else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
65 const BlockTextRegion *BR = BD->getCodeRegion();
66 const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>();
67 const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
68 actualResultTy = FT->getResultType();
72 if (actualResultTy.isNull())
75 // For now, ignore references.
76 if (actualResultTy->getAs<ReferenceType>())
81 if (expectedResultTy != actualResultTy) {
82 // FIXME: Do more checking and actual emit an error. At least performing
83 // the cast avoids some assertion failures elsewhere.
84 SValBuilder &svalBuilder = C.getSValBuilder();
85 V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
86 C.addTransition(state->BindExpr(CE, LCtx, V));
90 void ento::registerAdjustedReturnValueChecker(CheckerManager &mgr) {
91 mgr.registerChecker<AdjustedReturnValueChecker>();