clang  9.0.0
BuiltinFunctionChecker.cpp
Go to the documentation of this file.
1 //=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This checker evaluates clang builtin functions.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "clang/Basic/Builtins.h"
19 
20 using namespace clang;
21 using namespace ento;
22 
23 namespace {
24 
25 class BuiltinFunctionChecker : public Checker<eval::Call> {
26 public:
27  bool evalCall(const CallEvent &Call, CheckerContext &C) const;
28 };
29 
30 }
31 
32 bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
33  CheckerContext &C) const {
34  ProgramStateRef state = C.getState();
35  const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
36  if (!FD)
37  return false;
38 
39  const LocationContext *LCtx = C.getLocationContext();
40  const Expr *CE = Call.getOriginExpr();
41 
42  switch (FD->getBuiltinID()) {
43  default:
44  return false;
45 
46  case Builtin::BI__builtin_assume: {
47  assert (Call.getNumArgs() > 0);
48  SVal Arg = Call.getArgSVal(0);
49  if (Arg.isUndef())
50  return true; // Return true to model purity.
51 
52  state = state->assume(Arg.castAs<DefinedOrUnknownSVal>(), true);
53  // FIXME: do we want to warn here? Not right now. The most reports might
54  // come from infeasible paths, thus being false positives.
55  if (!state) {
56  C.generateSink(C.getState(), C.getPredecessor());
57  return true;
58  }
59 
60  C.addTransition(state);
61  return true;
62  }
63 
64  case Builtin::BI__builtin_unpredictable:
65  case Builtin::BI__builtin_expect:
66  case Builtin::BI__builtin_assume_aligned:
67  case Builtin::BI__builtin_addressof: {
68  // For __builtin_unpredictable, __builtin_expect, and
69  // __builtin_assume_aligned, just return the value of the subexpression.
70  // __builtin_addressof is going from a reference to a pointer, but those
71  // are represented the same way in the analyzer.
72  assert (Call.getNumArgs() > 0);
73  SVal Arg = Call.getArgSVal(0);
74  C.addTransition(state->BindExpr(CE, LCtx, Arg));
75  return true;
76  }
77 
78  case Builtin::BI__builtin_alloca_with_align:
79  case Builtin::BI__builtin_alloca: {
80  // FIXME: Refactor into StoreManager itself?
81  MemRegionManager& RM = C.getStoreManager().getRegionManager();
82  const AllocaRegion* R =
83  RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext());
84 
85  // Set the extent of the region in bytes. This enables us to use the
86  // SVal of the argument directly. If we save the extent in bits, we
87  // cannot represent values like symbol*8.
88  auto Size = Call.getArgSVal(0);
89  if (Size.isUndef())
90  return true; // Return true to model purity.
91 
92  SValBuilder& svalBuilder = C.getSValBuilder();
93  DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
94  DefinedOrUnknownSVal extentMatchesSizeArg =
95  svalBuilder.evalEQ(state, Extent, Size.castAs<DefinedOrUnknownSVal>());
96  state = state->assume(extentMatchesSizeArg, true);
97  assert(state && "The region should not have any previous constraints");
98 
99  C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
100  return true;
101  }
102 
103  case Builtin::BI__builtin_dynamic_object_size:
104  case Builtin::BI__builtin_object_size:
105  case Builtin::BI__builtin_constant_p: {
106  // This must be resolvable at compile time, so we defer to the constant
107  // evaluator for a value.
108  SValBuilder &SVB = C.getSValBuilder();
109  SVal V = UnknownVal();
110  Expr::EvalResult EVResult;
111  if (CE->EvaluateAsInt(EVResult, C.getASTContext(), Expr::SE_NoSideEffects)) {
112  // Make sure the result has the correct type.
113  llvm::APSInt Result = EVResult.Val.getInt();
114  BasicValueFactory &BVF = SVB.getBasicValueFactory();
115  BVF.getAPSIntType(CE->getType()).apply(Result);
116  V = SVB.makeIntVal(Result);
117  }
118 
119  if (FD->getBuiltinID() == Builtin::BI__builtin_constant_p) {
120  // If we didn't manage to figure out if the value is constant or not,
121  // it is safe to assume that it's not constant and unsafe to assume
122  // that it's constant.
123  if (V.isUnknown())
124  V = SVB.makeIntVal(0, CE->getType());
125  }
126 
127  C.addTransition(state->BindExpr(CE, LCtx, V));
128  return true;
129  }
130  }
131 }
132 
133 void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
134  mgr.registerChecker<BuiltinFunctionChecker>();
135 }
136 
137 bool ento::shouldRegisterBuiltinFunctionChecker(const LangOptions &LO) {
138  return true;
139 }
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Strictly evaluate the expression.
Definition: Expr.h:606
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:582
This represents one expression.
Definition: Expr.h:108
#define V(N, I)
Definition: ASTContext.h:2907
QualType getType() const
Definition: Expr.h:137
Dataflow Directional Tag Classes.
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:580
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
APSInt & getInt()
Definition: APValue.h:336
Defines enum values for all the target-independent builtin functions.