Skip to content

Commit eddf348

Browse files
committed
[analyzer][NFC] Introduce APSIntPtr, a safe wrapper of APSInt (1/4)
1 parent 76714be commit eddf348

File tree

9 files changed

+147
-90
lines changed

9 files changed

+147
-90
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//== APSIntPtr.h - Wrapper for APSInt objects owned separately -*- 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+
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H
10+
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H
11+
12+
#include "llvm/ADT/APSInt.h"
13+
14+
namespace clang::ento {
15+
class BasicValueFactory;
16+
17+
/// A safe wrapper around APSInt objects allocated and owned by
18+
/// \c BasicValueFactory. This just wraps a common llvm::APSInt.
19+
class APSIntPtr {
20+
using APSInt = llvm::APSInt;
21+
22+
public:
23+
APSIntPtr() = delete;
24+
APSIntPtr(const APSIntPtr &) = default;
25+
APSIntPtr &operator=(const APSIntPtr &) & = default;
26+
~APSIntPtr() = default;
27+
28+
/// You should not use this API.
29+
/// If do, ensure that the \p Ptr not going to dangle.
30+
/// Prefer using \c BasicValueFactory::getValue() to get an APSIntPtr object.
31+
static APSIntPtr unsafeConstructor(const APSInt *Ptr) {
32+
return APSIntPtr(Ptr);
33+
}
34+
35+
const APSInt *get() const { return Ptr; }
36+
/*implicit*/ operator const APSInt &() const { return *get(); }
37+
38+
APSInt operator-() const { return -*Ptr; }
39+
APSInt operator~() const { return ~*Ptr; }
40+
41+
#define DEFINE_OPERATOR(OP) \
42+
bool operator OP(APSIntPtr Other) const { return (*Ptr)OP(*Other.Ptr); }
43+
DEFINE_OPERATOR(>)
44+
DEFINE_OPERATOR(>=)
45+
DEFINE_OPERATOR(<)
46+
DEFINE_OPERATOR(<=)
47+
DEFINE_OPERATOR(==)
48+
DEFINE_OPERATOR(!=)
49+
#undef DEFINE_OPERATOR
50+
51+
const APSInt &operator*() const { return *Ptr; }
52+
const APSInt *operator->() const { return Ptr; }
53+
54+
private:
55+
friend class BasicValueFactory;
56+
explicit APSIntPtr(const APSInt *Ptr) : Ptr(Ptr) {}
57+
58+
/// Owned by \c BasicValueFactory.
59+
const APSInt *Ptr;
60+
};
61+
62+
} // namespace clang::ento
63+
64+
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H

clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
#include "clang/AST/ASTContext.h"
1919
#include "clang/AST/Expr.h"
2020
#include "clang/AST/Type.h"
21+
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h"
2122
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
23+
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
2224
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
2325
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
24-
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
2526
#include "llvm/ADT/APSInt.h"
2627
#include "llvm/ADT/FoldingSet.h"
2728
#include "llvm/ADT/ImmutableList.h"
@@ -129,7 +130,7 @@ class BasicValueFactory {
129130

130131
// This is private because external clients should use the factory
131132
// method that takes a QualType.
132-
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
133+
APSIntPtr getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
133134

134135
public:
135136
BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
@@ -140,9 +141,9 @@ class BasicValueFactory {
140141

141142
ASTContext &getContext() const { return Ctx; }
142143

143-
const llvm::APSInt& getValue(const llvm::APSInt& X);
144-
const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
145-
const llvm::APSInt& getValue(uint64_t X, QualType T);
144+
APSIntPtr getValue(const llvm::APSInt &X);
145+
APSIntPtr getValue(const llvm::APInt &X, bool isUnsigned);
146+
APSIntPtr getValue(uint64_t X, QualType T);
146147

147148
/// Returns the type of the APSInt used to store values of the given QualType.
148149
APSIntType getAPSIntType(QualType T) const {
@@ -165,79 +166,70 @@ class BasicValueFactory {
165166

166167
/// Convert - Create a new persistent APSInt with the same value as 'From'
167168
/// but with the bitwidth and signedness of 'To'.
168-
const llvm::APSInt &Convert(const llvm::APSInt& To,
169-
const llvm::APSInt& From) {
169+
APSIntPtr Convert(const llvm::APSInt &To, const llvm::APSInt &From) {
170170
APSIntType TargetType(To);
171171
if (TargetType == APSIntType(From))
172-
return From;
172+
return APSIntPtr(&From);
173173

174174
return getValue(TargetType.convert(From));
175175
}
176176

177-
const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
177+
APSIntPtr Convert(QualType T, const llvm::APSInt &From) {
178178
APSIntType TargetType = getAPSIntType(T);
179179
return Convert(TargetType, From);
180180
}
181181

182-
const llvm::APSInt &Convert(APSIntType TargetType, const llvm::APSInt &From) {
182+
APSIntPtr Convert(APSIntType TargetType, const llvm::APSInt &From) {
183183
if (TargetType == APSIntType(From))
184-
return From;
184+
return APSIntPtr(&From);
185185

186186
return getValue(TargetType.convert(From));
187187
}
188188

189-
const llvm::APSInt &getIntValue(uint64_t X, bool isUnsigned) {
189+
APSIntPtr getIntValue(uint64_t X, bool isUnsigned) {
190190
QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
191191
return getValue(X, T);
192192
}
193193

194-
const llvm::APSInt &getMaxValue(const llvm::APSInt &v) {
194+
APSIntPtr getMaxValue(const llvm::APSInt &v) {
195195
return getValue(APSIntType(v).getMaxValue());
196196
}
197197

198-
const llvm::APSInt &getMinValue(const llvm::APSInt &v) {
198+
APSIntPtr getMinValue(const llvm::APSInt &v) {
199199
return getValue(APSIntType(v).getMinValue());
200200
}
201201

202-
const llvm::APSInt &getMaxValue(QualType T) {
203-
return getMaxValue(getAPSIntType(T));
204-
}
202+
APSIntPtr getMaxValue(QualType T) { return getMaxValue(getAPSIntType(T)); }
205203

206-
const llvm::APSInt &getMinValue(QualType T) {
207-
return getMinValue(getAPSIntType(T));
208-
}
204+
APSIntPtr getMinValue(QualType T) { return getMinValue(getAPSIntType(T)); }
209205

210-
const llvm::APSInt &getMaxValue(APSIntType T) {
211-
return getValue(T.getMaxValue());
212-
}
206+
APSIntPtr getMaxValue(APSIntType T) { return getValue(T.getMaxValue()); }
213207

214-
const llvm::APSInt &getMinValue(APSIntType T) {
215-
return getValue(T.getMinValue());
216-
}
208+
APSIntPtr getMinValue(APSIntType T) { return getValue(T.getMinValue()); }
217209

218-
const llvm::APSInt &Add1(const llvm::APSInt &V) {
210+
APSIntPtr Add1(const llvm::APSInt &V) {
219211
llvm::APSInt X = V;
220212
++X;
221213
return getValue(X);
222214
}
223215

224-
const llvm::APSInt &Sub1(const llvm::APSInt &V) {
216+
APSIntPtr Sub1(const llvm::APSInt &V) {
225217
llvm::APSInt X = V;
226218
--X;
227219
return getValue(X);
228220
}
229221

230-
const llvm::APSInt &getZeroWithTypeSize(QualType T) {
222+
APSIntPtr getZeroWithTypeSize(QualType T) {
231223
assert(T->isScalarType());
232224
return getValue(0, Ctx.getTypeSize(T), true);
233225
}
234226

235-
const llvm::APSInt &getTruthValue(bool b, QualType T) {
227+
APSIntPtr getTruthValue(bool b, QualType T) {
236228
return getValue(b ? 1 : 0, Ctx.getIntWidth(T),
237229
T->isUnsignedIntegerOrEnumerationType());
238230
}
239231

240-
const llvm::APSInt &getTruthValue(bool b) {
232+
APSIntPtr getTruthValue(bool b) {
241233
return getTruthValue(b, Ctx.getLogicalOperationType());
242234
}
243235

@@ -273,9 +265,9 @@ class BasicValueFactory {
273265
accumCXXBase(llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
274266
const nonloc::PointerToMember &PTM, const clang::CastKind &kind);
275267

276-
const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
277-
const llvm::APSInt& V1,
278-
const llvm::APSInt& V2);
268+
std::optional<APSIntPtr> evalAPSInt(BinaryOperator::Opcode Op,
269+
const llvm::APSInt &V1,
270+
const llvm::APSInt &V2);
279271

280272
const std::pair<SVal, uintptr_t>&
281273
getPersistentSValWithData(const SVal& V, uintptr_t Data);

clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ template <typename T> struct ProgramStateTrait {
7070
/// values will never change.
7171
class ProgramState : public llvm::FoldingSetNode {
7272
public:
73-
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
7473
typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
7574

7675
private:

clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "clang/Basic/JsonSupport.h"
1818
#include "clang/Basic/TargetInfo.h"
19+
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
1920
#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
2021
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
2122
#include <optional>
@@ -154,7 +155,7 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
154155
return nullptr;
155156

156157
// This is the only solution, store it
157-
return &BVF.getValue(Value);
158+
return BVF.getValue(Value).get();
158159
}
159160

160161
if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
@@ -167,7 +168,7 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
167168
const llvm::APSInt *Value;
168169
if (!(Value = getSymVal(State, CastSym)))
169170
return nullptr;
170-
return &BVF.Convert(SC->getType(), *Value);
171+
return BVF.Convert(SC->getType(), *Value).get();
171172
}
172173

173174
if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
@@ -195,7 +196,9 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
195196
std::tie(ConvertedRHS, RTy) = SMTConv::fixAPSInt(Ctx, *RHS);
196197
SMTConv::doIntTypeConversion<llvm::APSInt, &SMTConv::castAPSInt>(
197198
Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
198-
return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
199+
std::optional<APSIntPtr> Res =
200+
BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
201+
return Res ? Res.value().get() : nullptr;
199202
}
200203

201204
llvm_unreachable("Unsupported expression to get symbol value!");

clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,8 +1025,8 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
10251025
BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
10261026
const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
10271027
llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4);
1028-
const llvm::APSInt *maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt,
1029-
fourInt);
1028+
std::optional<APSIntPtr> maxLengthInt =
1029+
BVF.evalAPSInt(BO_Div, maxValInt, fourInt);
10301030
NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt);
10311031
SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn, maxLength,
10321032
svalBuilder.getConditionType());

clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,7 +1643,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
16431643
public:
16441644
GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {}
16451645
std::optional<RangeInt> operator()(QualType Ty) {
1646-
return BVF.getMaxValue(Ty).getLimitedValue();
1646+
return BVF.getMaxValue(Ty)->getLimitedValue();
16471647
}
16481648
std::optional<RangeInt> operator()(std::optional<QualType> Ty) {
16491649
if (Ty) {
@@ -1687,11 +1687,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
16871687
const QualType SizePtrTy = getPointerTy(SizeTy);
16881688
const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy);
16891689

1690-
const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
1690+
const RangeInt IntMax = BVF.getMaxValue(IntTy)->getLimitedValue();
16911691
const RangeInt UnsignedIntMax =
1692-
BVF.getMaxValue(UnsignedIntTy).getLimitedValue();
1693-
const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
1694-
const RangeInt SizeMax = BVF.getMaxValue(SizeTy).getLimitedValue();
1692+
BVF.getMaxValue(UnsignedIntTy)->getLimitedValue();
1693+
const RangeInt LongMax = BVF.getMaxValue(LongTy)->getLimitedValue();
1694+
const RangeInt SizeMax = BVF.getMaxValue(SizeTy)->getLimitedValue();
16951695

16961696
// Set UCharRangeMax to min of int or uchar maximum value.
16971697
// The C standard states that the arguments of functions like isalpha must
@@ -1700,7 +1700,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
17001700
// to be true for commonly used and well tested instruction set
17011701
// architectures, but not for others.
17021702
const RangeInt UCharRangeMax =
1703-
std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax);
1703+
std::min(BVF.getMaxValue(ACtx.UnsignedCharTy)->getLimitedValue(), IntMax);
17041704

17051705
// Get platform dependent values of some macros.
17061706
// Try our best to parse this from the Preprocessor, otherwise fallback to a
@@ -3704,7 +3704,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
37043704

37053705
// Functions for testing.
37063706
if (AddTestFunctions) {
3707-
const RangeInt IntMin = BVF.getMinValue(IntTy).getLimitedValue();
3707+
const RangeInt IntMin = BVF.getMinValue(IntTy)->getLimitedValue();
37083708

37093709
addToFunctionSummaryMap(
37103710
"__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),

clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ ProgramStateRef VLASizeChecker::checkVLA(CheckerContext &C,
9696
SValBuilder &SVB = C.getSValBuilder();
9797
CanQualType SizeTy = Ctx.getSizeType();
9898
uint64_t SizeMax =
99-
SVB.getBasicValueFactory().getMaxValue(SizeTy).getZExtValue();
99+
SVB.getBasicValueFactory().getMaxValue(SizeTy)->getZExtValue();
100100

101101
// Get the element size.
102102
CharUnits EleSize = Ctx.getTypeSizeInChars(VLALast->getElementType());

0 commit comments

Comments
 (0)