clang: lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

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

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

18#include

19

20using namespace clang;

21using namespace ento;

23

29

30

31

32

37 return std::string(RD->getName());

39}

40

41

42

46 bool DeallocSent) {

47

48 RefVal PrevV = *PrevT;

49

50

51 if (DeallocSent) {

52

53 assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");

54

55

58 os << "Object released by directly sending the '-dealloc' message";

59 return true;

60 }

61 }

62

63

65 switch (CurrV.getKind()) {

69

71 return false;

72

74 os << "Object autoreleased";

75 return true;

76 }

77

79 os << "Reference count decremented.";

80 else

81 os << "Reference count incremented.";

82

83 if (unsigned Count = CurrV.getCount())

84 os << " The object now has a +" << Count << " retain count.";

85

86 return true;

87

90 RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&

92 os << "Strong instance variable relinquished. ";

93 }

94 os << "Object released.";

95 return true;

96

98

100 return false;

101

102 os << "Object returned to caller as an owning reference (single "

103 "retain count transferred to caller)";

104 return true;

105

107 os << "Object returned to caller with a +0 retain count";

108 return true;

109

110 default:

111 return false;

112 }

113 return true;

114}

115

116

117

118

119static std::optional

122 if (!CE)

123 return std::nullopt;

124

125 for (unsigned Idx = 0; Idx < (*CE)->getNumArgs(); Idx++)

126 if (const MemRegion *MR = (*CE)->getArgSVal(Idx).getAsRegion())

127 if (const auto *TR = dyn_cast(MR))

128 if (CurrSt->getSVal(MR, TR->getValueType()).getAsSymbol() == Sym)

129 return Idx;

130

131 return std::nullopt;

132}

133

135 if (const auto *ME = dyn_cast(Callee)) {

136 if (ME->getMemberDecl()->getNameAsString() != "alloc")

137 return std::nullopt;

138 const Expr *This = ME->getBase()->IgnoreParenImpCasts();

139 if (const auto *DRE = dyn_cast(This)) {

140 const ValueDecl *VD = DRE->getDecl();

142 return std::nullopt;

143

144 if (const auto *RD = dyn_cast(VD->getDeclContext()))

146

147 }

148 }

149 return std::nullopt;

150}

151

153 if (const auto *CE = dyn_cast(S))

155 return *Out;

157}

158

162 const Stmt *S,

163 llvm::raw_string_ostream &os) {

164 CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();

165 if (const CallExpr *CE = dyn_cast(S)) {

166

167

168 SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);

170

171

172 if (!FD)

173 FD = dyn_cast(CE->getCalleeDecl());

174

175 if (const auto *MD = dyn_cast(CE->getCalleeDecl())) {

176 os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';

177 } else if (FD) {

179 } else {

180 os << "function call";

181 }

183 os << "Operator 'new'";

184 } else {

188

189 switch (Call->getMessageKind()) {

191 os << "Method";

192 break;

194 os << "Property";

195 break;

197 os << "Subscript";

198 break;

199 }

200 }

201

202 std::optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx, {nullptr, 0});

204

205

206 if (!Idx) {

207 os << " returns ";

208 } else {

209 os << " writes ";

210 }

211

212 if (CurrV.getObjKind() == ObjKind::CF) {

213 os << "a Core Foundation object of type '" << Sym->getType() << "' with a ";

214 } else if (CurrV.getObjKind() == ObjKind::OS) {

216 << "' with a ";

217 } else if (CurrV.getObjKind() == ObjKind::Generalized) {

218 os << "an object of type '" << Sym->getType() << "' with a ";

219 } else {

220 assert(CurrV.getObjKind() == ObjKind::ObjC);

223 os << "an Objective-C object with a ";

224 } else {

226 os << "an instance of " << PT->getPointeeType() << " with a ";

227 }

228 }

229

231 os << "+1 retain count";

232 } else {

234 os << "+0 retain count";

235 }

236

237 if (Idx) {

238 os << " into an out parameter '";

239 const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];

