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

1

2

3

4

5

6

7

8

9

10

11

12

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

32#include "llvm/ADT/SmallVector.h"

33#include "llvm/Support/Casting.h"

34#include "llvm/Support/ErrorHandling.h"

35#include

36#include

37#include

38

39using namespace clang;

40using namespace ento;

41

43 : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),

44 MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}

45

50

52 Call.getInitialStackFrameContents(LCtx, InitialBindings);

53

54 for (const auto &I : InitialBindings)

56

58}

59

62 uint64_t index) {

65}

66

70 assert(T.isNull());

72}

73

77

78

81

83

84

85

86

87 if (isa<CodeTextRegion, SymbolicRegion>(R))

88 return R;

89

90

91

92 return std::nullopt;

93 }

94

95

96

100

101

102 if (CanonPointeeTy == Ctx.VoidTy)

103 return R;

104

106 if (const auto *TR = dyn_cast(R)) {

109 return true;

110 }

111 return false;

112 };

113

114

115 if (R->isBoundable() && IsSameRegionType(R, CanonPointeeTy))

116 return R;

117

118

120 case MemRegion::CXXThisRegionKind:

121 case MemRegion::CodeSpaceRegionKind:

122 case MemRegion::StackLocalsSpaceRegionKind:

123 case MemRegion::StackArgumentsSpaceRegionKind:

124 case MemRegion::HeapSpaceRegionKind:

125 case MemRegion::UnknownSpaceRegionKind:

126 case MemRegion::StaticGlobalSpaceRegionKind:

127 case MemRegion::GlobalInternalSpaceRegionKind:

128 case MemRegion::GlobalSystemSpaceRegionKind:

129 case MemRegion::GlobalImmutableSpaceRegionKind: {

130 llvm_unreachable("Invalid region cast");

131 }

132

133 case MemRegion::FunctionCodeRegionKind:

134 case MemRegion::BlockCodeRegionKind:

135 case MemRegion::BlockDataRegionKind:

136 case MemRegion::StringRegionKind:

137

138 case MemRegion::SymbolicRegionKind:

139 case MemRegion::AllocaRegionKind:

140 case MemRegion::CompoundLiteralRegionKind:

141 case MemRegion::FieldRegionKind:

142 case MemRegion::ObjCIvarRegionKind:

143 case MemRegion::ObjCStringRegionKind:

144 case MemRegion::NonParamVarRegionKind:

145 case MemRegion::ParamVarRegionKind:

146 case MemRegion::CXXTempObjectRegionKind:

147 case MemRegion::CXXLifetimeExtendedObjectRegionKind:

148 case MemRegion::CXXBaseObjectRegionKind:

149 case MemRegion::CXXDerivedObjectRegionKind:

151

152 case MemRegion::ElementRegionKind: {

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172 const ElementRegion *elementR = cast(R);

175

176

177

178 if (!baseR)

179 return std::nullopt;

180

182

184

185

186

187 if (IsSameRegionType(baseR, CanonPointeeTy))

188 return baseR;

189

191 }

192

193

194

195

196

197

198

199

200 int64_t newIndex = 0;

201 const MemRegion *newSuperR = nullptr;

202

203

205

207 if (!pointeeTySize.isZero()) {

208

209

210

211 if (off % pointeeTySize == 0) {

212 newIndex = off / pointeeTySize;

213 newSuperR = baseR;

214 }

215 }

216 }

217

218 if (!newSuperR) {

219

220

223 }

224

225 return MakeElementRegion(cast(newSuperR), PointeeTy, newIndex);

226 }

227 }

228

229 llvm_unreachable("unreachable");

230}

231

233 const MemRegion *MR = V.getAsRegion();

234 if (!MR)

235 return true;

236

237 const auto *TVR = dyn_cast(MR);

238 if (!TVR)

239 return true;

240

241 const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl();

242 if (!RD)

243 return true;

244

248

250}

251

253

254

257

258

262 }

264}

265

267

269 for (const auto &I : Path)

271 I.Base->isVirtual());

273}

274

