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 20 using namespace clang; 21 using namespace ento; 22 23 namespace { 24 25 class BuiltinFunctionChecker : public Checker<eval::Call> { 26 public: 27 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 28 }; 29 30 } 31 32 bool 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.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.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 83 void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 84 mgr.registerChecker<BuiltinFunctionChecker>(); 85 } 86