241 false);

242 os << "'";

243

244 QualType RT = (*CE)->getResultType();

246 SVal RV = (*CE)->getReturnValue();

247 if (CurrSt->isNull(RV).isConstrainedTrue()) {

248 os << " (assuming the call returns zero)";

249 } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {

250 os << " (assuming the call returns non-zero)";

251 }

252

253 }

254 }

255}

256

258namespace ento {

260

262protected:

265

266public:

269

270 void Profile(llvm::FoldingSetNodeID &ID) const override {

271 static int x = 0;

272 ID.AddPointer(&x);

273 ID.AddPointer(Sym);

274 }

275

279

283};

284

286public:

289 LastBinding(LastBinding) {}

290

294

295private:

297};

298

299}

300}

301}

302

303

304

308 return nullptr;

310 if (!PC)

311 return nullptr;

312

316 }

317 return N;

318}

319

320

321

322

323

324static std::shared_ptr

329

331 if (!CN)

332 return nullptr;

333

335

336 std::string sbuf;

337 llvm::raw_string_ostream os(sbuf);

339 for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {

341

342 if (!PVD->hasAttr())

343 continue;

344

345 if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {

348

349 if (!CountBeforeCall || !CountAtExit)

350 continue;

351

352 unsigned CountBefore = CountBeforeCall->getCount();

353 unsigned CountAfter = CountAtExit->getCount();

354

355 bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;

356 if (!AsExpected) {

357 os << "Parameter '";

359 false);

360 os << "' is marked as consuming, but the function did not consume "

361 << "the reference\n";

362 }

363 }

364 }

365

366 if (sbuf.empty())

367 return nullptr;

368

370 return std::make_shared(L, sbuf);

371}

372

373

374static std::shared_ptr

378 if (!PP)

379 return nullptr;

380

381 const CFGBlock *Src = PP->getSrc();

383

386 return nullptr;

387

391

392 std::string s;

393 llvm::raw_string_ostream os(s);

394 os << "Parameter '" << PVD->getDeclName() << "' starts at +";

395 if (CurrT->getCount() == 1) {

396 os << "1, as it is marked as consuming";

397 } else {

398 assert(CurrT->getCount() == 0);

399 os << "0";

400 }

401 return std::make_shared(L, s);

402}

403

411 return PD;

412

414 return PD;

415

416

417

419 return nullptr;

420

421

426

428 if (!CurrT)

429 return nullptr;

430

431 const RefVal &CurrV = *CurrT;

433

434

435

436 std::string sbuf;

437 llvm::raw_string_ostream os(sbuf);

438

440 os << "Object is now not exclusively owned";

442 return std::make_shared(Pos, sbuf);

443 }

444

445

446

447 if (!PrevT) {

449

453 }

454

456 os << "NSArray literal is an object with a +0 retain count";

458 os << "NSDictionary literal is an object with a +0 retain count";

459 } else if (const ObjCBoxedExpr *BL = dyn_cast(S)) {

461 os << "NSNumber literal is an object with a +0 retain count";

462 else {

465 BoxClass = Method->getClassInterface();

466

467

468

469 if (BoxClass) {

470 os << *BoxClass << " b";

471 } else {

472 os << "B";

473 }

474

475 os << "oxed expression produces an object with a +0 retain count";

476 }

478 os << "Object loaded from instance variable";

479 } else {

481 }

482

484 return std::make_shared(Pos, sbuf);

485 }

486

487

488

489 bool DeallocSent = false;

490

492

494 os << "Assuming dynamic cast returns null due to type mismatch";

495 }

496

498

499

501

502 if (const CallExpr *CE = dyn_cast(S)) {

503

504

505 unsigned i = 0;

506

507 for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {

508

509

510

511 if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)

512 continue;

513

514

515 DeallocSent = true;

516 }

