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;

22using namespace retaincountchecker;

23

25 switch (BT) {

27 return "Use-after-release";

29 return "Bad release";

31 return "-dealloc sent to non-exclusively owned object";

33 return "freeing non-exclusively owned object";

35 return "Object autoreleased too many times";

37 return "Method should return an owned object";

39 return "Leak";

41 return "Leak of returned object";

42 }

43 llvm_unreachable("Unknown RefCountBugKind");

44}

45

47 switch (BT) {

49 return "Reference-counted object is used after it is released";

51 return "Incorrect decrement of the reference count of an object that is "

52 "not owned at this point by the caller";

54 return "-dealloc sent to object that may be referenced elsewhere";

56 return "'free' called on an object that may be referenced elsewhere";

58 return "Object autoreleased too many times";

60 return "Object with a +0 retain count returned to caller where a +1 "

61 "(owning) retain count is expected";

64 return "";

65 }

66 llvm_unreachable("Unknown RefCountBugKind");

67}

68

70 : BugType(Checker, bugTypeToName(BT), categories::MemoryRefCount,

71 BT == LeakWithinFunction ||

72 BT == LeakAtReturn),

73 BT(BT) {}

74

76

79}

80

81

82

83

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

90}

91

92

93

97 bool DeallocSent) {

98

99 RefVal PrevV = *PrevT;

100

101

102 if (DeallocSent) {

103

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

105

106

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

110 return true;

111 }

112 }

113

114

116 switch (CurrV.getKind()) {

120

122 return false;

123

125 os << "Object autoreleased";

126 return true;

127 }

128

130 os << "Reference count decremented.";

131 else

132 os << "Reference count incremented.";

133

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

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

136

137 return true;

138

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

144 }

145 os << "Object released.";

146 return true;

147

149

151 return false;

152

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

154 "retain count transferred to caller)";

155 return true;

156

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

159 return true;

160

161 default:

162 return false;

163 }

164 return true;

165}

166

167

168

169

170static std::optional

173 if (!CE)

174 return std::nullopt;

175

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

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

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

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

180 return Idx;

181

182 return std::nullopt;

183}

184

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

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

188 return std::nullopt;

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

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

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

193 return std::nullopt;

194

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

197

198 }

199 }

200 return std::nullopt;

201}

202

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

206 return *Out;

208}

209

213 const Stmt *S,

214 llvm::raw_string_ostream &os) {

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

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

217

218

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

221

222

223 if (!FD)

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

225

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

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

228 } else if (FD) {

230 } else {

231 os << "function call";

232 }

233 } else if (isa(S)) {

234 os << "Operator 'new'";

235 } else {

236 assert(isa(S));

238 cast(S), CurrSt, LCtx, {nullptr, 0});

239

240 switch (Call->getMessageKind()) {

242 os << "Method";

243 break;

245 os << "Property";

246 break;

248 os << "Subscript";

249 break;

250 }

251 }

252

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

255

256

257 if (!Idx) {

258 os << " returns ";

259 } else {

260 os << " writes ";

261 }

262

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

267 << "' with a ";

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

270 } else {

273 if (!isa(T)) {

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

275 } else {

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

278 }

279 }

280

282 os << "+1 retain count";

283 } else {

285 os << "+0 retain count";

286 }

287

288 if (Idx) {

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

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

292 false);

293 os << "'";

294

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

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

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

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

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

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

302 }

303

304 }

305 }

306}

307

309namespace ento {

310namespace retaincountchecker {

311

313protected:

315

316public:

318

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

320 static int x = 0;

321 ID.AddPointer(&x);

322 ID.AddPointer(Sym);

323 }

324

328

332};

333

335public:

338

342

343private:

345};

346

347}

348}

349}

350

351

352

356 return nullptr;

358 if (!PC)

359 return nullptr;

360

364 }

365 return N;

366}

367

368

369

370

371

372static std::shared_ptr

377

379 if (!CN)

380 return nullptr;

381

383

384 std::string sbuf;

385 llvm::raw_string_ostream os(sbuf);

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

389

390 if (!PVD->hasAttr())

391 continue;

392

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