276 bool IsVirtual) {

278 if (!DerivedReg)

279 return Derived;

280

282 if (!BaseDecl)

284 assert(BaseDecl && "not a C++ object?");

285

286 if (const auto *AlreadyDerivedReg =

287 dyn_cast(DerivedReg)) {

288 if (const auto *SR =

289 dyn_cast(AlreadyDerivedReg->getSuperRegion()))

290 if (SR->getSymbol()->getType()->getPointeeCXXRecordDecl() == BaseDecl)

292

293 DerivedReg = AlreadyDerivedReg->getSuperRegion();

294 }

295

297 BaseDecl, cast(DerivedReg), IsVirtual);

298

300}

301

302

303

304

305

306

307

309 if (const auto *TVR = dyn_cast(MR))

310 return TVR->getValueType()->getAsCXXRecordDecl();

311 if (const auto *SR = dyn_cast(MR))

312 return SR->getSymbol()->getType()->getPointeeCXXRecordDecl();

313 return nullptr;

314}

315

319 if (!MR)

321

322

324 assert(!TargetType.isNull());

326 if (!TargetClass && !TargetType->isVoidType())

328

329

330

332

333 if (MRClass == TargetClass)

335

336

337

338

339 if (!TargetType->isVoidType() && MRClass->hasDefinition()) {

340

341

342 CXXBasePaths Paths(false, true,

343 false);

344 if (MRClass->isDerivedFrom(TargetClass, Paths))

346 }

347

348 if (const auto *BaseR = dyn_cast(MR)) {

349

350 MR = BaseR->getSuperRegion();

351 continue;

352 }

353

354

357

358

359

360

361

362

363

364

365

367 if (Uncasted == MR) {

368

369

370

371 break;

372 }

373

374 MR = Uncasted;

375 }

376

377

378

379

380

381

382 if (const auto *SR = dyn_cast(MR)) {

383 QualType T = SR->getSymbol()->getType();

385 if (TargetClass && SourceClass && TargetClass->isDerivedFrom(SourceClass))

389 }

390

391

392 if (isa(MR))

393 return std::nullopt;

394

396}

397

398SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {

399 if (Base.isUnknownOrUndef())

401

403 const SubRegion* BaseR = nullptr;

404

405 switch (BaseL.getKind()) {

406 case loc::MemRegionValKind:

408 break;

409

410 case loc::GotoLabelKind:

411

413

414 case loc::ConcreteIntKind:

415

416

417

418

419

420

421

422

423

424

426

427 default:

428 llvm_unreachable("Unhandled Base.");

429 }

430

431

432

433 if (const auto *ID = dyn_cast(D))

435

437}

438

440 return getLValueFieldOrIvar(decl, base);

441}

442

445

446

447

448 if (Offset.isZeroConstant()) {

452 if (!PointeeTy.isNull() &&

455 }

456 }

457

458

459

460

461

462 if (Base.isUnknownOrUndef() || isaloc::ConcreteInt(Base))

464

465 if (isaloc::GotoLabel(Base))

467

470

471

472 const auto *ElemR = dyn_cast(BaseRegion);

473

474

476 if (!Off) {

477

478

479

480

481

483 }

484

485 Offset = Off.value();

486

487 if (!ElemR) {

488

489

490

491

492

493

494

496 BaseRegion, Ctx));

497 }

498

499 SVal BaseIdx = ElemR->getIndex();

500

501 if (!isanonloc::ConcreteInt(BaseIdx))

503

504 const llvm::APSInt &BaseIdxI =

506

507

508

509

510 if (!isanonloc::ConcreteInt(Offset)) {

511 if (isa(BaseRegion->StripCasts()))

513

515 elementType, Offset, cast(ElemR->getSuperRegion()), Ctx));

516 }

517

518 const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue();

519 assert(BaseIdxI.isSigned());

520

521

523 OffI));

524

525

526 const SubRegion *ArrayR = cast(ElemR->getSuperRegion());

529}

530

532

538 if (!SymV || SymV != Sym)

539 return true;

540

541 if (Binding) {

542 First = false;

543 return false;

544 }

545 else

546 Binding = R;

547

548 return true;

549}

Defines the clang::ASTContext interface.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

static bool regionMatchesCXXRecordType(SVal V, QualType Ty)

static const CXXRecordDecl * getCXXRecordType(const MemRegion *MR)

Returns the static type of the given region, if it represents a C++ class object.

C Language Family Type Representation.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

CanQualType getCanonicalType(QualType T) const

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

