47#include "llvm/Support/raw_ostream.h"
81 if (!
T->isObjCRetainableType())
93class ObjCDeallocChecker
94 :
public Checker<check::ASTDecl<ObjCImplementationDecl>,
95 check::PreObjCMessage, check::PostObjCMessage,
97 check::BeginFunction, check::EndFunction,
100 check::PreStmt<ReturnStmt>> {
102 mutable const IdentifierInfo *NSObjectII =
nullptr;
103 mutable const IdentifierInfo *SenTestCaseII =
nullptr;
104 mutable const IdentifierInfo *XCTestCaseII =
nullptr;
105 mutable const IdentifierInfo *Block_releaseII =
nullptr;
106 mutable const IdentifierInfo *CIFilterII =
nullptr;
108 mutable Selector DeallocSel;
109 mutable Selector ReleaseSel;
111 const BugType MissingReleaseBugType{
this,
"Missing ivar release (leak)",
113 const BugType ExtraReleaseBugType{
this,
"Extra ivar release",
115 const BugType MistakenDeallocBugType{
this,
"Mistaken dealloc",
119 void checkASTDecl(
const ObjCImplementationDecl *D, AnalysisManager& Mgr,
120 BugReporter &BR)
const;
121 void checkBeginFunction(CheckerContext &Ctx)
const;
122 void checkPreObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
123 void checkPreCall(
const CallEvent &
Call, CheckerContext &
C)
const;
124 void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
127 bool Assumption)
const;
131 const CallEvent *
Call,
133 void checkPreStmt(
const ReturnStmt *RS, CheckerContext &
C)
const;
134 void checkEndFunction(
const ReturnStmt *RS, CheckerContext &Ctx)
const;
137 void diagnoseMissingReleases(CheckerContext &
C)
const;
139 bool diagnoseExtraRelease(
SymbolRef ReleasedValue,
const ObjCMethodCall &M,
140 CheckerContext &
C)
const;
142 bool diagnoseMistakenDealloc(
SymbolRef DeallocedValue,
143 const ObjCMethodCall &M,
144 CheckerContext &
C)
const;
146 SymbolRef getValueReleasedByNillingOut(
const ObjCMethodCall &M,
147 CheckerContext &
C)
const;
149 const ObjCIvarRegion *getIvarRegionForIvarSymbol(
SymbolRef IvarSym)
const;
152 const ObjCPropertyImplDecl*
153 findPropertyOnDeallocatingInstance(
SymbolRef IvarSym,
154 CheckerContext &
C)
const;
157 getDeallocReleaseRequirement(
const ObjCPropertyImplDecl *PropImpl)
const;
159 bool isInInstanceDealloc(
const CheckerContext &
C, SVal &SelfValOut)
const;
160 bool isInInstanceDealloc(
const CheckerContext &
C,
const LocationContext *LCtx,
161 SVal &SelfValOut)
const;
162 bool instanceDeallocIsOnStack(
const CheckerContext &
C,
163 SVal &InstanceValOut)
const;
165 bool isSuperDeallocMessage(
const ObjCMethodCall &M)
const;
167 const ObjCImplDecl *getContainingObjCImpl(
const LocationContext *LCtx)
const;
169 const ObjCPropertyDecl *
170 findShadowedPropertyDecl(
const ObjCPropertyImplDecl *PropImpl)
const;
172 void transitionToReleaseValue(CheckerContext &
C,
SymbolRef Value)
const;
177 void initIdentifierInfoAndSelectors(ASTContext &Ctx)
const;
179 bool classHasSeparateTeardown(
const ObjCInterfaceDecl *ID)
const;
181 bool isReleasedByCIFilterDealloc(
const ObjCPropertyImplDecl *PropImpl)
const;
182 bool isNibLoadedIvarWithoutRetain(
const ObjCPropertyImplDecl *PropImpl)
const;
198 assert(Mgr.
getLangOpts().getGC() != LangOptions::GCOnly);
205 if (classHasSeparateTeardown(ID))
210 const ObjCPropertyImplDecl *PropImplRequiringRelease =
nullptr;
211 bool HasOthers =
false;
214 if (!PropImplRequiringRelease)
215 PropImplRequiringRelease = I;
223 if (!PropImplRequiringRelease)
226 const ObjCMethodDecl *MD =
nullptr;
230 if (I->getSelector() == DeallocSel) {
237 const char* Name =
"Missing -dealloc";
240 llvm::raw_string_ostream
OS(Buf);
241 OS <<
"'" << *D <<
"' lacks a 'dealloc' instance method but "
247 PathDiagnosticLocation DLoc =
259void ObjCDeallocChecker::checkBeginFunction(
260 CheckerContext &
C)
const {
261 initIdentifierInfoAndSelectors(
C.getASTContext());
265 if (!isInInstanceDealloc(
C, SelfVal))
270 const LocationContext *LCtx =
C.getLocationContext();
275 SymbolSet::Factory &F = State->getStateManager().get_context<
SymbolSet>();
278 SymbolSet RequiredReleases = F.getEmptySet();
282 if (
const SymbolSet *CurrSet = State->get<UnreleasedIvarMap>(SelfSymbol))
283 RequiredReleases = *CurrSet;
285 for (
auto *PropImpl : getContainingObjCImpl(LCtx)->property_impls()) {
290 SVal LVal = State->getLValue(PropImpl->getPropertyIvarDecl(), SelfVal);
291 std::optional<Loc> LValLoc = LVal.
getAs<Loc>();
295 SVal InitialVal = State->getSVal(*LValLoc);
301 RequiredReleases = F.add(RequiredReleases, Symbol);
304 if (!RequiredReleases.isEmpty()) {
305 State = State->set<UnreleasedIvarMap>(SelfSymbol, RequiredReleases);
308 if (State != InitialState) {
309 C.addTransition(State);
315const ObjCIvarRegion *
316ObjCDeallocChecker::getIvarRegionForIvarSymbol(
SymbolRef IvarSym)
const {
323ObjCDeallocChecker::getInstanceSymbolFromIvarSymbol(
SymbolRef IvarSym)
const {
325 const ObjCIvarRegion *IvarRegion = getIvarRegionForIvarSymbol(IvarSym);
330 assert(SR &&
"Symbolic base should not be nullptr");
336void ObjCDeallocChecker::checkPreObjCMessage(
337 const ObjCMethodCall &M, CheckerContext &
C)
const {
339 SVal DeallocedInstance;
340 if (!instanceDeallocIsOnStack(
C, DeallocedInstance))
355 if (diagnoseExtraRelease(ReleasedValue,M,
C))
360 ReleasedValue = getValueReleasedByNillingOut(M,
C);
366 transitionToReleaseValue(
C, ReleasedValue);
371void ObjCDeallocChecker::checkPreCall(
const CallEvent &
Call,
372 CheckerContext &
C)
const {
373 const IdentifierInfo *II =
Call.getCalleeIdentifier();
374 if (II != Block_releaseII)
377 if (
Call.getNumArgs() != 1)
384 transitionToReleaseValue(
C, ReleasedValue);
388void ObjCDeallocChecker::checkPostObjCMessage(
389 const ObjCMethodCall &M, CheckerContext &
C)
const {
393 if (isSuperDeallocMessage(M))
394 diagnoseMissingReleases(
C);
399void ObjCDeallocChecker::checkEndFunction(
400 const ReturnStmt *RS, CheckerContext &
C)
const {
401 diagnoseMissingReleases(
C);
405void ObjCDeallocChecker::checkPreStmt(
406 const ReturnStmt *RS, CheckerContext &
C)
const {
407 diagnoseMissingReleases(
C);
413 bool Assumption)
const {
414 if (State->get<UnreleasedIvarMap>().isEmpty())
417 auto *CondBSE = dyn_cast_or_null<BinarySymExpr>(
Cond.getAsSymbol());
431 if (
auto *SIE = dyn_cast<SymIntExpr>(CondBSE)) {
432 const llvm::APInt &RHS = SIE->getRHS();
435 NullSymbol = SIE->getLHS();
436 }
else if (
auto *SIE = dyn_cast<IntSymExpr>(CondBSE)) {
437 const llvm::APInt &LHS = SIE->getLHS();
440 NullSymbol = SIE->getRHS();
445 SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(NullSymbol);
449 State = removeValueRequiringRelease(State, InstanceSymbol, NullSymbol);
459 if (State->get<UnreleasedIvarMap>().isEmpty())
466 auto *OMC = dyn_cast_or_null<ObjCMethodCall>(
Call);
467 if (OMC && isSuperDeallocMessage(*OMC))
470 for (
const auto &Sym : Escaped) {
479 State = State->remove<UnreleasedIvarMap>(Sym);
483 SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(Sym);
487 State = removeValueRequiringRelease(State, InstanceSymbol, Sym);
495void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &
C)
const {
499 if (!isInInstanceDealloc(
C, SelfVal))
502 const MemRegion *SelfRegion = SelfVal.
castAs<loc::MemRegionVal>().
getRegion();
503 const LocationContext *LCtx =
C.getLocationContext();
505 ExplodedNode *ErrNode =
nullptr;
511 const SymbolSet *OldUnreleased = State->get<UnreleasedIvarMap>(SelfSym);
515 SymbolSet NewUnreleased = *OldUnreleased;
516 SymbolSet::Factory &F = State->getStateManager().get_context<
SymbolSet>();
520 for (
auto *IvarSymbol : *OldUnreleased) {
521 const TypedValueRegion *TVR =
529 const ObjCIvarDecl *IvarDecl = IvarRegion->
getDecl();
538 NewUnreleased = F.remove(NewUnreleased, IvarSymbol);
540 if (State->getStateManager()
541 .getConstraintManager()
542 .isNull(State, IvarSymbol)
543 .isConstrainedTrue()) {
549 ErrNode =
C.generateNonFatalErrorNode();
556 llvm::raw_string_ostream
OS(Buf);
568 const ObjCPropertyImplDecl *PropImpl =
576 OS <<
"The '" << *IvarDecl <<
"' ivar in '" << *ImplDecl
584 OS <<
" by a synthesized property but not released"
585 " before '[super dealloc]'";
587 auto BR = std::make_unique<PathSensitiveBugReport>(MissingReleaseBugType,
589 C.emitReport(std::move(BR));
592 if (NewUnreleased.isEmpty()) {
593 State = State->remove<UnreleasedIvarMap>(SelfSym);
595 State = State->set<UnreleasedIvarMap>(SelfSym, NewUnreleased);
599 C.addTransition(State, ErrNode);
600 }
else if (State != InitialState) {
601 C.addTransition(State);
607 assert(!LCtx->
inTopFrame() || State->get<UnreleasedIvarMap>().isEmpty());
613const ObjCPropertyImplDecl *
614ObjCDeallocChecker::findPropertyOnDeallocatingInstance(
616 SVal DeallocedInstance;
617 if (!isInInstanceDealloc(
C, DeallocedInstance))
621 auto *IvarRegion = getIvarRegionForIvarSymbol(IvarSym);
627 if (DeallocedInstance.
castAs<loc::MemRegionVal>().getRegion() !=
631 const LocationContext *LCtx =
C.getLocationContext();
632 const ObjCIvarDecl *IvarDecl = IvarRegion->
getDecl();
634 const ObjCImplDecl *Container = getContainingObjCImpl(LCtx);
635 const ObjCPropertyImplDecl *PropImpl =
643bool ObjCDeallocChecker::diagnoseExtraRelease(
SymbolRef ReleasedValue,
644 const ObjCMethodCall &M,
645 CheckerContext &
C)
const {
651 const ObjCPropertyImplDecl *PropImpl =
652 findPropertyOnDeallocatingInstance(ReleasedValue,
C);
659 if (getDeallocReleaseRequirement(PropImpl) !=
670 const ObjCPropertyDecl *PropDecl = findShadowedPropertyDecl(PropImpl);
678 ExplodedNode *ErrNode =
C.generateNonFatalErrorNode();
683 llvm::raw_string_ostream
OS(Buf);
688 isReleasedByCIFilterDealloc(PropImpl)
691 const ObjCImplDecl *Container = getContainingObjCImpl(
C.getLocationContext());
693 <<
"' ivar in '" << *Container;
696 if (isReleasedByCIFilterDealloc(PropImpl)) {
697 OS <<
"' will be released by '-[CIFilter dealloc]' but also released here";
699 OS <<
"' was synthesized for ";
704 OS <<
"an assign, readwrite";
706 OS <<
" property but was released in 'dealloc'";
709 auto BR = std::make_unique<PathSensitiveBugReport>(ExtraReleaseBugType, Buf,
721bool ObjCDeallocChecker::diagnoseMistakenDealloc(
SymbolRef DeallocedValue,
722 const ObjCMethodCall &M,
723 CheckerContext &
C)
const {
731 const ObjCPropertyImplDecl *PropImpl =
732 findPropertyOnDeallocatingInstance(DeallocedValue,
C);
736 if (getDeallocReleaseRequirement(PropImpl) !=
741 ExplodedNode *ErrNode =
C.generateErrorNode();
746 llvm::raw_string_ostream
OS(Buf);
749 <<
"' should be released rather than deallocated";
751 auto BR = std::make_unique<PathSensitiveBugReport>(MistakenDeallocBugType,
760void ObjCDeallocChecker::initIdentifierInfoAndSelectors(
761 ASTContext &Ctx)
const {
765 NSObjectII = &Ctx.
Idents.
get(
"NSObject");
766 SenTestCaseII = &Ctx.
Idents.
get(
"SenTestCase");
767 XCTestCaseII = &Ctx.
Idents.
get(
"XCTestCase");
768 Block_releaseII = &Ctx.
Idents.
get(
"_Block_release");
769 CIFilterII = &Ctx.
Idents.
get(
"CIFilter");
771 const IdentifierInfo *DeallocII = &Ctx.
Idents.
get(
"dealloc");
772 const IdentifierInfo *ReleaseII = &Ctx.
Idents.
get(
"release");
778bool ObjCDeallocChecker::isSuperDeallocMessage(
779 const ObjCMethodCall &M)
const {
788ObjCDeallocChecker::getContainingObjCImpl(
const LocationContext *LCtx)
const {
795const ObjCPropertyDecl *ObjCDeallocChecker::findShadowedPropertyDecl(
796 const ObjCPropertyImplDecl *PropImpl)
const {
803 auto *CatDecl = dyn_cast<ObjCCategoryDecl>(PropDecl->
getDeclContext());
806 if (!CatDecl || !CatDecl->IsClassExtension())
811 for (
const NamedDecl *D : R) {
812 auto *ShadowedPropDecl = dyn_cast<ObjCPropertyDecl>(D);
813 if (!ShadowedPropDecl)
816 if (ShadowedPropDecl->isInstanceProperty()) {
817 assert(ShadowedPropDecl->isReadOnly());
818 return ShadowedPropDecl;
826void ObjCDeallocChecker::transitionToReleaseValue(CheckerContext &
C,
835 removeValueRequiringRelease(InitialState, InstanceSym,
Value);
837 if (ReleasedState != InitialState) {
838 C.addTransition(ReleasedState);
848 const ObjCIvarRegion *RemovedRegion = getIvarRegionForIvarSymbol(
Value);
852 const SymbolSet *Unreleased = State->get<UnreleasedIvarMap>(Instance);
857 SymbolSet::Factory &F = State->getStateManager().get_context<
SymbolSet>();
859 for (
auto &Sym : *Unreleased) {
860 const ObjCIvarRegion *UnreleasedRegion = getIvarRegionForIvarSymbol(Sym);
861 assert(UnreleasedRegion);
863 NewUnreleased = F.remove(NewUnreleased, Sym);
867 if (NewUnreleased.isEmpty()) {
868 return State->remove<UnreleasedIvarMap>(Instance);
871 return State->set<UnreleasedIvarMap>(Instance, NewUnreleased);
877 const ObjCPropertyImplDecl *PropImpl)
const {
878 const ObjCIvarDecl *IvarDecl;
879 const ObjCPropertyDecl *PropDecl;
890 if (isReleasedByCIFilterDealloc(PropImpl))
893 if (isNibLoadedIvarWithoutRetain(PropImpl))
910 llvm_unreachable(
"Unrecognized setter kind");
916ObjCDeallocChecker::getValueReleasedByNillingOut(
const ObjCMethodCall &M,
917 CheckerContext &
C)
const {
931 std::tie(notNilState, nilState) =
933 if (!(nilState && !notNilState))
946 SVal LVal = State->getLValue(PropIvarDecl, ReceiverVal);
947 std::optional<Loc> LValLoc = LVal.
getAs<Loc>();
951 SVal CurrentValInIvar = State->getSVal(*LValLoc);
958bool ObjCDeallocChecker::isInInstanceDealloc(
const CheckerContext &
C,
959 SVal &SelfValOut)
const {
960 return isInInstanceDealloc(
C,
C.getLocationContext(), SelfValOut);
966bool ObjCDeallocChecker::isInInstanceDealloc(
const CheckerContext &
C,
967 const LocationContext *LCtx,
968 SVal &SelfValOut)
const {
969 auto *MD = dyn_cast<ObjCMethodDecl>(LCtx->
getDecl());
973 const ImplicitParamDecl *SelfDecl = LCtx->
getSelfDecl();
974 assert(SelfDecl &&
"No self in -dealloc?");
977 SelfValOut = State->getSVal(State->getRegion(SelfDecl, LCtx));
984bool ObjCDeallocChecker::instanceDeallocIsOnStack(
const CheckerContext &
C,
985 SVal &InstanceValOut)
const {
986 const LocationContext *LCtx =
C.getLocationContext();
989 if (isInInstanceDealloc(
C, LCtx, InstanceValOut))
1001bool ObjCDeallocChecker::classHasSeparateTeardown(
1002 const ObjCInterfaceDecl *ID)
const {
1004 for ( ;
ID ;
ID =
ID->getSuperClass()) {
1005 IdentifierInfo *II =
ID->getIdentifier();
1007 if (II == NSObjectII)
1014 if (II == XCTestCaseII || II == SenTestCaseII)
1029bool ObjCDeallocChecker::isReleasedByCIFilterDealloc(
1030 const ObjCPropertyImplDecl *PropImpl)
const {
1035 const char *ReleasePrefix =
"input";
1036 if (!(PropName.starts_with(ReleasePrefix) ||
1037 IvarName.starts_with(ReleasePrefix))) {
1041 const ObjCInterfaceDecl *
ID =
1043 for ( ;
ID ;
ID =
ID->getSuperClass()) {
1044 IdentifierInfo *II =
ID->getIdentifier();
1045 if (II == CIFilterII)
1060bool ObjCDeallocChecker::isNibLoadedIvarWithoutRetain(
1061 const ObjCPropertyImplDecl *PropImpl)
const {
1063 if (!IvarDecl->
hasAttr<IBOutletAttr>())
1066 const llvm::Triple &
Target =
1078void ento::registerObjCDeallocChecker(CheckerManager &Mgr) {
1082bool ento::shouldRegisterObjCDeallocChecker(
const CheckerManager &mgr) {
1085 return LO.getGC() != LangOptions::GCOnly && !LO.ObjCAutoRefCount;
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
ReleaseRequirement
Indicates whether an instance variable is required to be released in -dealloc.
@ MustNotReleaseDirectly
The instance variable must not be directly released with -release.
@ Unknown
The requirement for the instance variable could not be determined.
@ MustRelease
The instance variable must be released, either by calling -release on it directly or by nilling it ou...
static bool isSynthesizedRetainableProperty(const ObjCPropertyImplDecl *I, const ObjCIvarDecl **ID, const ObjCPropertyDecl **PD)
Returns true if the property implementation is synthesized and the type of the property is retainable...
Defines the clang::LangOptions interface.
llvm::MachO::SymbolSet SymbolSet
llvm::MachO::Target Target
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set type Name and registers the factory for such sets in the program state,...
SelectorTable & Selectors
const TargetInfo & getTargetInfo() const
BinaryOperatorKind Opcode
DeclContextLookupResult lookup_result
ASTContext & getASTContext() const LLVM_READONLY
DeclContext * getDeclContext()
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const Decl * getDecl() const
const LocationContext * getParent() const
It might return null.
virtual bool inTopFrame() const
const ImplicitParamDecl * getSelfDecl() const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
instmeth_range instance_methods() const
propimpl_range property_impls() const
const ObjCInterfaceDecl * getClassInterface() const
ObjCPropertyImplDecl * FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const
FindPropertyImplIvarDecl - This method lookup the ivar in the list of properties implemented in this ...
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
ObjCImplementationDecl * getImplementation() const
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
@ SuperInstance
The receiver is the instance of the superclass object.
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Selector getSelector() const
bool isInstanceMethod() const
Represents one property declaration in an Objective-C interface.
ObjCMethodDecl * getSetterMethodDecl() const
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
ObjCIvarDecl * getPropertyIvarDecl() const
SetterKind getSetterKind() const
getSetterKind - Return the method used for doing assignment in the property setter.
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
ObjCIvarDecl * getPropertyIvarDecl() const
Kind getPropertyImplementation() const
ObjCPropertyDecl * getPropertyDecl() const
A (possibly-)qualified type.
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isObjCRetainableType() const
const LangOptions & getLangOpts() const
ASTContext & getASTContext() override
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerFrontend *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
const ProgramStateRef & getState() const
The state in which the call is being evaluated.
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
const LangOptions & getLangOpts() const
Simple checker classes that implement one frontend (i.e.
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const ObjCIvarDecl * getDecl() const override
const Expr * getArgExpr(unsigned Index) const override
Returns the expression associated with a given argument.
unsigned getNumArgs() const override
Returns the number of arguments (explicit and implicit).
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Selector getSelector() const
const ObjCPropertyDecl * getAccessedProperty() const
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
virtual const MemRegion * getOriginRegion() const
Find the region from which this symbol originates.
SymbolRef getSymbol() const
It might return null.
Defines the clang::TargetInfo interface.
const char *const CoreFoundationObjectiveC
const char *const MemoryRefCount
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
U cast(CodeGen::Address addr)
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.