BuiltinFunctionChecker.cpp revision cab62f8cc4967a6b9b86bb6d2b21562ad5385eb5
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/Checker.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 Checker<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 ProgramState *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.addTransition(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.getCurrentBlockCount(), C.getLocationContext()); 61 62 // Set the extent of the region in bytes. This enables us to use the 63 // SVal of the argument directly. If we save the extent in bits, we 64 // cannot represent values like symbol*8. 65 DefinedOrUnknownSVal Size = 66 cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()))); 67 68 SValBuilder& svalBuilder = C.getSValBuilder(); 69 DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 70 DefinedOrUnknownSVal extentMatchesSizeArg = 71 svalBuilder.evalEQ(state, Extent, Size); 72 state = state->assume(extentMatchesSizeArg, true); 73 74 C.addTransition(state->BindExpr(CE, loc::MemRegionVal(R))); 75 return true; 76 } 77 } 78 79 return false; 80} 81 82void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 83 mgr.registerChecker<BuiltinFunctionChecker>(); 84} 85