clang: lib/StaticAnalyzer/Core/BasicValueFactory.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

20#include "llvm/ADT/APSInt.h"

21#include "llvm/ADT/FoldingSet.h"

22#include "llvm/ADT/ImmutableList.h"

23#include "llvm/ADT/STLExtras.h"

24#include "llvm/ADT/SmallPtrSet.h"

25#include

26#include

27#include

28

29using namespace clang;

30using namespace ento;

31

33 llvm::ImmutableList L) {

35 ID.AddPointer(L.getInternalPointer());

36}

37

41 ID.AddPointer(store.getStore());

42 ID.AddPointer(region);

43}

44

46 llvm::FoldingSetNodeID &ID, const NamedDecl *D,

47 llvm::ImmutableList<const CXXBaseSpecifier *> L) {

48 ID.AddPointer(D);

49 ID.AddPointer(L.getInternalPointer());

50}

51

52using SValData = std::pair<SVal, uintptr_t>;

53using SValPair = std::pair<SVal, SVal>;

54

55namespace llvm {

56

59 X.first.Profile(ID);

60 ID.AddPointer( (void*) X.second);

61 }

62};

63

66 X.first.Profile(ID);

67 X.second.Profile(ID);

68 }

69};

70

71}

72

74 llvm::FoldingSet<llvm::FoldingSetNodeWrapper>;

75

77 llvm::FoldingSet<llvm::FoldingSetNodeWrapper>;

78

80

81

82

83 for (const auto &I : APSIntSet)

84 I.getValue().~APSInt();

85

88}

89

90APSIntPtr BasicValueFactory::getValue(const llvm::APSInt &X) {

91 llvm::FoldingSetNodeID ID;

92 void *InsertPos;

93

94 using FoldNodeTy = llvm::FoldingSetNodeWrapperllvm::APSInt;

95

96 X.Profile(ID);

97 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);

98

99 if (P) {

100 P = new (BPAlloc) FoldNodeTy(X);

101 APSIntSet.InsertNode(P, InsertPos);

102 }

103

104

106}

107

110 return getValue(V);

111}

112

113APSIntPtr BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,

116 V = X;

117 return getValue(V);

118}

119

122}

123

126 llvm::ImmutableList Vals) {

127 llvm::FoldingSetNodeID ID;

129 void *InsertPos;

130

131 CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);

132

133 if (D) {

135 CompoundValDataSet.InsertNode(D, InsertPos);

136 }

137

138 return D;

139}

140

144 llvm::FoldingSetNodeID ID;

146 void *InsertPos;

147

149 LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);

150

151 if (D) {

153 LazyCompoundValDataSet.InsertNode(D, InsertPos);

154 }

155

156 return D;

157}

158

160 const NamedDecl *ND, llvm::ImmutableList<const CXXBaseSpecifier *> L) {

161 llvm::FoldingSetNodeID ID;

163 void *InsertPos;

164

166 PointerToMemberDataSet.FindNodeOrInsertPos(ID, InsertPos);

167

168 if (D) {

170 PointerToMemberDataSet.InsertNode(D, InsertPos);

171 }

172

173 return D;

174}

175

177 llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList) {

180 QualType BaseType = BaseSpec->getType();

181

182 if (!BaseSpecSeen.insert(BaseType).second)

183 return false;

184 }

185 return true;

186}

187

189 llvm::iterator_rangeCastExpr::path\_const\_iterator PathRange,

191 assert((kind == CK_DerivedToBaseMemberPointer ||

192 kind == CK_BaseToDerivedMemberPointer ||

193 kind == CK_ReinterpretMemberPointer) &&

194 "accumCXXBase called with wrong CastKind");

197 llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList;

198

199 if (PTMDT.isNull() || isa<const NamedDecl *>(PTMDT)) {

200 if (const auto *NDP = dyn_cast_if_present<const NamedDecl *>(PTMDT))

201 ND = NDP;

202

203 BaseSpecList = CXXBaseListFactory.getEmptyList();

204 } else {

205 const auto *PTMD = cast<const PointerToMemberData *>(PTMDT);

206 ND = PTMD->getDeclaratorDecl();

207

208 BaseSpecList = PTMD->getCXXBaseList();

209 }

210

212 "CXXBaseSpecifier list of PointerToMemberData must not have repeated "

213 "elements");

214

215 if (kind == CK_DerivedToBaseMemberPointer) {

216

217

218

219

220

221

222

223

224

225

226 auto ReducedBaseSpecList = CXXBaseListFactory.getEmptyList();

228 auto IsSameAsBaseSpec = [&BaseSpec](const CXXBaseSpecifier *I) -> bool {

229 return BaseSpec->getType() == I->getType();

230 };

231 if (llvm::none_of(PathRange, IsSameAsBaseSpec))

232 ReducedBaseSpecList =

233 CXXBaseListFactory.add(BaseSpec, ReducedBaseSpecList);

234 }

235

237 }

238

239

243}

244

245std::optional