517 } else if (const ObjCMessageExpr *ME = dyn_cast(S)) {

518 if (const Expr *receiver = ME->getInstanceReceiver()) {

519 if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)

520 .getAsLocSymbol() == Sym) {

521

522 DeallocSent = true;

523 }

524 }

525 }

526 }

527

529 return nullptr;

530

531 if (sbuf.empty())

532 return nullptr;

533

537 auto P = std::make_shared(Pos, sbuf);

538

539

540

542 if (const Expr *Exp = dyn_cast_or_null(Child))

543 if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {

544 P->addRange(Exp->getSourceRange());

545 break;

546 }

547

548 return std::move(P);

549}

550

552 if (const auto *VR = dyn_cast_or_null(MR))

553 return std::string(VR->getDecl()->getName());

554

555

556 return std::nullopt;

557}

558

560

561namespace {

565

566public:

568 : Sym(Sym), Result(ToFill) {}

569

571 SVal Val) override {

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

574 return true;

575

577 Result.emplace_back(R, Val);

578

579 return true;

580 }

581};

582}

583

588 VarBindingsCollector Collector{Sym, Result};

589 while (Result.empty() && Node) {

592 }

593

594 return Result;

595}

596

597namespace {

598

599

600

601

602

603struct AllocationInfo {

604 const ExplodedNode* N;

605 const MemRegion *R;

606 const LocationContext *InterestingMethodContext;

607 AllocationInfo(const ExplodedNode *InN,

608 const MemRegion *InR,

609 const LocationContext *InInterestingMethodContext) :

610 N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}

611};

612}

613

617 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;

618 const MemRegion *FirstBinding = nullptr;

620

621

622

624

625 while (N) {

628

630 break;

631

634

635 if (FB) {

637

638

640 if (MR->getStackFrame() == LeakContext->getStackFrame())

641 FirstBinding = R;

642 }

643

644

645 AllocationNode = N;

646

647

648

649

650

651

652

653

654 if (NContext == LeakContext || NContext->isParentOf(LeakContext))

655 AllocationNodeInCurrentOrParentContext = N;

656

657

658

659 if (!InitMethodContext)

661 const Stmt *CE = CEP->getCallExpr();

662 if (const auto *ME = dyn_cast_or_null(CE)) {

663 const Stmt *RecExpr = ME->getInstanceReceiver();

664 if (RecExpr) {

665 SVal RecV = St->getSVal(RecExpr, NContext);

667 InitMethodContext = CEP->getCalleeContext();

668 }

669 }

670 }

671

673 }

674

675

676

677 const LocationContext *InterestingMethodContext = nullptr;

678 if (InitMethodContext) {

680 if (std::optional SP = AllocPP.getAs<StmtPoint>())

682 if (ME->getMethodFamily() == OMF_alloc)

683 InterestingMethodContext = InitMethodContext;

684 }

685

686

687

688 assert(N && "Could not find allocation node");

689

690 if (AllocationNodeInCurrentOrParentContext &&

692 LeakContext)

693 FirstBinding = nullptr;

694

695 return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,

696 InterestingMethodContext);

697}

698

706

711

712

713

715

717

718 std::string sbuf;

719 llvm::raw_string_ostream os(sbuf);

720

721 os << "Object leaked: ";

722

723 std::optionalstd::string RegionDescription = describeRegion(LastBinding);

724 if (RegionDescription) {

725 os << "object allocated and stored into '" << *RegionDescription << '\'';

726 } else {

728 << "'";

729 }

730

731

733 assert(RV);

734

737

738 os << (isa(D) ? " is returned from a method "

739 : " is returned from a function ");

740

