clang API Documentation
00001 //=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This checker evaluates clang builtin functions. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "ClangSACheckers.h" 00015 #include "clang/StaticAnalyzer/Core/Checker.h" 00016 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00017 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 00018 #include "clang/Basic/Builtins.h" 00019 00020 using namespace clang; 00021 using namespace ento; 00022 00023 namespace { 00024 00025 class BuiltinFunctionChecker : public Checker<eval::Call> { 00026 public: 00027 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 00028 }; 00029 00030 } 00031 00032 bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, 00033 CheckerContext &C) const { 00034 ProgramStateRef state = C.getState(); 00035 const FunctionDecl *FD = C.getCalleeDecl(CE); 00036 const LocationContext *LCtx = C.getLocationContext(); 00037 if (!FD) 00038 return false; 00039 00040 unsigned id = FD->getBuiltinID(); 00041 00042 if (!id) 00043 return false; 00044 00045 switch (id) { 00046 case Builtin::BI__builtin_expect: { 00047 // For __builtin_expect, just return the value of the subexpression. 00048 assert (CE->arg_begin() != CE->arg_end()); 00049 SVal X = state->getSVal(*(CE->arg_begin()), LCtx); 00050 C.addTransition(state->BindExpr(CE, LCtx, X)); 00051 return true; 00052 } 00053 00054 case Builtin::BI__builtin_alloca: { 00055 // FIXME: Refactor into StoreManager itself? 00056 MemRegionManager& RM = C.getStoreManager().getRegionManager(); 00057 const AllocaRegion* R = 00058 RM.getAllocaRegion(CE, C.getCurrentBlockCount(), C.getLocationContext()); 00059 00060 // Set the extent of the region in bytes. This enables us to use the 00061 // SVal of the argument directly. If we save the extent in bits, we 00062 // cannot represent values like symbol*8. 00063 DefinedOrUnknownSVal Size = 00064 cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()), LCtx)); 00065 00066 SValBuilder& svalBuilder = C.getSValBuilder(); 00067 DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 00068 DefinedOrUnknownSVal extentMatchesSizeArg = 00069 svalBuilder.evalEQ(state, Extent, Size); 00070 state = state->assume(extentMatchesSizeArg, true); 00071 00072 C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R))); 00073 return true; 00074 } 00075 } 00076 00077 return false; 00078 } 00079 00080 void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 00081 mgr.registerChecker<BuiltinFunctionChecker>(); 00082 }