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