void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C, const CallExpr *CE) { // Get the result type of the call. QualType expectedResultTy = CE->getType(); // Fetch the signature of the called function. const GRState *state = C.getState(); SVal V = state->getSVal(CE); if (V.isUnknown()) return; // Casting to void? Discard the value. if (expectedResultTy->isVoidType()) { C.GenerateNode(state->BindExpr(CE, UnknownVal())); return; } const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion(); if (!callee) return; QualType actualResultTy; if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) { const FunctionDecl *FD = FT->getDecl(); actualResultTy = FD->getResultType(); } else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) { const BlockTextRegion *BR = BD->getCodeRegion(); const BlockPointerType *BT = BR->getLocationType(C.getASTContext())->getAs<BlockPointerType>(); const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>(); actualResultTy = FT->getResultType(); } // Can this happen? if (actualResultTy.isNull()) return; // For now, ignore references. if (actualResultTy->getAs<ReferenceType>()) return; // Are they the same? if (expectedResultTy != actualResultTy) { // FIXME: Do more checking and actual emit an error. At least performing // the cast avoids some assertion failures elsewhere. SValuator &SVator = C.getSValuator(); V = SVator.EvalCast(V, expectedResultTy, actualResultTy); C.GenerateNode(state->BindExpr(CE, V)); } }