12754fe60SDimitry Andric //=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
22754fe60SDimitry Andric //
32754fe60SDimitry Andric //                     The LLVM Compiler Infrastructure
42754fe60SDimitry Andric //
52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source
62754fe60SDimitry Andric // License. See LICENSE.TXT for details.
72754fe60SDimitry Andric //
82754fe60SDimitry Andric //===----------------------------------------------------------------------===//
92754fe60SDimitry Andric //
102754fe60SDimitry Andric // This checker evaluates clang builtin functions.
112754fe60SDimitry Andric //
122754fe60SDimitry Andric //===----------------------------------------------------------------------===//
132754fe60SDimitry Andric 
14*b5893f02SDimitry Andric #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15139f7f9bSDimitry Andric #include "clang/Basic/Builtins.h"
163b0f4066SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
173b0f4066SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
183b0f4066SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
192754fe60SDimitry Andric 
202754fe60SDimitry Andric using namespace clang;
212754fe60SDimitry Andric using namespace ento;
222754fe60SDimitry Andric 
232754fe60SDimitry Andric namespace {
242754fe60SDimitry Andric 
253b0f4066SDimitry Andric class BuiltinFunctionChecker : public Checker<eval::Call> {
262754fe60SDimitry Andric public:
273b0f4066SDimitry Andric   bool evalCall(const CallExpr *CE, CheckerContext &C) const;
282754fe60SDimitry Andric };
292754fe60SDimitry Andric 
302754fe60SDimitry Andric }
312754fe60SDimitry Andric 
evalCall(const CallExpr * CE,CheckerContext & C) const323b0f4066SDimitry Andric bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
333b0f4066SDimitry Andric                                       CheckerContext &C) const {
34dff0c46cSDimitry Andric   ProgramStateRef state = C.getState();
35dff0c46cSDimitry Andric   const FunctionDecl *FD = C.getCalleeDecl(CE);
36dff0c46cSDimitry Andric   const LocationContext *LCtx = C.getLocationContext();
372754fe60SDimitry Andric   if (!FD)
382754fe60SDimitry Andric     return false;
392754fe60SDimitry Andric 
40f785676fSDimitry Andric   switch (FD->getBuiltinID()) {
41f785676fSDimitry Andric   default:
422754fe60SDimitry Andric     return false;
432754fe60SDimitry Andric 
445517e702SDimitry Andric   case Builtin::BI__builtin_assume: {
455517e702SDimitry Andric     assert (CE->arg_begin() != CE->arg_end());
464ba319b5SDimitry Andric     SVal ArgSVal = C.getSVal(CE->getArg(0));
475517e702SDimitry Andric     if (ArgSVal.isUndef())
485517e702SDimitry Andric       return true; // Return true to model purity.
495517e702SDimitry Andric 
505517e702SDimitry Andric     state = state->assume(ArgSVal.castAs<DefinedOrUnknownSVal>(), true);
515517e702SDimitry Andric     // FIXME: do we want to warn here? Not right now. The most reports might
525517e702SDimitry Andric     // come from infeasible paths, thus being false positives.
53edd7eaddSDimitry Andric     if (!state) {
54edd7eaddSDimitry Andric       C.generateSink(C.getState(), C.getPredecessor());
555517e702SDimitry Andric       return true;
56edd7eaddSDimitry Andric     }
575517e702SDimitry Andric 
585517e702SDimitry Andric     C.addTransition(state);
595517e702SDimitry Andric     return true;
605517e702SDimitry Andric   }
615517e702SDimitry Andric 
620623d748SDimitry Andric   case Builtin::BI__builtin_unpredictable:
63f785676fSDimitry Andric   case Builtin::BI__builtin_expect:
6439d628a0SDimitry Andric   case Builtin::BI__builtin_assume_aligned:
65f785676fSDimitry Andric   case Builtin::BI__builtin_addressof: {
660623d748SDimitry Andric     // For __builtin_unpredictable, __builtin_expect, and
670623d748SDimitry Andric     // __builtin_assume_aligned, just return the value of the subexpression.
68f785676fSDimitry Andric     // __builtin_addressof is going from a reference to a pointer, but those
69f785676fSDimitry Andric     // are represented the same way in the analyzer.
702754fe60SDimitry Andric     assert (CE->arg_begin() != CE->arg_end());
714ba319b5SDimitry Andric     SVal X = C.getSVal(*(CE->arg_begin()));
72dff0c46cSDimitry Andric     C.addTransition(state->BindExpr(CE, LCtx, X));
732754fe60SDimitry Andric     return true;
742754fe60SDimitry Andric   }
752754fe60SDimitry Andric 
7644290647SDimitry Andric   case Builtin::BI__builtin_alloca_with_align:
772754fe60SDimitry Andric   case Builtin::BI__builtin_alloca: {
782754fe60SDimitry Andric     // FIXME: Refactor into StoreManager itself?
792754fe60SDimitry Andric     MemRegionManager& RM = C.getStoreManager().getRegionManager();
802754fe60SDimitry Andric     const AllocaRegion* R =
813861d79fSDimitry Andric       RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext());
822754fe60SDimitry Andric 
832754fe60SDimitry Andric     // Set the extent of the region in bytes. This enables us to use the
842754fe60SDimitry Andric     // SVal of the argument directly. If we save the extent in bits, we
852754fe60SDimitry Andric     // cannot represent values like symbol*8.
864ba319b5SDimitry Andric     auto Size = C.getSVal(*(CE->arg_begin())).castAs<DefinedOrUnknownSVal>();
872754fe60SDimitry Andric 
882754fe60SDimitry Andric     SValBuilder& svalBuilder = C.getSValBuilder();
892754fe60SDimitry Andric     DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
902754fe60SDimitry Andric     DefinedOrUnknownSVal extentMatchesSizeArg =
912754fe60SDimitry Andric       svalBuilder.evalEQ(state, Extent, Size);
922754fe60SDimitry Andric     state = state->assume(extentMatchesSizeArg, true);
93139f7f9bSDimitry Andric     assert(state && "The region should not have any previous constraints");
942754fe60SDimitry Andric 
95dff0c46cSDimitry Andric     C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
962754fe60SDimitry Andric     return true;
972754fe60SDimitry Andric   }
98f785676fSDimitry Andric 
994ba319b5SDimitry Andric   case Builtin::BI__builtin_object_size:
1004ba319b5SDimitry Andric   case Builtin::BI__builtin_constant_p: {
101f785676fSDimitry Andric     // This must be resolvable at compile time, so we defer to the constant
102f785676fSDimitry Andric     // evaluator for a value.
103f785676fSDimitry Andric     SVal V = UnknownVal();
104*b5893f02SDimitry Andric     Expr::EvalResult EVResult;
105*b5893f02SDimitry Andric     if (CE->EvaluateAsInt(EVResult, C.getASTContext(), Expr::SE_NoSideEffects)) {
106f785676fSDimitry Andric       // Make sure the result has the correct type.
107*b5893f02SDimitry Andric       llvm::APSInt Result = EVResult.Val.getInt();
108f785676fSDimitry Andric       SValBuilder &SVB = C.getSValBuilder();
109f785676fSDimitry Andric       BasicValueFactory &BVF = SVB.getBasicValueFactory();
110f785676fSDimitry Andric       BVF.getAPSIntType(CE->getType()).apply(Result);
111f785676fSDimitry Andric       V = SVB.makeIntVal(Result);
1122754fe60SDimitry Andric     }
1132754fe60SDimitry Andric 
114f785676fSDimitry Andric     C.addTransition(state->BindExpr(CE, LCtx, V));
115f785676fSDimitry Andric     return true;
116f785676fSDimitry Andric   }
117f785676fSDimitry Andric   }
1182754fe60SDimitry Andric }
1193b0f4066SDimitry Andric 
registerBuiltinFunctionChecker(CheckerManager & mgr)1203b0f4066SDimitry Andric void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
1213b0f4066SDimitry Andric   mgr.registerChecker<BuiltinFunctionChecker>();
1223b0f4066SDimitry Andric }
123