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)