741 if (D->hasAttr()) {

742 os << "that is annotated as CF_RETURNS_NOT_RETAINED";

743 } else if (D->hasAttr()) {

744 os << "that is annotated as NS_RETURNS_NOT_RETAINED";

745 } else if (D->hasAttr()) {

746 os << "that is annotated as OS_RETURNS_NOT_RETAINED";

747 } else {

748 if (const ObjCMethodDecl *MD = dyn_cast(D)) {

750 os << "managed by Automatic Reference Counting";

751 } else {

752 os << "whose name ('" << MD->getSelector().getAsString()

753 << "') does not start with "

754 "'copy', 'mutableCopy', 'alloc' or 'new'."

755 " This violates the naming convention rules"

756 " given in the Memory Management Guide for Cocoa";

757 }

758 } else {

762 os << "whose name ('" << *FD

763 << "') does not contain 'Copy' or 'Create'. This violates the "

764 "naming convention rules given in the Memory Management Guide "

765 "for Core Foundation";

768 os << "whose name ('" << FuncName << "') starts with '"

769 << StringRef(FuncName).substr(0, 3) << "'";

770 }

771 }

772 }

773 } else {

774 os << " is not referenced later in this execution path and has a retain "

775 "count of +"

777 }

778

779 return std::make_shared(L, sbuf);

780}

781

784 bool IsReleaseUnowned)

789}

790

793 StringRef endText)

795

797}

798

799void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {

801

803 return;

804

806 if (Region) {

807 const Decl *PDecl = Region->getDecl();

808 if (isa_and_nonnull(PDecl)) {

811 Location = ParamLocation;

814 }

815 }

816}

817

818void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {

819

820

821

822

823

824

825

826

828

830

831 AllocationInfo AllocI =

833

834 AllocNode = AllocI.N;

835 AllocFirstBinding = AllocI.R;

837

838

839

840

841

843

844 if (!AllocStmt) {

845 AllocFirstBinding = nullptr;

846 return;

847 }

848

851 Location = AllocLocation;

852

853

854

857}

858

859void RefLeakReport::createDescription(CheckerContext &Ctx) {

862 llvm::raw_string_ostream os(Description);

863 os << "Potential leak of an object";

864

865 std::optionalstd::string RegionDescription =

867 if (RegionDescription) {

868 os << " stored into '" << *RegionDescription << '\'';

869 } else {

870

871

873 }

874}

875

876void RefLeakReport::findBindingToReport(CheckerContext &Ctx,

877 ExplodedNode *Node) {

878 if (!AllocFirstBinding)

879

880

881 return;

882

883

884 if (Node->getState()->getSVal(AllocFirstBinding).getAsSymbol() == Sym) {

885

886 AllocBindingToReport = AllocFirstBinding;

887 return;

888 }

889

890

891

892

893

894

895

896

897

898

899

900

901

902

905

906

907

908

909 if (!AllVarBindings.empty() &&

910 !llvm::is_contained(llvm::make_first_range(AllVarBindings),

911 AllocFirstBinding)) {

912

913 AllocBindingToReport = AllVarBindings[0].first;

914

915

916

917

918

919

920

921

922

923

925 AllocBindingToReport, *this);

926 } else {

927 AllocBindingToReport = AllocFirstBinding;

928 }

929}

930

935

936 deriveAllocLocation(Ctx);

937 findBindingToReport(Ctx, N);

938

939 if (!AllocFirstBinding)

940 deriveParamLocation(Ctx);

941

942 createDescription(Ctx);

943

945}

static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)

static std::shared_ptr< PathDiagnosticEventPiece > annotateStartParameter(const ExplodedNode *N, SymbolRef Sym, const SourceManager &SM)

Annotate the parameter at the analysis entry point.

Definition RetainCountDiagnostics.cpp:375

static std::string getPrettyTypeName(QualType QT)

If type represents a pointer to CXXRecordDecl, and is not a typedef, return the decl name.

Definition RetainCountDiagnostics.cpp:33

static bool shouldGenerateNote(llvm::raw_string_ostream &os, const RefVal *PrevT, const RefVal &CurrV, bool DeallocSent)

Write information about the type state change to os, return whether the note should be generated.

Definition RetainCountDiagnostics.cpp:43

static bool isNumericLiteralExpression(const Expr *E)

Definition RetainCountDiagnostics.cpp:24

