xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This checker evaluates clang builtin functions.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "ClangSACheckers.h"
15f4a2713aSLionel Sambuc #include "clang/Basic/Builtins.h"
16f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/Checker.h"
17f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/CheckerManager.h"
18f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19f4a2713aSLionel Sambuc 
20f4a2713aSLionel Sambuc using namespace clang;
21f4a2713aSLionel Sambuc using namespace ento;
22f4a2713aSLionel Sambuc 
23f4a2713aSLionel Sambuc namespace {
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc class BuiltinFunctionChecker : public Checker<eval::Call> {
26f4a2713aSLionel Sambuc public:
27f4a2713aSLionel Sambuc   bool evalCall(const CallExpr *CE, CheckerContext &C) const;
28f4a2713aSLionel Sambuc };
29f4a2713aSLionel Sambuc 
30f4a2713aSLionel Sambuc }
31f4a2713aSLionel Sambuc 
evalCall(const CallExpr * CE,CheckerContext & C) const32f4a2713aSLionel Sambuc bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
33f4a2713aSLionel Sambuc                                       CheckerContext &C) const {
34f4a2713aSLionel Sambuc   ProgramStateRef state = C.getState();
35f4a2713aSLionel Sambuc   const FunctionDecl *FD = C.getCalleeDecl(CE);
36f4a2713aSLionel Sambuc   const LocationContext *LCtx = C.getLocationContext();
37f4a2713aSLionel Sambuc   if (!FD)
38f4a2713aSLionel Sambuc     return false;
39f4a2713aSLionel Sambuc 
40f4a2713aSLionel Sambuc   switch (FD->getBuiltinID()) {
41f4a2713aSLionel Sambuc   default:
42f4a2713aSLionel Sambuc     return false;
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc   case Builtin::BI__builtin_expect:
45*0a6a1f1dSLionel Sambuc   case Builtin::BI__builtin_assume_aligned:
46f4a2713aSLionel Sambuc   case Builtin::BI__builtin_addressof: {
47*0a6a1f1dSLionel Sambuc     // For __builtin_expect and __builtin_assume_aligned, just return the value
48*0a6a1f1dSLionel Sambuc     // of the subexpression.
49f4a2713aSLionel Sambuc     // __builtin_addressof is going from a reference to a pointer, but those
50f4a2713aSLionel Sambuc     // are represented the same way in the analyzer.
51f4a2713aSLionel Sambuc     assert (CE->arg_begin() != CE->arg_end());
52f4a2713aSLionel Sambuc     SVal X = state->getSVal(*(CE->arg_begin()), LCtx);
53f4a2713aSLionel Sambuc     C.addTransition(state->BindExpr(CE, LCtx, X));
54f4a2713aSLionel Sambuc     return true;
55f4a2713aSLionel Sambuc   }
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc   case Builtin::BI__builtin_alloca: {
58f4a2713aSLionel Sambuc     // FIXME: Refactor into StoreManager itself?
59f4a2713aSLionel Sambuc     MemRegionManager& RM = C.getStoreManager().getRegionManager();
60f4a2713aSLionel Sambuc     const AllocaRegion* R =
61f4a2713aSLionel Sambuc       RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext());
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc     // Set the extent of the region in bytes. This enables us to use the
64f4a2713aSLionel Sambuc     // SVal of the argument directly. If we save the extent in bits, we
65f4a2713aSLionel Sambuc     // cannot represent values like symbol*8.
66f4a2713aSLionel Sambuc     DefinedOrUnknownSVal Size =
67f4a2713aSLionel Sambuc         state->getSVal(*(CE->arg_begin()), LCtx).castAs<DefinedOrUnknownSVal>();
68f4a2713aSLionel Sambuc 
69f4a2713aSLionel Sambuc     SValBuilder& svalBuilder = C.getSValBuilder();
70f4a2713aSLionel Sambuc     DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
71f4a2713aSLionel Sambuc     DefinedOrUnknownSVal extentMatchesSizeArg =
72f4a2713aSLionel Sambuc       svalBuilder.evalEQ(state, Extent, Size);
73f4a2713aSLionel Sambuc     state = state->assume(extentMatchesSizeArg, true);
74f4a2713aSLionel Sambuc     assert(state && "The region should not have any previous constraints");
75f4a2713aSLionel Sambuc 
76f4a2713aSLionel Sambuc     C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
77f4a2713aSLionel Sambuc     return true;
78f4a2713aSLionel Sambuc   }
79f4a2713aSLionel Sambuc 
80f4a2713aSLionel Sambuc   case Builtin::BI__builtin_object_size: {
81f4a2713aSLionel Sambuc     // This must be resolvable at compile time, so we defer to the constant
82f4a2713aSLionel Sambuc     // evaluator for a value.
83f4a2713aSLionel Sambuc     SVal V = UnknownVal();
84f4a2713aSLionel Sambuc     llvm::APSInt Result;
85f4a2713aSLionel Sambuc     if (CE->EvaluateAsInt(Result, C.getASTContext(), Expr::SE_NoSideEffects)) {
86f4a2713aSLionel Sambuc       // Make sure the result has the correct type.
87f4a2713aSLionel Sambuc       SValBuilder &SVB = C.getSValBuilder();
88f4a2713aSLionel Sambuc       BasicValueFactory &BVF = SVB.getBasicValueFactory();
89f4a2713aSLionel Sambuc       BVF.getAPSIntType(CE->getType()).apply(Result);
90f4a2713aSLionel Sambuc       V = SVB.makeIntVal(Result);
91f4a2713aSLionel Sambuc     }
92f4a2713aSLionel Sambuc 
93f4a2713aSLionel Sambuc     C.addTransition(state->BindExpr(CE, LCtx, V));
94f4a2713aSLionel Sambuc     return true;
95f4a2713aSLionel Sambuc   }
96f4a2713aSLionel Sambuc   }
97f4a2713aSLionel Sambuc }
98f4a2713aSLionel Sambuc 
registerBuiltinFunctionChecker(CheckerManager & mgr)99f4a2713aSLionel Sambuc void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
100f4a2713aSLionel Sambuc   mgr.registerChecker<BuiltinFunctionChecker>();
101f4a2713aSLionel Sambuc }
102