47#include "llvm/ADT/STLExtras.h"
48#include "llvm/Support/raw_ostream.h"
82 if (!
T->isObjCRetainableType())
94class ObjCDeallocChecker
95 :
public Checker<check::ASTDecl<ObjCImplementationDecl>,
96 check::PreObjCMessage, check::PostObjCMessage,
98 check::BeginFunction, check::EndFunction,
100 check::PointerEscape,
101 check::PreStmt<ReturnStmt>> {
103 mutable const IdentifierInfo *NSObjectII =
nullptr;
104 mutable const IdentifierInfo *SenTestCaseII =
nullptr;
105 mutable const IdentifierInfo *XCTestCaseII =
nullptr;
106 mutable const IdentifierInfo *Block_releaseII =
nullptr;
107 mutable const IdentifierInfo *CIFilterII =
nullptr;
109 mutable Selector DeallocSel;
110 mutable Selector ReleaseSel;
112 const BugType MissingReleaseBugType{
this,
"Missing ivar release (leak)",
114 const BugType ExtraReleaseBugType{
this,
"Extra ivar release",
116 const BugType MistakenDeallocBugType{
this,
"Mistaken dealloc",
120 void checkASTDecl(
const ObjCImplementationDecl *D, AnalysisManager& Mgr,
121 BugReporter &BR)
const;
122 void checkBeginFunction(CheckerContext &Ctx)
const;
123 void checkPreObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
124 void checkPreCall(
const CallEvent &
Call, CheckerContext &
C)
const;
125 void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
128 bool Assumption)
const;
132 const CallEvent *
Call,
134 void checkPreStmt(
const ReturnStmt *RS, CheckerContext &
C)
const;
135 void checkEndFunction(
const ReturnStmt *RS, CheckerContext &Ctx)
const;
138 void diagnoseMissingReleases(CheckerContext &
C)
const;
140 bool diagnoseExtraRelease(
SymbolRef ReleasedValue,
const ObjCMethodCall &M,
141 CheckerContext &
C)
const;
143 bool diagnoseMistakenDealloc(
SymbolRef DeallocedValue,
144 const ObjCMethodCall &M,
145 CheckerContext &
C)
const;
147 SymbolRef getValueReleasedByNillingOut(
const ObjCMethodCall &M,
148 CheckerContext &
C)
const;
150 const ObjCIvarRegion *getIvarRegionForIvarSymbol(
SymbolRef IvarSym)
const;
153 const ObjCPropertyImplDecl*
154 findPropertyOnDeallocatingInstance(
SymbolRef IvarSym,
155 CheckerContext &
C)
const;
158 getDeallocReleaseRequirement(
const ObjCPropertyImplDecl *PropImpl)
const;
160 bool isInInstanceDealloc(
const CheckerContext &
C, SVal &SelfValOut)
const;
161 bool isInInstanceDealloc(
const CheckerContext &
C,
const StackFrame *SF,
162 SVal &SelfValOut)
const;
163 bool instanceDeallocIsOnStack(
const CheckerContext &
C,
164 SVal &InstanceValOut)
const;
166 bool isSuperDeallocMessage(
const ObjCMethodCall &M)
const;
168 const ObjCImplDecl *getContainingObjCImpl(
const StackFrame *SF)
const;
170 const ObjCPropertyDecl *
171 findShadowedPropertyDecl(
const ObjCPropertyImplDecl *PropImpl)
const;
173 void transitionToReleaseValue(CheckerContext &
C,
SymbolRef Value)
const;
178 void initIdentifierInfoAndSelectors(ASTContext &Ctx)
const;
180 bool classHasSeparateTeardown(
const ObjCInterfaceDecl *ID)
const;
182 bool isReleasedByCIFilterDealloc(
const ObjCPropertyImplDecl *PropImpl)
const;
183 bool isNibLoadedIvarWithoutRetain(
const ObjCPropertyImplDecl *PropImpl)
const;
199 assert(Mgr.
getLangOpts().getGC() != LangOptions::GCOnly);
206 if (classHasSeparateTeardown(ID))
211 const ObjCPropertyImplDecl *PropImplRequiringRelease =
nullptr;
212 bool HasOthers =
false;
215 if (!PropImplRequiringRelease)
216 PropImplRequiringRelease = I;
224 if (!PropImplRequiringRelease)
227 const ObjCMethodDecl *MD =
nullptr;
231 if (I->getSelector() == DeallocSel) {
238 const char* Name =
"Missing -dealloc";
241 llvm::raw_string_ostream
OS(Buf);
242 OS <<
"'" << *D <<
"' lacks a 'dealloc' instance method but "
248 PathDiagnosticLocation DLoc =
260void ObjCDeallocChecker::checkBeginFunction(
261 CheckerContext &
C)
const {
262 initIdentifierInfoAndSelectors(
C.getASTContext());
266 if (!isInInstanceDealloc(
C, SelfVal))
271 const StackFrame *SF =
C.getStackFrame();
276 SymbolSet::Factory &F = State->getStateManager().get_context<
SymbolSet>();
279 SymbolSet RequiredReleases = F.getEmptySet();
283 if (
const SymbolSet *CurrSet = State->get<UnreleasedIvarMap>(SelfSymbol))
284 RequiredReleases = *CurrSet;
286 for (
auto *PropImpl : getContainingObjCImpl(SF)->property_impls()) {
291 SVal LVal = State->getLValue(PropImpl->getPropertyIvarDecl(), SelfVal);
292 std::optional<Loc> LValLoc = LVal.
getAs<Loc>();
296 SVal InitialVal = State->getSVal(*LValLoc);
302 RequiredReleases = F.add(RequiredReleases, Symbol);
305 if (!RequiredReleases.isEmpty()) {
306 State = State->set<UnreleasedIvarMap>(SelfSymbol, RequiredReleases);
309 if (State != InitialState) {
310 C.addTransition(State);
316const ObjCIvarRegion *
317ObjCDeallocChecker::getIvarRegionForIvarSymbol(
SymbolRef IvarSym)
const {
324ObjCDeallocChecker::getInstanceSymbolFromIvarSymbol(
SymbolRef IvarSym)
const {
326 const ObjCIvarRegion *IvarRegion = getIvarRegionForIvarSymbol(IvarSym);
331 assert(SR &&
"Symbolic base should not be nullptr");
337void ObjCDeallocChecker::checkPreObjCMessage(
338 const ObjCMethodCall &M, CheckerContext &
C)
const {
340 SVal DeallocedInstance;
341 if (!instanceDeallocIsOnStack(
C, DeallocedInstance))
356 if (diagnoseExtraRelease(ReleasedValue,M,
C))
361 ReleasedValue = getValueReleasedByNillingOut(M,
C);
367 transitionToReleaseValue(
C, ReleasedValue);
372void ObjCDeallocChecker::checkPreCall(
const CallEvent &
Call,
373 CheckerContext &
C)
const {
374 const IdentifierInfo *II =
Call.getCalleeIdentifier();
375 if (II != Block_releaseII)
378 if (
Call.getNumArgs() != 1)
385 transitionToReleaseValue(
C, ReleasedValue);
389void ObjCDeallocChecker::checkPostObjCMessage(
390 const ObjCMethodCall &M, CheckerContext &
C)
const {
394 if (isSuperDeallocMessage(M))
395 diagnoseMissingReleases(
C);
400void ObjCDeallocChecker::checkEndFunction(
401 const ReturnStmt *RS, CheckerContext &
C)
const {
402 diagnoseMissingReleases(
C);
406void ObjCDeallocChecker::checkPreStmt(
407 const ReturnStmt *RS, CheckerContext &
C)
const {
408 diagnoseMissingReleases(
C);
414 bool Assumption)
const {
415 if (State->get<UnreleasedIvarMap>().isEmpty())
418 auto *CondBSE = dyn_cast_or_null<BinarySymExpr>(
Cond.getAsSymbol());
432 if (
auto *SIE = dyn_cast<SymIntExpr>(CondBSE)) {
433 const llvm::APInt &RHS = SIE->getRHS();
436 NullSymbol = SIE->getLHS();
437 }
else if (
auto *SIE = dyn_cast<IntSymExpr>(CondBSE)) {
438 const llvm::APInt &LHS = SIE->getLHS();
441 NullSymbol = SIE->getRHS();
446 SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(NullSymbol);
450 State = removeValueRequiringRelease(State, InstanceSymbol, NullSymbol);
460 if (State->get<UnreleasedIvarMap>().isEmpty())
467 auto *OMC = dyn_cast_or_null<ObjCMethodCall>(
Call);
468 if (OMC && isSuperDeallocMessage(*OMC))
471 for (
const auto &Sym : Escaped) {
480 State = State->remove<UnreleasedIvarMap>(Sym);
484 SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(Sym);
488 State = removeValueRequiringRelease(State, InstanceSymbol, Sym);
496void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &
C)
const {
500 if (!isInInstanceDealloc(
C, SelfVal))
503 const MemRegion *SelfRegion = SelfVal.
castAs<loc::MemRegionVal>().
getRegion();
504 const StackFrame *SF =
C.getStackFrame();
506 ExplodedNode *ErrNode =
nullptr;
512 const SymbolSet *OldUnreleased = State->get<UnreleasedIvarMap>(SelfSym);
516 SymbolSet NewUnreleased = *OldUnreleased;
517 SymbolSet::Factory &F = State->getStateManager().get_context<
SymbolSet>();
521 for (
auto *IvarSymbol : *OldUnreleased) {
522 const TypedValueRegion *TVR =
530 const ObjCIvarDecl *IvarDecl = IvarRegion->
getDecl();
539 NewUnreleased = F.remove(NewUnreleased, IvarSymbol);
541 if (State->getStateManager()
542 .getConstraintManager()
543 .isNull(State, IvarSymbol)
544 .isConstrainedTrue()) {
550 ErrNode =
C.generateNonFatalErrorNode();
557 llvm::raw_string_ostream
OS(Buf);
569 const ObjCPropertyImplDecl *PropImpl =
577 OS <<
"The '" << *IvarDecl <<
"' ivar in '" << *ImplDecl
585 OS <<
" by a synthesized property but not released"
586 " before '[super dealloc]'";
588 auto BR = std::make_unique<PathSensitiveBugReport>(MissingReleaseBugType,
590 C.emitReport(std::move(BR));
593 if (NewUnreleased.isEmpty()) {
594 State = State->remove<UnreleasedIvarMap>(SelfSym);
596 State = State->set<UnreleasedIvarMap>(SelfSym, NewUnreleased);
600 C.addTransition(State, ErrNode);
601 }
else if (State != InitialState) {
602 C.addTransition(State);
608 assert(!SF->
inTopFrame() || State->get<UnreleasedIvarMap>().isEmpty());
614const ObjCPropertyImplDecl *
615ObjCDeallocChecker::findPropertyOnDeallocatingInstance(
617 SVal DeallocedInstance;
618 if (!isInInstanceDealloc(
C, DeallocedInstance))
622 auto *IvarRegion = getIvarRegionForIvarSymbol(IvarSym);
628 if (DeallocedInstance.
castAs<loc::MemRegionVal>().getRegion() !=
632 const StackFrame *SF =
C.getStackFrame();
633 const ObjCIvarDecl *IvarDecl = IvarRegion->
getDecl();
635 const ObjCImplDecl *Container = getContainingObjCImpl(SF);
636 const ObjCPropertyImplDecl *PropImpl =
644bool ObjCDeallocChecker::diagnoseExtraRelease(
SymbolRef ReleasedValue,
645 const ObjCMethodCall &M,
646 CheckerContext &
C)
const {
652 const ObjCPropertyImplDecl *PropImpl =
653 findPropertyOnDeallocatingInstance(ReleasedValue,
C);
660 if (getDeallocReleaseRequirement(PropImpl) !=
671 const ObjCPropertyDecl *PropDecl = findShadowedPropertyDecl(PropImpl);
679 ExplodedNode *ErrNode =
C.generateNonFatalErrorNode();
684 llvm::raw_string_ostream
OS(Buf);
689 isReleasedByCIFilterDealloc(PropImpl)
692 const ObjCImplDecl *Container = getContainingObjCImpl(
C.getStackFrame());
694 <<
"' ivar in '" << *Container;
697 if (isReleasedByCIFilterDealloc(PropImpl)) {
698 OS <<
"' will be released by '-[CIFilter dealloc]' but also released here";
700 OS <<
"' was synthesized for ";
705 OS <<
"an assign, readwrite";
707 OS <<
" property but was released in 'dealloc'";
710 auto BR = std::make_unique<PathSensitiveBugReport>(ExtraReleaseBugType, Buf,
722bool ObjCDeallocChecker::diagnoseMistakenDealloc(
SymbolRef DeallocedValue,
723 const ObjCMethodCall &M,
724 CheckerContext &
C)
const {
732 const ObjCPropertyImplDecl *PropImpl =
733 findPropertyOnDeallocatingInstance(DeallocedValue,
C);
737 if (getDeallocReleaseRequirement(PropImpl) !=
742 ExplodedNode *ErrNode =
C.generateErrorNode();
747 llvm::raw_string_ostream
OS(Buf);
750 <<
"' should be released rather than deallocated";
752 auto BR = std::make_unique<PathSensitiveBugReport>(MistakenDeallocBugType,
761void ObjCDeallocChecker::initIdentifierInfoAndSelectors(
762 ASTContext &Ctx)
const {
766 NSObjectII = &Ctx.
Idents.
get(
"NSObject");
767 SenTestCaseII = &Ctx.
Idents.
get(
"SenTestCase");
768 XCTestCaseII = &Ctx.
Idents.
get(
"XCTestCase");
769 Block_releaseII = &Ctx.
Idents.
get(
"_Block_release");
770 CIFilterII = &Ctx.
Idents.
get(
"CIFilter");
772 const IdentifierInfo *DeallocII = &Ctx.
Idents.
get(
"dealloc");
773 const IdentifierInfo *ReleaseII = &Ctx.
Idents.
get(
"release");
779bool ObjCDeallocChecker::isSuperDeallocMessage(
780 const ObjCMethodCall &M)
const {
789ObjCDeallocChecker::getContainingObjCImpl(
const StackFrame *SF)
const {
796const ObjCPropertyDecl *ObjCDeallocChecker::findShadowedPropertyDecl(
797 const ObjCPropertyImplDecl *PropImpl)
const {
804 auto *CatDecl = dyn_cast<ObjCCategoryDecl>(PropDecl->
getDeclContext());
807 if (!CatDecl || !CatDecl->IsClassExtension())
812 for (
const NamedDecl *D : R) {
813 auto *ShadowedPropDecl = dyn_cast<ObjCPropertyDecl>(D);
814 if (!ShadowedPropDecl)
817 if (ShadowedPropDecl->isInstanceProperty()) {
818 assert(ShadowedPropDecl->isReadOnly());
819 return ShadowedPropDecl;
827void ObjCDeallocChecker::transitionToReleaseValue(CheckerContext &
C,
836 removeValueRequiringRelease(InitialState, InstanceSym,
Value);
838 if (ReleasedState != InitialState) {
839 C.addTransition(ReleasedState);
849 const ObjCIvarRegion *RemovedRegion = getIvarRegionForIvarSymbol(
Value);
853 const SymbolSet *Unreleased = State->get<UnreleasedIvarMap>(Instance);
858 SymbolSet::Factory &F = State->getStateManager().get_context<
SymbolSet>();
860 for (
auto &Sym : *Unreleased) {
861 const ObjCIvarRegion *UnreleasedRegion = getIvarRegionForIvarSymbol(Sym);
862 assert(UnreleasedRegion);
864 NewUnreleased = F.remove(NewUnreleased, Sym);
868 if (NewUnreleased.isEmpty()) {
869 return State->remove<UnreleasedIvarMap>(Instance);
872 return State->set<UnreleasedIvarMap>(Instance, NewUnreleased);
878 const ObjCPropertyImplDecl *PropImpl)
const {
879 const ObjCIvarDecl *IvarDecl;
880 const ObjCPropertyDecl *PropDecl;
891 if (isReleasedByCIFilterDealloc(PropImpl))
894 if (isNibLoadedIvarWithoutRetain(PropImpl))
911 llvm_unreachable(
"Unrecognized setter kind");
917ObjCDeallocChecker::getValueReleasedByNillingOut(
const ObjCMethodCall &M,
918 CheckerContext &
C)
const {
932 std::tie(notNilState, nilState) =
933 C.getState()->assume(Arg.
castAs<DefinedOrUnknownSVal>());
934 if (!(nilState && !notNilState))
947 SVal LVal = State->getLValue(PropIvarDecl, ReceiverVal);
948 std::optional<Loc> LValLoc = LVal.
getAs<Loc>();
952 SVal CurrentValInIvar = State->getSVal(*LValLoc);
959bool ObjCDeallocChecker::isInInstanceDealloc(
const CheckerContext &
C,
960 SVal &SelfValOut)
const {
961 return isInInstanceDealloc(
C,
C.getStackFrame(), SelfValOut);
967bool ObjCDeallocChecker::isInInstanceDealloc(
const CheckerContext &
C,
968 const StackFrame *SF,
969 SVal &SelfValOut)
const {
970 auto *MD = dyn_cast<ObjCMethodDecl>(SF->
getDecl());
974 const ImplicitParamDecl *SelfDecl = SF->
getSelfDecl();
975 assert(SelfDecl &&
"No self in -dealloc?");
978 SelfValOut = State->getSVal(State->getRegion(SelfDecl, SF));
985bool ObjCDeallocChecker::instanceDeallocIsOnStack(
const CheckerContext &
C,
986 SVal &InstanceValOut)
const {
987 return llvm::any_of(
C.stackframes(), [&](
const StackFrame &SF) {
988 return isInInstanceDealloc(C, &SF, InstanceValOut);
995bool ObjCDeallocChecker::classHasSeparateTeardown(
996 const ObjCInterfaceDecl *ID)
const {
998 for ( ;
ID ;
ID =
ID->getSuperClass()) {
999 IdentifierInfo *II =
ID->getIdentifier();
1001 if (II == NSObjectII)
1008 if (II == XCTestCaseII || II == SenTestCaseII)
1023bool ObjCDeallocChecker::isReleasedByCIFilterDealloc(
1024 const ObjCPropertyImplDecl *PropImpl)
const {
1029 const char *ReleasePrefix =
"input";
1030 if (!(PropName.starts_with(ReleasePrefix) ||
1031 IvarName.starts_with(ReleasePrefix))) {
1035 const ObjCInterfaceDecl *
ID =
1037 for ( ;
ID ;
ID =
ID->getSuperClass()) {
1038 IdentifierInfo *II =
ID->getIdentifier();
1039 if (II == CIFilterII)
1054bool ObjCDeallocChecker::isNibLoadedIvarWithoutRetain(
1055 const ObjCPropertyImplDecl *PropImpl)
const {
1057 if (!IvarDecl->
hasAttr<IBOutletAttr>())
1060 const llvm::Triple &
Target =
1072void ento::registerObjCDeallocChecker(CheckerManager &Mgr) {
1076bool ento::shouldRegisterObjCDeallocChecker(
const CheckerManager &mgr) {
1079 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.
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.
const Decl * getDecl() const
const ImplicitParamDecl * getSelfDecl() const
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.
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.