static std::optional< unsigned > findArgIdxOfSymbol(ProgramStateRef CurrSt, const LocationContext *LCtx, SymbolRef &Sym, std::optional< CallEventRef<> > CE)

Finds argument index of the out paramter in the call S corresponding to the symbol Sym.

Definition RetainCountDiagnostics.cpp:120

static std::shared_ptr< PathDiagnosticEventPiece > annotateConsumedSummaryMismatch(const ExplodedNode *N, CallExitBegin &CallExitLoc, const SourceManager &SM, CallEventManager &CEMgr)

Insert a diagnostic piece at function exit if a function parameter is annotated as "os_consumed",...

Definition RetainCountDiagnostics.cpp:325

llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings

Definition RetainCountDiagnostics.cpp:559

static std::string findAllocatedObjectName(const Stmt *S, QualType QT)

Definition RetainCountDiagnostics.cpp:152

static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym)

Definition RetainCountDiagnostics.cpp:614

static std::optional< std::string > describeRegion(const MemRegion *MR)

Definition RetainCountDiagnostics.cpp:551

static std::optional< std::string > findMetaClassAlloc(const Expr *Callee)

Definition RetainCountDiagnostics.cpp:134

static const ExplodedNode * getCalleeNode(const ExplodedNode *Pred)

Find the first node with the parent stack frame.

Definition RetainCountDiagnostics.cpp:305

static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt, const LocationContext *LCtx, const RefVal &CurrV, SymbolRef &Sym, const Stmt *S, llvm::raw_string_ostream &os)

Definition RetainCountDiagnostics.cpp:159

static Bindings getAllVarBindingsForSymbol(ProgramStateManager &Manager, const ExplodedNode *Node, SymbolRef Sym)

Definition RetainCountDiagnostics.cpp:584

__device__ __2f16 float __ockl_bool s

a trap message and trap category.

const LangOptions & getLangOpts() const

const clang::PrintingPolicy & getPrintingPolicy() const

Represents a single basic block in a source-level CFG.

A boolean literal, per ([C++ lex.bool] Boolean literals).

Represents a point when we begin processing an inlined call.

Represents a point when we start the call exit sequence (for inlined call).

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

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

ASTContext & getASTContext() const LLVM_READONLY

DeclContext * getDeclContext()

This represents one expression.

Represents a function declaration or definition.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

bool isParentOf(const LocationContext *LC) const

const Decl * getDecl() const

const LocationContext * getParent() const

It might return null.

const StackFrameContext * getStackFrame() const

std::string getQualifiedNameAsString() const

std::string getNameAsString() const

Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...

virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const

Appends a human-readable name for this declaration into the given stream.

ObjCBoolLiteralExpr - Objective-C Boolean Literal.

ObjCBoxedExpr - used for generalized expression boxing.

Represents an ObjC class declaration.

An expression that sends a message to the given Objective-C object or class.

ObjCMethodDecl - Represents an instance or class method declaration.

Represents a pointer to an Objective C object.

QualType getPointeeType() const

Gets the type pointed to by this ObjC pointer.

Represents a parameter to a function.

ProgramPoints can be "tagged" as representing points specific to a given analysis entity.

const ProgramPointTag * getTag() const

T castAs() const

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

std::optional< T > getAs() const

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

A (possibly-)qualified type.

bool isNull() const

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

static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)

This class handles loading and caching of source files into memory.

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

const Stmt * getCallSite() const

bool inTopFrame() const override

Stmt - This represents one statement.

CXXRecordDecl * getAsCXXRecordDecl() const

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

QualType getPointeeType() const

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

const T * getAs() const

Member-template getAs'.

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

ASTContext & getASTContext() const

ProgramStateManager & getStateManager() const

const SourceManager & getSourceManager() const

BugReporterVisitor()=default

static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N, const PathSensitiveBugReport &BR)

Generates the default final diagnostic piece.

Manages the lifetime of CallEvent objects.

CallEventRef getCall(const Stmt *S, ProgramStateRef State, const LocationContext *LC, CFGBlock::ConstCFGElementRef ElemRef)