247 const llvm::APSInt &V2) {

248 switch (Op) {

249 default:

250 llvm_unreachable("Invalid Opcode.");

251

252 case BO_Mul:

253 return getValue(V1 * V2);

254

255 case BO_Div:

256 if (V2 == 0)

257 return std::nullopt;

258 return getValue(V1 / V2);

259

260 case BO_Rem:

261 if (V2 == 0)

262 return std::nullopt;

263 return getValue(V1 % V2);

264

265 case BO_Add:

266 return getValue(V1 + V2);

267

268 case BO_Sub:

269 return getValue(V1 - V2);

270

271 case BO_Shl: {

272

273

274

275 if (V2.isNegative() || V2.getBitWidth() > 64)

276 return std::nullopt;

277

278 uint64_t Amt = V2.getZExtValue();

279

280 if (Amt >= V1.getBitWidth())

281 return std::nullopt;

282

283 return getValue(V1.operator<<((unsigned)Amt));

284 }

285

286 case BO_Shr: {

287

288

289

290 if (V2.isNegative() || V2.getBitWidth() > 64)

291 return std::nullopt;

292

293 uint64_t Amt = V2.getZExtValue();

294

295 if (Amt >= V1.getBitWidth())

296 return std::nullopt;

297

298 return getValue(V1.operator>>((unsigned)Amt));

299 }

300

301 case BO_LT:

303

304 case BO_GT:

306

307 case BO_LE:

309

310 case BO_GE:

312

313 case BO_EQ:

315

316 case BO_NE:

318

319

320

321 case BO_And:

322 return getValue(V1 & V2);

323

324 case BO_Or:

325 return getValue(V1 | V2);

326

327 case BO_Xor:

328 return getValue(V1 ^ V2);

329 }

330}

331

332const std::pair<SVal, uintptr_t>&

334

336

337 llvm::FoldingSetNodeID ID;

338 void *InsertPos;

339 V.Profile(ID);

340 ID.AddPointer((void*) Data);

341

343

344 using FoldNodeTy = llvm::FoldingSetNodeWrapper;

345

346 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);

347

348 if (P) {

349 P = new (BPAlloc) FoldNodeTy(std::make_pair(V, Data));

350 Map.InsertNode(P, InsertPos);

351 }

352

353 return P->getValue();

354}

355

356const std::pair<SVal, SVal>&

358

360

361 llvm::FoldingSetNodeID ID;

362 void *InsertPos;

365

367

368 using FoldNodeTy = llvm::FoldingSetNodeWrapper;

369

370 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);

371

372 if (P) {

373 P = new (BPAlloc) FoldNodeTy(std::make_pair(V1, V2));

374 Map.InsertNode(P, InsertPos);

375 }

376

377 return P->getValue();

378}

379

382}

static bool isUnsigned(SValBuilder &SVB, NonLoc Value)

std::pair< SVal, SVal > SValPair

llvm::FoldingSet< llvm::FoldingSetNodeWrapper< SValData > > PersistentSValsTy

llvm::FoldingSet< llvm::FoldingSetNodeWrapper< SValPair > > PersistentSValPairsTy

std::pair< SVal, uintptr_t > SValData

static LLVM_ATTRIBUTE_UNUSED bool hasNoRepeatedElements(llvm::ImmutableList< const CXXBaseSpecifier * > BaseSpecList)

Represents a base class of a C++ class.

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)

This represents a decl that may have a name.

A (possibly-)qualified type.

A safe wrapper around APSInt objects allocated and owned by BasicValueFactory.

static APSIntPtr unsafeConstructor(const APSInt *Ptr)

You should not use this API.

const CompoundValData * getCompoundValData(QualType T, llvm::ImmutableList< SVal > Vals)

const std::pair< SVal, SVal > & getPersistentSValPair(const SVal &V1, const SVal &V2)

const SVal * getPersistentSVal(SVal X)

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

APSIntType getAPSIntType(QualType T) const

Returns the type of the APSInt used to store values of the given QualType.

std::optional< APSIntPtr > evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)

APSIntPtr getTruthValue(bool b, QualType T)

const PointerToMemberData * getPointerToMemberData(const NamedDecl *ND, llvm::ImmutableList< const CXXBaseSpecifier * > L)

llvm::ImmutableList< const CXXBaseSpecifier * > prependCXXBase(const CXXBaseSpecifier *CBS, llvm::ImmutableList< const CXXBaseSpecifier * > L)

const LazyCompoundValData * getLazyCompoundValData(const StoreRef &store, const TypedValueRegion *region)

const PointerToMemberData * accumCXXBase(llvm::iterator_range< CastExpr::path_const_iterator > PathRange, const nonloc::PointerToMember &PTM, const clang::CastKind &kind)

static void Profile(llvm::FoldingSetNodeID &ID, QualType T, llvm::ImmutableList< SVal > L)

static void Profile(llvm::FoldingSetNodeID &ID, const StoreRef &store, const TypedValueRegion *region)

static void Profile(llvm::FoldingSetNodeID &ID, const NamedDecl *D, llvm::ImmutableList< const CXXBaseSpecifier * > L)

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

void Profile(llvm::FoldingSetNodeID &ID) const

TypedValueRegion - An abstract class representing regions having a typed value.

Value representing pointer-to-member.

llvm::PointerUnion< const NamedDecl *, const PointerToMemberData * > PTMDataType

const PTMDataType getPTMData() const

The JSON file list parser is used to communicate input to InstallAPI.

CastKind

CastKind - The kind of operation required for a conversion.

const FunctionProtoType * T

Diagnostic wrappers for TextAPI types for error reporting.

__UINTPTR_TYPE__ uintptr_t

An unsigned integer type with the property that any valid pointer to void can be converted to this ty...

static void Profile(const SValData &X, llvm::FoldingSetNodeID &ID)

static void Profile(const SValPair &X, llvm::FoldingSetNodeID &ID)