396

397 if (!CountBeforeCall || !CountAtExit)

398 continue;

399

400 unsigned CountBefore = CountBeforeCall->getCount();

401 unsigned CountAfter = CountAtExit->getCount();

402

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

404 if (!AsExpected) {

405 os << "Parameter '";

407 false);

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

409 << "the reference\n";

410 }

411 }

412 }

413

414 if (sbuf.empty())

415 return nullptr;

416

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

419}

420

421

422static std::shared_ptr

426 if (!PP)

427 return nullptr;

428

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

431

434 return nullptr;

435

436 const auto *VR = cast(cast(Sym)->getRegion());

437 const auto *PVD = cast(VR->getDecl());

439

440 std::string s;

441 llvm::raw_string_ostream os(s);

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

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

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

445 } else {

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

447 os << "0";

448 }

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

450}

451

455

457

460

465 return PD;

466

468 return PD;

469

470

471

473 return nullptr;

474

475

480

482 if (!CurrT)

483 return nullptr;

484

485 const RefVal &CurrV = *CurrT;

487

488

489

490 std::string sbuf;

491 llvm::raw_string_ostream os(sbuf);

492

493 if (PrevT && IsFreeUnowned && CurrV.isNotOwned() && PrevT->isOwned()) {

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

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

497 }

498

499

500

501 if (!PrevT) {

503

504 if (isa(S) &&

507 }

508

509 if (isa(S)) {

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

511 } else if (isa(S)) {

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

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

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

516 else {

518 if (const ObjCMethodDecl *Method = BL->getBoxingMethod())

519 BoxClass = Method->getClassInterface();

520

521

522

523 if (BoxClass) {

524 os << *BoxClass << " b";

525 } else {

526 os << "B";

527 }

528

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

530 }

531 } else if (isa(S)) {

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

533 } else {

535 }

536

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

539 }

540

541

542

543 bool DeallocSent = false;

544

546

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

549 }

550

552

553

555

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

557

558

559 unsigned i = 0;

560

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

562

563

564

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

566 continue;

567

568

569 DeallocSent = true;

570 }

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

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

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

574 .getAsLocSymbol() == Sym) {

575

576 DeallocSent = true;

577 }

578 }

579 }

580 }

581

583 return nullptr;

584

585 if (sbuf.empty())

586 return nullptr;

587

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

592

593

594

595 for (const Stmt *Child : S->children())

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

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

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

599 break;

600 }

601

602 return std::move(P);

603}

604

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

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

608

609

610 return std::nullopt;

611}

612

614

615namespace {

619

620public:

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

623

625 SVal Val) override {

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

628 return true;

629

630 if (isa(R))

631 Result.emplace_back(R, Val);

632

633 return true;

634 }

635};

636}

637

642 VarBindingsCollector Collector{Sym, Result};

646 }

647

649}

650

651namespace {

652

653

654

655

656

657struct AllocationInfo {

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

665};

666}

667

671 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;

672 const MemRegion *FirstBinding = nullptr;

674

675

676

678

679 while (N) {

682

684 break;

685

688

689 if (FB) {

691

692

693 if (auto MR = dyn_cast(R->getMemorySpace()))

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

695 FirstBinding = R;

696 }

697

698

699 AllocationNode = N;

700

701

702

703

704

705

706

707

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

709 AllocationNodeInCurrentOrParentContext = N;

710

711

712

713 if (!InitMethodContext)

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

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

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

718 if (RecExpr) {

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

721 InitMethodContext = CEP->getCalleeContext();

722 }

723 }

724 }

725

727 }

728

729

730

731 const LocationContext *InterestingMethodContext = nullptr;

732 if (InitMethodContext) {

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

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

737 InterestingMethodContext = InitMethodContext;

738 }

739

740

741

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

743

744 if (AllocationNodeInCurrentOrParentContext &&

746 LeakContext)

747 FirstBinding = nullptr;

748

749 return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,

750 InterestingMethodContext);

751}

752

759}

760

765

766

767

769

771

772 std::string sbuf;

773 llvm::raw_string_ostream os(sbuf);

774

775 os << "Object leaked: ";

