1218887Sdim//=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim// This checker evaluates clang builtin functions.
11218887Sdim//
12218887Sdim//===----------------------------------------------------------------------===//
13218887Sdim
14221345Sdim#include "ClangSACheckers.h"
15249423Sdim#include "clang/Basic/Builtins.h"
16221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
17221345Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18221345Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19218887Sdim
20218887Sdimusing namespace clang;
21218887Sdimusing namespace ento;
22218887Sdim
23218887Sdimnamespace {
24218887Sdim
25221345Sdimclass BuiltinFunctionChecker : public Checker<eval::Call> {
26218887Sdimpublic:
27221345Sdim  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
28218887Sdim};
29218887Sdim
30218887Sdim}
31218887Sdim
32221345Sdimbool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
33234353Sdim                                      CheckerContext &C) const {
34234353Sdim  ProgramStateRef state = C.getState();
35234353Sdim  const FunctionDecl *FD = C.getCalleeDecl(CE);
36234353Sdim  const LocationContext *LCtx = C.getLocationContext();
37218887Sdim  if (!FD)
38218887Sdim    return false;
39218887Sdim
40263508Sdim  switch (FD->getBuiltinID()) {
41263508Sdim  default:
42218887Sdim    return false;
43218887Sdim
44263508Sdim  case Builtin::BI__builtin_expect:
45263508Sdim  case Builtin::BI__builtin_addressof: {
46218887Sdim    // For __builtin_expect, just return the value of the subexpression.
47263508Sdim    // __builtin_addressof is going from a reference to a pointer, but those
48263508Sdim    // are represented the same way in the analyzer.
49218887Sdim    assert (CE->arg_begin() != CE->arg_end());
50234353Sdim    SVal X = state->getSVal(*(CE->arg_begin()), LCtx);
51234353Sdim    C.addTransition(state->BindExpr(CE, LCtx, X));
52218887Sdim    return true;
53218887Sdim  }
54218887Sdim
55218887Sdim  case Builtin::BI__builtin_alloca: {
56218887Sdim    // FIXME: Refactor into StoreManager itself?
57218887Sdim    MemRegionManager& RM = C.getStoreManager().getRegionManager();
58218887Sdim    const AllocaRegion* R =
59243830Sdim      RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext());
60218887Sdim
61218887Sdim    // Set the extent of the region in bytes. This enables us to use the
62218887Sdim    // SVal of the argument directly. If we save the extent in bits, we
63218887Sdim    // cannot represent values like symbol*8.
64218887Sdim    DefinedOrUnknownSVal Size =
65249423Sdim        state->getSVal(*(CE->arg_begin()), LCtx).castAs<DefinedOrUnknownSVal>();
66218887Sdim
67218887Sdim    SValBuilder& svalBuilder = C.getSValBuilder();
68218887Sdim    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
69218887Sdim    DefinedOrUnknownSVal extentMatchesSizeArg =
70218887Sdim      svalBuilder.evalEQ(state, Extent, Size);
71218887Sdim    state = state->assume(extentMatchesSizeArg, true);
72249423Sdim    assert(state && "The region should not have any previous constraints");
73218887Sdim
74234353Sdim    C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
75218887Sdim    return true;
76218887Sdim  }
77263508Sdim
78263508Sdim  case Builtin::BI__builtin_object_size: {
79263508Sdim    // This must be resolvable at compile time, so we defer to the constant
80263508Sdim    // evaluator for a value.
81263508Sdim    SVal V = UnknownVal();
82263508Sdim    llvm::APSInt Result;
83263508Sdim    if (CE->EvaluateAsInt(Result, C.getASTContext(), Expr::SE_NoSideEffects)) {
84263508Sdim      // Make sure the result has the correct type.
85263508Sdim      SValBuilder &SVB = C.getSValBuilder();
86263508Sdim      BasicValueFactory &BVF = SVB.getBasicValueFactory();
87263508Sdim      BVF.getAPSIntType(CE->getType()).apply(Result);
88263508Sdim      V = SVB.makeIntVal(Result);
89263508Sdim    }
90263508Sdim
91263508Sdim    C.addTransition(state->BindExpr(CE, LCtx, V));
92263508Sdim    return true;
93218887Sdim  }
94263508Sdim  }
95218887Sdim}
96221345Sdim
97221345Sdimvoid ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
98221345Sdim  mgr.registerChecker<BuiltinFunctionChecker>();
99221345Sdim}
100