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