776

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

778 if (RegionDescription) {

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

780 } else {

782 << "'";

783 }

784

785

787 assert(RV);

788

791

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

793 : " is returned from a function ");

794

795 if (D->hasAttr()) {

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

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

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

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

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

801 } else {

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

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

805 } else {

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

807 << "') does not start with "

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

809 " This violates the naming convention rules"

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

811 }

812 } else {

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

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

818 "naming"

819 " convention rules given in the Memory Management Guide for "

820 "Core"

821 " Foundation";

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

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

826 }

827 }

828 }

829 } else {

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

831 "count of +"

833 }

834

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

836}

837

841 isLeak(isLeak) {

843 addVisitor(sym);

844}

845

848 StringRef endText)

850

851 addVisitor(sym);

852}

853

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

856

858 return;

859

861 if (Region) {

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

863 if (isa_and_nonnull(PDecl)) {

866 Location = ParamLocation;

868 UniqueingDecl = Ctx.getLocationContext()->getDecl();

869 }

870 }

871}

872

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

874

875

876

877

878

879

880

881

883

885

886 AllocationInfo AllocI =

888

889 AllocNode = AllocI.N;

890 AllocFirstBinding = AllocI.R;

892

893

894

895

896

898

899 if (!AllocStmt) {

900 AllocFirstBinding = nullptr;

901 return;

902 }

903

906 Location = AllocLocation;

907

908

909

912}

913

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

917 llvm::raw_string_ostream os(Description);

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

919

920 std::optionalstd::string RegionDescription =

922 if (RegionDescription) {

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

924 } else {

925

926

928 }

929}

930

931void RefLeakReport::findBindingToReport(CheckerContext &Ctx,

933 if (!AllocFirstBinding)

934

935

936 return;

937

938

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

940

941 AllocBindingToReport = AllocFirstBinding;

942 return;

943 }

944

945

946

947

948

949

950

951

952

953

954

955

956

957

960

961

962

963

964 if (!AllVarBindings.empty() &&

965 llvm::count_if(AllVarBindings,

966 [this](const std::pair<const MemRegion *, SVal> Binding) {

967 return Binding.first == AllocFirstBinding;

968 }) == 0) {

969

970 AllocBindingToReport = AllVarBindings[0].first;

971

972

973

974

975

976

977

978

979

980

982 AllocBindingToReport, *this);

983 } else {

984 AllocBindingToReport = AllocFirstBinding;

985 }

986}

987

992

993 deriveAllocLocation(Ctx);

994 findBindingToReport(Ctx, N);

995

996 if (!AllocFirstBinding)

997 deriveParamLocation(Ctx);

998

999 createDescription(Ctx);

1000

1001 addVisitor(Sym, AllocBindingToReport);

1002}

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.

static std::string getPrettyTypeName(QualType QT)

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

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.

static bool isNumericLiteralExpression(const Expr *E)

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.

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",...

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

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

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

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

static const ExplodedNode * getCalleeNode(const ExplodedNode *Pred)

Find the first node with the parent stack frame.

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

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

__device__ __2f16 float __ockl_bool s

SourceManager & getSourceManager()

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 ...

const BugType & getBugType() const

ASTContext & getASTContext() const

ProgramStateManager & getStateManager() const

const SourceManager & getSourceManager() const

BugReporterVisitors are used to add custom diagnostics along a path.

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.

This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...

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.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() 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

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

RefCountBug(CheckerNameRef Checker, RefCountBugKind BT)

StringRef getDescription() const

RefCountBugKind getBugType() const

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

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

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

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 ...

RefCountReportVisitor(SymbolRef sym)

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

RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)

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 ...

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

unsigned getCount() const

unsigned getCombinedCounts() const

@ ReleasedAfterDirectAccess

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 CheckerProgramPointTag & getCastFailTag()

static const CheckerProgramPointTag & 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...

ObjKind

Determines the object kind of a tracked object.

@ OS

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

@ Generalized

Indicates that the tracked object is a generalized object.

@ CF

Indicates that the tracked object is a CF object.

@ ObjC

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

const void * Store

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

std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef

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