Gets a call event for a function call, Objective-C method call, a 'new', or a 'delete' call.

CallEventRef< ObjCMethodCall > getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)

CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)

Gets an outside caller given a callee context.

const SourceManager & getSourceManager()

ProgramStateManager & getStateManager()

const LocationContext * getLocationContext() const

const ProgramStateRef & getState() const

const Stmt * getStmtForDiagnostics() const

If the node's program point corresponds to a statement, retrieve that statement.

ProgramPoint getLocation() const

getLocation - Returns the edge associated with the given node.

const StackFrameContext * getStackFrame() const

const LocationContext * getLocationContext() const

std::optional< T > getLocationAs() const &

ExplodedNode * getFirstPred()

const Decl & getCodeDecl() const

MemRegion - The root abstract class for all memory regions.

const MemSpace * getMemorySpaceAs(ProgramStateRef State) const

static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)

Create a location for the beginning of the declaration.

static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)

Create a location corresponding to the given declaration.

void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)

Marks a symbol as interesting.

PathDiagnosticLocation UniqueingLocation

Reports with different uniqueing locations are considered to be different for the purposes of dedupli...

const ExplodedNode * getErrorNode() const

PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode)

void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)

Add custom or predefined bug report visitors to this report.

const Decl * UniqueingDecl

CallEventManager & getCallEventManager()

void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)

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

SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const

If this SVal wraps a symbol return that SymbolRef.

SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const

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

const MemRegion * getRegion()

virtual const MemRegion * getOriginRegion() const

Find the region from which this symbol originates.

virtual QualType getType() const =0

void Profile(llvm::FoldingSetNodeID &ID) const override

Definition RetainCountDiagnostics.cpp:270

SymbolRef Sym

Definition RetainCountDiagnostics.cpp:263

PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override

Return a diagnostic piece which should be associated with the given node.

Definition RetainCountDiagnostics.cpp:405

PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR) override

Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...

Definition RetainCountDiagnostics.cpp:700

bool IsReleaseUnowned

Definition RetainCountDiagnostics.cpp:264

RefCountReportVisitor(SymbolRef S, bool IRU)

Definition RetainCountDiagnostics.cpp:267

RefCountReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n, SymbolRef sym, bool isLeak=false, bool IsReleaseUnowned=false)

Definition RetainCountDiagnostics.cpp:782

RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)

Definition RetainCountDiagnostics.cpp:287

PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, PathSensitiveBugReport &BR) override

Provide custom definition for the final diagnostic piece on the path - the piece, which is displayed ...

Definition RetainCountDiagnostics.cpp:708

RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n, SymbolRef sym, CheckerContext &Ctx)

Definition RetainCountDiagnostics.cpp:931

unsigned getCount() const

unsigned getCombinedCounts() const

IvarAccessHistory getIvarAccessHistory() const

Returns what the analyzer knows about direct accesses to a particular instance variable.

unsigned getAutoreleaseCount() const

bool hasSameState(const RefVal &X) const

ObjKind getObjKind() const

static const SimpleProgramPointTag & getCastFailTag()

static const SimpleProgramPointTag & getDeallocSentTag()

void trackStoredValue(SVal V, const MemRegion *R, PathSensitiveBugReport &Report, TrackingOptions Opts={}, const StackFrameContext *Origin=nullptr)

Track how the value got stored into the given region and where it came from.

const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)

bool isSynthesizedAccessor(const StackFrameContext *SFC)

Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...

IntrusiveRefCntPtr< const ProgramState > ProgramStateRef

const SymExpr * SymbolRef

ObjKind

Determines the object kind of a tracked object.

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

@ CF

Indicates that the tracked object is a CF object.

@ ObjC

Indicates that the tracked object is an Objective-C object.

std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef

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.

bool isa(CodeGen::Address addr)

@ Result

The result type of a method or function.

const FunctionProtoType * T

U cast(CodeGen::Address addr)