33#include "llvm/ADT/STLExtras.h"
34#include "llvm/ADT/StringMap.h"
35#include "llvm/Support/raw_ostream.h"
43class APIMisuse :
public BugType {
45 APIMisuse(
const CheckerBase *checker,
const char *name)
56 return ID->getIdentifier()->getName();
72 bool IncludeSuperclasses =
true) {
73 static llvm::StringMap<FoundationClass> Classes;
74 if (Classes.empty()) {
85 FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
86 if (result ==
FC_None && IncludeSuperclasses)
98class NilArgChecker :
public Checker<check::PreObjCMessage,
99 check::PostStmt<ObjCDictionaryLiteral>,
100 check::PostStmt<ObjCArrayLiteral>,
101 EventDispatcher<ImplicitNullDerefEvent>> {
102 const APIMisuse BT{
this,
"nil argument"};
104 mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
105 mutable Selector ArrayWithObjectSel;
106 mutable Selector AddObjectSel;
107 mutable Selector InsertObjectAtIndexSel;
108 mutable Selector ReplaceObjectAtIndexWithObjectSel;
109 mutable Selector SetObjectAtIndexedSubscriptSel;
110 mutable Selector ArrayByAddingObjectSel;
111 mutable Selector DictionaryWithObjectForKeySel;
112 mutable Selector SetObjectForKeySel;
113 mutable Selector SetObjectForKeyedSubscriptSel;
114 mutable Selector RemoveObjectForKeySel;
116 void warnIfNilExpr(
const Expr *E,
const char *Msg, CheckerContext &
C)
const;
118 void warnIfNilArg(CheckerContext &
C,
const ObjCMethodCall &msg,
unsigned Arg,
121 void generateBugReport(ExplodedNode *N, StringRef Msg, SourceRange Range,
122 const Expr *Expr, CheckerContext &
C)
const;
125 void checkPreObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
126 void checkPostStmt(
const ObjCDictionaryLiteral *DL, CheckerContext &
C)
const;
127 void checkPostStmt(
const ObjCArrayLiteral *AL, CheckerContext &
C)
const;
131void NilArgChecker::warnIfNilExpr(
const Expr *E,
134 auto Location =
C.getSVal(E).getAs<Loc>();
142 if (ExplodedNode *N =
C.generateErrorNode()) {
151 if (ExplodedNode *N =
C.generateSink(Null,
C.getPredecessor())) {
152 dispatchEvent({*Location,
false, N, &
C.getBugReporter(),
159void NilArgChecker::warnIfNilArg(CheckerContext &
C,
160 const ObjCMethodCall &msg,
163 bool CanBeSubscript)
const {
166 if (!State->isNull(msg.
getArgSVal(Arg)).isConstrainedTrue())
174 if (ExplodedNode *N =
C.generateErrorNode()) {
175 SmallString<128> sbuf;
176 llvm::raw_svector_ostream os(sbuf);
181 os <<
"Array element cannot be nil";
184 os <<
"Value stored into '";
191 llvm_unreachable(
"Missing foundation class for the subscript expr");
196 os <<
"Value argument ";
199 os <<
"Key argument ";
203 os <<
"' cannot be nil";
207 os <<
"' cannot be nil";
216void NilArgChecker::generateBugReport(ExplodedNode *N,
220 CheckerContext &
C)
const {
221 auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
224 C.emitReport(std::move(R));
227void NilArgChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
228 CheckerContext &
C)
const {
235 static const unsigned InvalidArgIndex =
UINT_MAX;
236 unsigned Arg = InvalidArgIndex;
237 bool CanBeSubscript =
false;
245 if (StringSelectors.empty()) {
246 ASTContext &Ctx =
C.getASTContext();
259 for (Selector KnownSel : Sels)
260 StringSelectors[KnownSel] = 0;
262 auto I = StringSelectors.find(S);
263 if (I == StringSelectors.end())
272 if (ArrayWithObjectSel.
isNull()) {
273 ASTContext &Ctx =
C.getASTContext();
276 InsertObjectAtIndexSel =
278 ReplaceObjectAtIndexWithObjectSel =
280 SetObjectAtIndexedSubscriptSel =
285 if (S == ArrayWithObjectSel || S == AddObjectSel ||
286 S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
288 }
else if (S == SetObjectAtIndexedSubscriptSel) {
290 CanBeSubscript =
true;
291 }
else if (S == ReplaceObjectAtIndexWithObjectSel) {
300 if (DictionaryWithObjectForKeySel.
isNull()) {
301 ASTContext &Ctx =
C.getASTContext();
302 DictionaryWithObjectForKeySel =
305 SetObjectForKeyedSubscriptSel =
310 if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
312 warnIfNilArg(
C, msg, 1,
Class);
313 }
else if (S == SetObjectForKeyedSubscriptSel) {
314 CanBeSubscript =
true;
316 }
else if (S == RemoveObjectForKeySel) {
322 if ((Arg != InvalidArgIndex))
323 warnIfNilArg(
C, msg, Arg,
Class, CanBeSubscript);
326void NilArgChecker::checkPostStmt(
const ObjCArrayLiteral *AL,
327 CheckerContext &
C)
const {
329 for (
unsigned i = 0; i < NumOfElements; ++i) {
330 warnIfNilExpr(AL->
getElement(i),
"Array element cannot be nil",
C);
334void NilArgChecker::checkPostStmt(
const ObjCDictionaryLiteral *DL,
335 CheckerContext &
C)
const {
337 for (
unsigned i = 0; i < NumOfElements; ++i) {
339 warnIfNilExpr(Element.
Key,
"Dictionary key cannot be nil",
C);
340 warnIfNilExpr(Element.
Value,
"Dictionary value cannot be nil",
C);
349class CFNumberChecker :
public Checker< check::PreStmt<CallExpr> > {
350 const APIMisuse BT{
this,
"Bad use of CFNumber APIs"};
351 mutable IdentifierInfo *ICreate =
nullptr, *IGetValue =
nullptr;
353 CFNumberChecker() =
default;
355 void checkPreStmt(
const CallExpr *CE, CheckerContext &
C)
const;
379 static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
382 return FixedSize[i-1];
406static const char* GetCFNumberTypeStr(uint64_t i) {
407 static const char* Names[] = {
408 "kCFNumberSInt8Type",
409 "kCFNumberSInt16Type",
410 "kCFNumberSInt32Type",
411 "kCFNumberSInt64Type",
412 "kCFNumberFloat32Type",
413 "kCFNumberFloat64Type",
415 "kCFNumberShortType",
418 "kCFNumberLongLongType",
419 "kCFNumberFloatType",
420 "kCFNumberDoubleType",
421 "kCFNumberCFIndexType",
422 "kCFNumberNSIntegerType",
423 "kCFNumberCGFloatType"
430void CFNumberChecker::checkPreStmt(
const CallExpr *CE,
431 CheckerContext &
C)
const {
433 const FunctionDecl *FD =
C.getCalleeDecl(CE);
437 ASTContext &Ctx =
C.getASTContext();
439 ICreate = &Ctx.
Idents.
get(
"CFNumberCreate");
440 IGetValue = &Ctx.
Idents.
get(
"CFNumberGetValue");
447 SVal TheTypeVal =
C.getSVal(CE->
getArg(1));
451 std::optional<nonloc::ConcreteInt>
V =
452 dyn_cast<nonloc::ConcreteInt>(TheTypeVal);
456 uint64_t NumberKind =
V->getValue()->getLimitedValue();
457 std::optional<uint64_t> OptCFNumberSize =
GetCFNumberSize(Ctx, NumberKind);
460 if (!OptCFNumberSize)
463 uint64_t CFNumberSize = *OptCFNumberSize;
468 SVal TheValueExpr =
C.getSVal(CE->
getArg(2));
472 std::optional<loc::MemRegionVal> LV = TheValueExpr.
getAs<loc::MemRegionVal>();
476 const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
490 if (PrimitiveTypeSize == CFNumberSize)
495 ExplodedNode *N =
C.generateNonFatalErrorNode();
497 SmallString<128> sbuf;
498 llvm::raw_svector_ostream os(sbuf);
502 os << (PrimitiveTypeSize == 8 ?
"An " :
"A ")
503 << PrimitiveTypeSize <<
"-bit integer is used to initialize a "
504 <<
"CFNumber object that represents "
505 << (CFNumberSize == 8 ?
"an " :
"a ")
506 << CFNumberSize <<
"-bit integer; ";
508 os <<
"A CFNumber object that represents "
509 << (CFNumberSize == 8 ?
"an " :
"a ")
510 << CFNumberSize <<
"-bit integer is used to initialize "
511 << (PrimitiveTypeSize == 8 ?
"an " :
"a ")
512 << PrimitiveTypeSize <<
"-bit integer; ";
515 if (PrimitiveTypeSize < CFNumberSize)
516 os << (CFNumberSize - PrimitiveTypeSize)
517 <<
" bits of the CFNumber value will "
518 << (isCreate ?
"be garbage." :
"overwrite adjacent storage.");
520 os << (PrimitiveTypeSize - CFNumberSize)
521 <<
" bits of the integer value will be "
522 << (isCreate ?
"lost." :
"garbage.");
524 auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
526 C.emitReport(std::move(report));
535class CFRetainReleaseChecker :
public Checker<check::PreCall> {
536 const APIMisuse BT{
this,
"null passed to CF memory management function"};
537 const CallDescriptionSet ModelledCalls = {
538 {CDM::CLibrary, {
"CFRetain"}, 1},
539 {CDM::CLibrary, {
"CFRelease"}, 1},
540 {CDM::CLibrary, {
"CFMakeCollectable"}, 1},
541 {CDM::CLibrary, {
"CFAutorelease"}, 1},
545 void checkPreCall(
const CallEvent &
Call, CheckerContext &
C)
const;
549void CFRetainReleaseChecker::checkPreCall(
const CallEvent &
Call,
550 CheckerContext &
C)
const {
556 SVal ArgVal =
Call.getArgSVal(0);
557 std::optional<DefinedSVal> DefArgVal = ArgVal.
getAs<DefinedSVal>();
564 std::tie(stateNonNull, stateNull) = state->assume(*DefArgVal);
567 ExplodedNode *N =
C.generateErrorNode(stateNull);
572 raw_svector_ostream
OS(Str);
573 OS <<
"Null pointer argument in call to "
576 auto report = std::make_unique<PathSensitiveBugReport>(BT,
OS.str(), N);
577 report->addRange(
Call.getArgSourceRange(0));
579 C.emitReport(std::move(report));
584 C.addTransition(stateNonNull);
592class ClassReleaseChecker :
public Checker<check::PreObjCMessage> {
593 mutable Selector releaseS;
594 mutable Selector retainS;
595 mutable Selector autoreleaseS;
596 mutable Selector drainS;
598 this,
"message incorrectly sent to class instead of class instance"};
601 void checkPreObjCMessage(
const ObjCMethodCall &msg, CheckerContext &
C)
const;
605void ClassReleaseChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
606 CheckerContext &
C)
const {
608 ASTContext &Ctx =
C.getASTContext();
621 if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
624 if (ExplodedNode *N =
C.generateNonFatalErrorNode()) {
625 SmallString<200> buf;
626 llvm::raw_svector_ostream os(buf);
630 os <<
"' message should be sent to instances "
631 "of class '" <<
Class->getName()
632 <<
"' and not the class directly";
634 auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
636 C.emitReport(std::move(report));
646class VariadicMethodTypeChecker :
public Checker<check::PreObjCMessage> {
647 mutable Selector arrayWithObjectsS;
648 mutable Selector dictionaryWithObjectsAndKeysS;
649 mutable Selector setWithObjectsS;
650 mutable Selector orderedSetWithObjectsS;
651 mutable Selector initWithObjectsS;
652 mutable Selector initWithObjectsAndKeysS;
653 const APIMisuse BT{
this,
"Arguments passed to variadic method aren't all "
654 "Objective-C pointer types"};
656 bool isVariadicMessage(
const ObjCMethodCall &msg)
const;
659 void checkPreObjCMessage(
const ObjCMethodCall &msg, CheckerContext &
C)
const;
666VariadicMethodTypeChecker::isVariadicMessage(
const ObjCMethodCall &msg)
const {
667 const ObjCMethodDecl *MD = msg.
getDecl();
687 return S == initWithObjectsS;
689 return S == initWithObjectsAndKeysS;
698 return S == arrayWithObjectsS;
700 return S == orderedSetWithObjectsS;
702 return S == setWithObjectsS;
704 return S == dictionaryWithObjectsAndKeysS;
711void VariadicMethodTypeChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
712 CheckerContext &
C)
const {
713 if (arrayWithObjectsS.
isNull()) {
714 ASTContext &Ctx =
C.getASTContext();
716 dictionaryWithObjectsAndKeysS =
725 if (!isVariadicMessage(msg))
734 unsigned variadicArgsEnd = msg.
getNumArgs() - 1;
736 if (variadicArgsEnd <= variadicArgsBegin)
740 std::optional<ExplodedNode *> errorNode;
742 for (
unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
756 if (
C.getASTContext().isObjCNSObjectType(ArgTy))
765 errorNode =
C.generateNonFatalErrorNode();
770 SmallString<128> sbuf;
771 llvm::raw_svector_ostream os(sbuf);
775 os <<
"Argument to '" <<
TypeName <<
"' method '";
777 os <<
"Argument to method '";
780 os <<
"' should be an Objective-C pointer type, not '";
781 ArgTy.
print(os,
C.getLangOpts());
784 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), *errorNode);
786 C.emitReport(std::move(R));
801 :
public Checker<check::PostStmt<ObjCForCollectionStmt>,
802 check::PostObjCMessage,
804 check::PointerEscape > {
805 mutable IdentifierInfo *CountSelectorII =
nullptr;
807 bool isCollectionCountMethod(
const ObjCMethodCall &M,
808 CheckerContext &
C)
const;
811 ObjCLoopChecker() =
default;
812 void checkPostStmt(
const ObjCForCollectionStmt *FCS, CheckerContext &
C)
const;
813 void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
814 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &
C)
const;
817 const CallEvent *
Call,
854 std::optional<DefinedSVal> KnownCollection =
856 if (!KnownCollection)
860 std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
861 if (StNil && !StNonNil) {
887 std::optional<Loc> ElementLoc;
888 if (
const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
890 assert(ElemDecl->
getInit() ==
nullptr);
891 ElementLoc = State->getLValue(ElemDecl, LCtx);
893 ElementLoc = State->getSVal(Element, LCtx).getAs<
Loc>();
900 SVal Val = State->getSVal(*ElementLoc);
908 SymbolRef CollectionS,
bool Assumption) {
909 if (!State || !CollectionS)
912 const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
914 const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
916 return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
917 return (Assumption == *KnownNonEmpty) ? State :
nullptr;
921 SVal CountGreaterThanZeroVal =
924 SvalBuilder.
makeIntVal(0, (*CountS)->getType()),
926 std::optional<DefinedSVal> CountGreaterThanZero =
928 if (!CountGreaterThanZero) {
934 return State->assume(*CountGreaterThanZero, Assumption);
956 return BE->getSrc()->getLoopTarget() == FCS;
968void ObjCLoopChecker::checkPostStmt(
const ObjCForCollectionStmt *FCS,
969 CheckerContext &
C)
const {
985 C.generateSink(
C.getState(),
C.getPredecessor());
986 else if (State !=
C.getState())
987 C.addTransition(State);
990bool ObjCLoopChecker::isCollectionCountMethod(
const ObjCMethodCall &M,
991 CheckerContext &
C)
const {
994 if (!CountSelectorII)
995 CountSelectorII = &
C.getASTContext().Idents.get(
"count");
1002void ObjCLoopChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
1003 CheckerContext &
C)
const {
1024 if (!isCollectionCountMethod(M,
C))
1028 SymbolRef CountS =
C.getSVal(MsgExpr).getAsSymbol();
1032 C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1033 State = State->set<ContainerCountMap>(ContainerS, CountS);
1035 if (
const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1036 State = State->remove<ContainerNonEmptyMap>(ContainerS);
1040 C.addTransition(State);
1058 StaticClass = Message->getOriginExpr()->getReceiverInterface();
1079 return Message->getReceiverSVal().getAsSymbol();
1085 const CallEvent *
Call,
1095 if (Sym == ImmutableReceiver)
1100 State = State->remove<ContainerCountMap>(Sym);
1101 State = State->remove<ContainerNonEmptyMap>(Sym);
1106void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1107 CheckerContext &
C)
const {
1111 ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1112 for (
SymbolRef Sym : llvm::make_first_range(Tracked)) {
1113 if (SymReaper.
isDead(Sym)) {
1114 State = State->remove<ContainerCountMap>(Sym);
1115 State = State->remove<ContainerNonEmptyMap>(Sym);
1119 C.addTransition(State);
1126class ObjCNonNilReturnValueChecker
1127 :
public Checker<check::PostObjCMessage,
1128 check::PostStmt<ObjCArrayLiteral>,
1129 check::PostStmt<ObjCDictionaryLiteral>,
1130 check::PostStmt<ObjCBoxedExpr> > {
1132 mutable Selector ObjectAtIndex;
1133 mutable Selector ObjectAtIndexedSubscript;
1134 mutable Selector NullSelector;
1137 ObjCNonNilReturnValueChecker() =
default;
1141 CheckerContext &
C)
const;
1142 void assumeExprIsNonNull(
const Expr *E, CheckerContext &
C)
const {
1143 C.addTransition(assumeExprIsNonNull(E,
C.getState(),
C));
1146 void checkPostStmt(
const ObjCArrayLiteral *E, CheckerContext &
C)
const {
1147 assumeExprIsNonNull(E,
C);
1149 void checkPostStmt(
const ObjCDictionaryLiteral *E, CheckerContext &
C)
const {
1150 assumeExprIsNonNull(E,
C);
1152 void checkPostStmt(
const ObjCBoxedExpr *E, CheckerContext &
C)
const {
1153 assumeExprIsNonNull(E,
C);
1156 void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
1161ObjCNonNilReturnValueChecker::assumeExprIsNonNull(
const Expr *NonNullExpr,
1163 CheckerContext &
C)
const {
1164 SVal Val =
C.getSVal(NonNullExpr);
1165 if (std::optional<DefinedOrUnknownSVal> DV =
1166 Val.
getAs<DefinedOrUnknownSVal>())
1167 return State->assume(*DV,
true);
1171void ObjCNonNilReturnValueChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
1177 ASTContext &Ctx =
C.getASTContext();
1179 ObjectAtIndexedSubscript =
GetUnarySelector(
"objectAtIndexedSubscript", Ctx);
1194 if (!
C.inTopFrame() && M.
getDecl() &&
1207 if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1221 C.addTransition(State);
1228void ento::registerNilArgChecker(CheckerManager &mgr) {
1232bool ento::shouldRegisterNilArgChecker(
const CheckerManager &mgr) {
1236void ento::registerCFNumberChecker(CheckerManager &mgr) {
1240bool ento::shouldRegisterCFNumberChecker(
const CheckerManager &mgr) {
1244void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1248bool ento::shouldRegisterCFRetainReleaseChecker(
const CheckerManager &mgr) {
1252void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1256bool ento::shouldRegisterClassReleaseChecker(
const CheckerManager &mgr) {
1260void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1264bool ento::shouldRegisterVariadicMethodTypeChecker(
const CheckerManager &mgr) {
1268void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1272bool ento::shouldRegisterObjCLoopChecker(
const CheckerManager &mgr) {
1276void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1280bool ento::shouldRegisterObjCNonNilReturnValueChecker(
const CheckerManager &mgr) {
Defines the clang::ASTContext interface.
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
static bool isKnownNonNilCollectionType(QualType T)
static ProgramStateRef assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State, SymbolRef CollectionS, bool Assumption)
Returns NULL state if the collection is known to contain elements (or is known not to contain element...
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg)
static std::optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
static ProgramStateRef checkElementNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection elements are non-nil.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Defines the Objective-C statement AST node classes.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
DeclContext * getDeclContext()
This represents one expression.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Represents Objective-C's collection statement.
Represents an ObjC class declaration.
ObjCInterfaceDecl * getSuperClass() const
ObjCMethodDecl - Represents an instance or class method declaration.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
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.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
bool isUnarySelector() const
bool isNull() const
Determine whether this is the empty selector.
unsigned getNumArgs() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isBlockPointerType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isObjCObjectPointerType() const
Represents a variable declaration or definition.
const Expr * getInit() const
bool contains(const CallEvent &Call) const
Represents an abstract call to a function or method along a particular path.
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
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,...
Simple checker classes that implement one frontend (i.e.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
Represents any expression that calls an Objective-C method.
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
bool isInstanceMessage() const
const Expr * getArgExpr(unsigned Index) const override
Returns the expression associated with a given argument.
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
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.
SourceRange getSourceRange() const override
Returns a source range for the entire call, suitable for outputting in diagnostics.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Selector getSelector() const
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
QualType getConditionType() const
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
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.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
virtual QualType getValueType() const =0
Represents symbolic expression that isn't a location.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
const char *const AppleAPIMisuse
bool isCFObjectRef(QualType T)
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,...
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Descriptor *Desc)
The JSON file list parser is used to communicate input to InstallAPI.
static Selector getKeywordSelector(ASTContext &Ctx, const IdentifierInfos *...IIs)
bool isa(CodeGen::Address addr)
@ NonNull
Values of this type can never be null.
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
Expr * Value
The value of the dictionary element.
Expr * Key
The key for the dictionary element.