clang  19.0.0git
DynamicExtent.cpp
Go to the documentation of this file.
1 //===- DynamicExtent.cpp - Dynamic extent related APIs ----------*- 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 file defines APIs that track and query dynamic extent information.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "clang/AST/Expr.h"
15 #include "clang/Basic/LLVM.h"
21 
24 
25 namespace clang {
26 namespace ento {
27 
28 DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
29  const MemRegion *MR, SValBuilder &SVB) {
30  MR = MR->StripCasts();
31 
32  if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR))
33  if (auto SSize =
34  SVB.convertToArrayIndex(*Size).getAs<DefinedOrUnknownSVal>())
35  return *SSize;
36 
37  return MR->getMemRegionManager().getStaticSize(MR, SVB);
38 }
39 
40 DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) {
41  return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(),
42  SVB.getArrayIndexType());
43 }
44 
45 static DefinedOrUnknownSVal getConstantArrayElementCount(SValBuilder &SVB,
46  const MemRegion *MR) {
47  MR = MR->StripCasts();
48 
49  const auto *TVR = MR->getAs<TypedValueRegion>();
50  if (!TVR)
51  return UnknownVal();
52 
53  if (const ConstantArrayType *CAT =
54  SVB.getContext().getAsConstantArrayType(TVR->getValueType()))
55  return SVB.makeIntVal(CAT->getSize(), /* isUnsigned = */ false);
56 
57  return UnknownVal();
58 }
59 
60 static DefinedOrUnknownSVal
62  DefinedOrUnknownSVal ElementSize) {
63  SValBuilder &SVB = State->getStateManager().getSValBuilder();
64 
65  auto ElementCount =
66  SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType())
67  .getAs<DefinedOrUnknownSVal>();
68  return ElementCount.value_or(UnknownVal());
69 }
70 
71 DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
72  const MemRegion *MR,
73  SValBuilder &SVB,
74  QualType ElementTy) {
75  assert(MR != nullptr && "Not-null region expected");
76  MR = MR->StripCasts();
77 
78  DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);
79  if (ElementSize.isZeroConstant())
80  return getConstantArrayElementCount(SVB, MR);
81 
83  ElementSize);
84 }
85 
87  SValBuilder &SVB = State->getStateManager().getSValBuilder();
88  const MemRegion *MRegion = BufV.getAsRegion();
89  if (!MRegion)
90  return UnknownVal();
91  RegionOffset Offset = MRegion->getAsOffset();
92  if (Offset.hasSymbolicOffset())
93  return UnknownVal();
94  const MemRegion *BaseRegion = MRegion->getBaseRegion();
95  if (!BaseRegion)
96  return UnknownVal();
97 
98  NonLoc OffsetInChars =
99  SVB.makeArrayIndex(Offset.getOffset() / SVB.getContext().getCharWidth());
100  DefinedOrUnknownSVal ExtentInBytes = getDynamicExtent(State, BaseRegion, SVB);
101 
102  return SVB.evalBinOp(State, BinaryOperator::Opcode::BO_Sub, ExtentInBytes,
103  OffsetInChars, SVB.getArrayIndexType());
104 }
105 
107  SVal BufV,
108  QualType ElementTy) {
109  const MemRegion *MR = BufV.getAsRegion();
110  if (!MR)
111  return UnknownVal();
112 
113  SValBuilder &SVB = State->getStateManager().getSValBuilder();
114  DefinedOrUnknownSVal ElementSize = getElementExtent(ElementTy, SVB);
115  if (ElementSize.isZeroConstant())
116  return getConstantArrayElementCount(SVB, MR);
117 
119  ElementSize);
120 }
121 
123  DefinedOrUnknownSVal Size, SValBuilder &SVB) {
124  MR = MR->StripCasts();
125 
126  if (Size.isUnknown())
127  return State;
128 
129  return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
130 }
131 
132 } // namespace ento
133 } // namespace clang
REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *, clang::ento::DefinedOrUnknownSVal) namespace clang
unsigned Offset
Definition: Format.cpp:2978
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
LineState State
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:96
const MemRegion * getAsRegion() const
Definition: SVals.cpp:120
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition: SVals.h:86
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV)
Get the dynamic extent for a symbolic value that represents a buffer.
DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB)
DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB)
ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, DefinedOrUnknownSVal Extent, SValBuilder &SVB)
Set the dynamic extent Extent of the region MR.
DefinedOrUnknownSVal getDynamicElementCountWithOffset(ProgramStateRef State, SVal BufV, QualType Ty)
The JSON file list parser is used to communicate input to InstallAPI.