BuiltinFunctionChecker.cpp revision b805c8ff133ef0c62df032fa711d6b13c5afd7f4
12e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor//=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===// 22e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// 32e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// The LLVM Compiler Infrastructure 42e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// 52e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// This file is distributed under the University of Illinois Open Source 62e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// License. See LICENSE.TXT for details. 72e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// 82e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor//===----------------------------------------------------------------------===// 92e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// 102e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// This checker evaluates clang builtin functions. 112e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor// 122e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor//===----------------------------------------------------------------------===// 132e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 142e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor#include "ClangSACheckers.h" 152e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor#include "clang/StaticAnalyzer/Core/Checker.h" 162e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor#include "clang/StaticAnalyzer/Core/CheckerManager.h" 172e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 182e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor#include "clang/Basic/Builtins.h" 192e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 202e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregorusing namespace clang; 212e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregorusing namespace ento; 222e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 232e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregornamespace { 242e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 25011bb4edf731d529da1cbf71c7c2696aaf5a054fChris Lattnerclass BuiltinFunctionChecker : public Checker<eval::Call> { 26011bb4edf731d529da1cbf71c7c2696aaf5a054fChris Lattnerpublic: 27011bb4edf731d529da1cbf71c7c2696aaf5a054fChris Lattner bool evalCall(const CallExpr *CE, CheckerContext &C) const; 282e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor}; 29011bb4edf731d529da1cbf71c7c2696aaf5a054fChris Lattner 302a3009a432bdcec59e6383d7b2b17494d6f91649Douglas Gregor} 312e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 322e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregorbool BuiltinFunctionChecker::evalCall(const CallExpr *CE, 332e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor CheckerContext &C) const { 342e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor const ProgramState *state = C.getState(); 352e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor const FunctionDecl *FD = C.getCalleeDecl(CE); 362e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor if (!FD) 372e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor return false; 382e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 392e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor unsigned id = FD->getBuiltinID(); 402e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 412e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor if (!id) 422e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor return false; 432e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 442e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor switch (id) { 452e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor case Builtin::BI__builtin_expect: { 462e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor // For __builtin_expect, just return the value of the subexpression. 472e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor assert (CE->arg_begin() != CE->arg_end()); 48e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor SVal X = state->getSVal(*(CE->arg_begin())); 492a3009a432bdcec59e6383d7b2b17494d6f91649Douglas Gregor C.addTransition(state->BindExpr(CE, X)); 502a3009a432bdcec59e6383d7b2b17494d6f91649Douglas Gregor return true; 512e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor } 522e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 532e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor case Builtin::BI__builtin_alloca: { 542e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor // FIXME: Refactor into StoreManager itself? 552e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor MemRegionManager& RM = C.getStoreManager().getRegionManager(); 562e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor const AllocaRegion* R = 572e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor RM.getAllocaRegion(CE, C.getCurrentBlockCount(), C.getLocationContext()); 582e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 592e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor // Set the extent of the region in bytes. This enables us to use the 60e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor // SVal of the argument directly. If we save the extent in bits, we 612e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor // cannot represent values like symbol*8. 622e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor DefinedOrUnknownSVal Size = 632e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()))); 642e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 652e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor SValBuilder& svalBuilder = C.getSValBuilder(); 662e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 672e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor DefinedOrUnknownSVal extentMatchesSizeArg = 682e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor svalBuilder.evalEQ(state, Extent, Size); 69e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor state = state->assume(extentMatchesSizeArg, true); 70e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor 712e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor C.addTransition(state->BindExpr(CE, loc::MemRegionVal(R))); 72e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor return true; 73e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor } 74e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor } 752e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor 76e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor return false; 77e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor} 78e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor 792e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregorvoid ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 80e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor mgr.registerChecker<BuiltinFunctionChecker>(); 81e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor} 82e94ca9e4371c022329270436b3dd77adc4ddfa8fDouglas Gregor