BuiltinFunctionChecker.cpp revision 103487088211c13ff3ae66f265130c56fb6be025
1//=== BuiltinFunctionChecker.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 checker evaluates clang builtin functions. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ClangSACheckers.h" 15#include "clang/StaticAnalyzer/Core/CheckerV2.h" 16#include "clang/StaticAnalyzer/Core/CheckerManager.h" 17#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 18#include "clang/Basic/Builtins.h" 19 20using namespace clang; 21using namespace ento; 22 23namespace { 24 25class BuiltinFunctionChecker : public CheckerV2<eval::Call> { 26public: 27 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 28}; 29 30} 31 32bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, 33 CheckerContext &C) const{ 34 const GRState *state = C.getState(); 35 const Expr *Callee = CE->getCallee(); 36 SVal L = state->getSVal(Callee); 37 const FunctionDecl *FD = L.getAsFunctionDecl(); 38 39 if (!FD) 40 return false; 41 42 unsigned id = FD->getBuiltinID(); 43 44 if (!id) 45 return false; 46 47 switch (id) { 48 case Builtin::BI__builtin_expect: { 49 // For __builtin_expect, just return the value of the subexpression. 50 assert (CE->arg_begin() != CE->arg_end()); 51 SVal X = state->getSVal(*(CE->arg_begin())); 52 C.generateNode(state->BindExpr(CE, X)); 53 return true; 54 } 55 56 case Builtin::BI__builtin_alloca: { 57 // FIXME: Refactor into StoreManager itself? 58 MemRegionManager& RM = C.getStoreManager().getRegionManager(); 59 const AllocaRegion* R = 60 RM.getAllocaRegion(CE, C.getNodeBuilder().getCurrentBlockCount(), 61 C.getPredecessor()->getLocationContext()); 62 63 // Set the extent of the region in bytes. This enables us to use the 64 // SVal of the argument directly. If we save the extent in bits, we 65 // cannot represent values like symbol*8. 66 DefinedOrUnknownSVal Size = 67 cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()))); 68 69 SValBuilder& svalBuilder = C.getSValBuilder(); 70 DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 71 DefinedOrUnknownSVal extentMatchesSizeArg = 72 svalBuilder.evalEQ(state, Extent, Size); 73 state = state->assume(extentMatchesSizeArg, true); 74 75 C.generateNode(state->BindExpr(CE, loc::MemRegionVal(R))); 76 return true; 77 } 78 } 79 80 return false; 81} 82 83void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 84 mgr.registerChecker<BuiltinFunctionChecker>(); 85} 86