CharUnits getTypeSizeInChars(QualType T) const

Return the size of the specified (complete) type T, in characters.

Represents a path from a specific derived class (which is not represented as part of the path) to a p...

BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...

Represents a base class of a C++ class.

Represents a C++ struct/union/class.

CXXRecordDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

bool isDerivedFrom(const CXXRecordDecl *Base) const

Determine whether this class is derived from the class Base.

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

CharUnits - This is an opaque type for sizes expressed in character units.

bool isZero() const

isZero - Test whether the quantity equals zero.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

Decl - This represents one declaration (or definition), e.g.

ObjCIvarDecl - Represents an ObjC instance variable.

A (possibly-)qualified type.

QualType getLocalUnqualifiedType() const

Return this type with all of the instance-specific qualifiers removed, but without removing any quali...

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getCanonicalType() const

It represents a stack frame of the call stack (based on CallEvent).

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isBlockPointerType() const

const CXXRecordDecl * getPointeeCXXRecordDecl() const

If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isIncompleteType(NamedDecl **Def=nullptr) const

Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...

bool isObjCObjectPointerType() const

Represents an abstract call to a function or method along a particular path.

ElementRegion is used to represent both array elements and casts.

RegionRawOffset getAsArrayOffset() const

Compute the offset within the array. The array might also be a subobject.

const CXXDerivedObjectRegion * getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super)

Create a CXXDerivedObjectRegion with the given derived class for region Super.

const FieldRegion * getFieldRegion(const FieldDecl *fd, const SubRegion *superRegion)

getFieldRegion - Retrieve or create the memory region associated with a specified FieldDecl.

const ElementRegion * getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, const ASTContext &Ctx)

getElementRegion - Retrieve the memory region associated with the associated element type,...

const ObjCIvarRegion * getObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *superRegion)

getObjCIvarRegion - Retrieve or create the memory region associated with a specified Objective-c inst...

const CXXBaseObjectRegion * getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, bool IsVirtual)

Create a CXXBaseObjectRegion with the given base class for region Super.

MemRegion - The root abstract class for all memory regions.

virtual bool isBoundable() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const

ASTContext & getContext()

CharUnits getOffset() const

const MemRegion * getRegion() const

BasicValueFactory & getBasicValueFactory()

NonLoc makeArrayIndex(uint64_t idx)

ASTContext & getContext()

SVal convertToArrayIndex(SVal val)

NonLoc makeZeroArrayIndex()

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

std::optional< T > getAs() const

Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.

SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const

If this SVal is a location and wraps a symbol, return that SymbolRef.

const MemRegion * getAsRegion() const

T castAs() const

Convert to the specified SVal type, asserting that this SVal is of the desired type.

virtual ~BindingsHandler()

bool HandleBinding(StoreManager &SMgr, Store store, const MemRegion *R, SVal val) override

SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)

Evaluates a chain of derived-to-base casts through the path specified in Cast.

ProgramStateManager & StateMgr

std::optional< SVal > evalBaseToDerived(SVal Base, QualType DerivedPtrType)

Attempts to do a down cast.

const ElementRegion * MakeElementRegion(const SubRegion *baseRegion, QualType pointeeTy, uint64_t index=0)

StoreRef enterStackFrame(Store store, const CallEvent &Call, const StackFrameContext *CalleeCtx)

enterStackFrame - Let the StoreManager to do something when execution engine is about to execute into...

MemRegionManager & MRMgr

MRMgr - Manages region objects associated with this StoreManager.

SValBuilder & svalBuilder

virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base)

StoreManager(ProgramStateManager &stateMgr)

const ElementRegion * GetElementZeroRegion(const SubRegion *R, QualType T)

virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base)

std::optional< const MemRegion * > castRegion(const MemRegion *region, QualType CastToTy)

castRegion - Used by ExprEngine::VisitCast to handle casts from a MemRegion* to a specific location t...

SubRegion - A region that subsets another larger region.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const

Get the underlining region.

Value representing integer constant.

const internal::VariadicAllOfMatcher< Decl > decl

Matches declarations.

const void * Store

Store - This opaque type encapsulates an immutable mapping from locations to values.

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

@ Bind

'bind' clause, allowed on routine constructs.

@ Result

The result type of a method or function.

const FunctionProtoType * T