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 const llvm::StringMap<FoundationClass> Classes{
81 FoundationClass result = Classes.lookup(ID->getIdentifier()->getName());
82 if (result ==
FC_None && IncludeSuperclasses)
94class NilArgChecker :
public Checker<check::PreObjCMessage,
95 check::PostStmt<ObjCDictionaryLiteral>,
96 check::PostStmt<ObjCArrayLiteral>,
97 EventDispatcher<ImplicitNullDerefEvent>> {
98 const APIMisuse BT{
this,
"nil argument"};
100 mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
101 mutable Selector ArrayWithObjectSel;
102 mutable Selector AddObjectSel;
103 mutable Selector InsertObjectAtIndexSel;
104 mutable Selector ReplaceObjectAtIndexWithObjectSel;
105 mutable Selector SetObjectAtIndexedSubscriptSel;
106 mutable Selector ArrayByAddingObjectSel;
107 mutable Selector DictionaryWithObjectForKeySel;
108 mutable Selector SetObjectForKeySel;
109 mutable Selector SetObjectForKeyedSubscriptSel;
110 mutable Selector RemoveObjectForKeySel;
112 void warnIfNilExpr(
const Expr *E,
const char *Msg, CheckerContext &
C)
const;
114 void warnIfNilArg(CheckerContext &
C,
const ObjCMethodCall &msg,
unsigned Arg,
117 void generateBugReport(ExplodedNode *N, StringRef Msg, SourceRange Range,
118 const Expr *Expr, CheckerContext &
C)
const;
121 void checkPreObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
122 void checkPostStmt(
const ObjCDictionaryLiteral *DL, CheckerContext &
C)
const;
123 void checkPostStmt(
const ObjCArrayLiteral *AL, CheckerContext &
C)
const;
127void NilArgChecker::warnIfNilExpr(
const Expr *E,
130 auto Location =
C.getSVal(E).getAs<Loc>();
138 if (ExplodedNode *N =
C.generateErrorNode()) {
147 if (ExplodedNode *N =
C.generateSink(Null,
C.getPredecessor())) {
148 dispatchEvent({*Location,
false, N, &
C.getBugReporter(),
155void NilArgChecker::warnIfNilArg(CheckerContext &
C,
156 const ObjCMethodCall &msg,
159 bool CanBeSubscript)
const {
162 if (!State->isNull(msg.
getArgSVal(Arg)).isConstrainedTrue())
170 if (ExplodedNode *N =
C.generateErrorNode()) {
171 SmallString<128> sbuf;
172 llvm::raw_svector_ostream os(sbuf);
177 os <<
"Array element cannot be nil";
180 os <<
"Value stored into '";
187 llvm_unreachable(
"Missing foundation class for the subscript expr");
192 os <<
"Value argument ";
195 os <<
"Key argument ";
199 os <<
"' cannot be nil";
203 os <<
"' cannot be nil";
212void NilArgChecker::generateBugReport(ExplodedNode *N,
216 CheckerContext &
C)
const {
217 auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
220 C.emitReport(std::move(R));
223void NilArgChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
224 CheckerContext &
C)
const {
231 static const unsigned InvalidArgIndex =
UINT_MAX;
232 unsigned Arg = InvalidArgIndex;
233 bool CanBeSubscript =
false;
241 if (StringSelectors.empty()) {
242 ASTContext &Ctx =
C.getASTContext();
255 for (Selector KnownSel : Sels)
256 StringSelectors[KnownSel] = 0;
258 auto I = StringSelectors.find(S);
259 if (I == StringSelectors.end())
268 if (ArrayWithObjectSel.
isNull()) {
269 ASTContext &Ctx =
C.getASTContext();
272 InsertObjectAtIndexSel =
274 ReplaceObjectAtIndexWithObjectSel =
276 SetObjectAtIndexedSubscriptSel =
281 if (S == ArrayWithObjectSel || S == AddObjectSel ||
282 S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
284 }
else if (S == SetObjectAtIndexedSubscriptSel) {
286 CanBeSubscript =
true;
287 }
else if (S == ReplaceObjectAtIndexWithObjectSel) {
296 if (DictionaryWithObjectForKeySel.
isNull()) {
297 ASTContext &Ctx =
C.getASTContext();
298 DictionaryWithObjectForKeySel =
301 SetObjectForKeyedSubscriptSel =
306 if (S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
308 warnIfNilArg(
C, msg, 1,
Class);
309 }
else if (S == SetObjectForKeyedSubscriptSel) {
310 CanBeSubscript =
true;
312 }
else if (S == RemoveObjectForKeySel) {
318 if ((Arg != InvalidArgIndex))
319 warnIfNilArg(
C, msg, Arg,
Class, CanBeSubscript);
322void NilArgChecker::checkPostStmt(
const ObjCArrayLiteral *AL,
323 CheckerContext &
C)
const {
325 for (
unsigned i = 0; i < NumOfElements; ++i) {
326 warnIfNilExpr(AL->
getElement(i),
"Array element cannot be nil",
C);
330void NilArgChecker::checkPostStmt(
const ObjCDictionaryLiteral *DL,
331 CheckerContext &
C)
const {
333 for (
unsigned i = 0; i < NumOfElements; ++i) {
335 warnIfNilExpr(Element.
Key,
"Dictionary key cannot be nil",
C);
336 warnIfNilExpr(Element.
Value,
"Dictionary value cannot be nil",
C);
345class CFNumberChecker :
public Checker< check::PreStmt<CallExpr> > {
346 const APIMisuse BT{
this,
"Bad use of CFNumber APIs"};
347 mutable IdentifierInfo *ICreate =
nullptr, *IGetValue =
nullptr;
349 CFNumberChecker() =
default;
351 void checkPreStmt(
const CallExpr *CE, CheckerContext &
C)
const;
375 static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
378 return FixedSize[i-1];
402static const char* GetCFNumberTypeStr(uint64_t i) {
403 static const char* Names[] = {
404 "kCFNumberSInt8Type",
405 "kCFNumberSInt16Type",
406 "kCFNumberSInt32Type",
407 "kCFNumberSInt64Type",
408 "kCFNumberFloat32Type",
409 "kCFNumberFloat64Type",
411 "kCFNumberShortType",
414 "kCFNumberLongLongType",
415 "kCFNumberFloatType",
416 "kCFNumberDoubleType",
417 "kCFNumberCFIndexType",
418 "kCFNumberNSIntegerType",
419 "kCFNumberCGFloatType"
426void CFNumberChecker::checkPreStmt(
const CallExpr *CE,
427 CheckerContext &
C)
const {
429 const FunctionDecl *FD =
C.getCalleeDecl(CE);
433 ASTContext &Ctx =
C.getASTContext();
435 ICreate = &Ctx.
Idents.
get(
"CFNumberCreate");
436 IGetValue = &Ctx.
Idents.
get(
"CFNumberGetValue");
443 SVal TheTypeVal =
C.getSVal(CE->
getArg(1));
447 std::optional<nonloc::ConcreteInt>
V =
448 dyn_cast<nonloc::ConcreteInt>(TheTypeVal);
452 uint64_t NumberKind =
V->getValue()->getLimitedValue();
453 std::optional<uint64_t> OptCFNumberSize =
GetCFNumberSize(Ctx, NumberKind);
456 if (!OptCFNumberSize)
459 uint64_t CFNumberSize = *OptCFNumberSize;
464 SVal TheValueExpr =
C.getSVal(CE->
getArg(2));
468 std::optional<loc::MemRegionVal> LV = TheValueExpr.
getAs<loc::MemRegionVal>();
472 const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
486 if (PrimitiveTypeSize == CFNumberSize)
491 ExplodedNode *N =
C.generateNonFatalErrorNode();
493 SmallString<128> sbuf;
494 llvm::raw_svector_ostream os(sbuf);
498 os << (PrimitiveTypeSize == 8 ?
"An " :
"A ")
499 << PrimitiveTypeSize <<
"-bit integer is used to initialize a "
500 <<
"CFNumber object that represents "
501 << (CFNumberSize == 8 ?
"an " :
"a ")
502 << CFNumberSize <<
"-bit integer; ";
504 os <<
"A CFNumber object that represents "
505 << (CFNumberSize == 8 ?
"an " :
"a ")
506 << CFNumberSize <<
"-bit integer is used to initialize "
507 << (PrimitiveTypeSize == 8 ?
"an " :
"a ")
508 << PrimitiveTypeSize <<
"-bit integer; ";
511 if (PrimitiveTypeSize < CFNumberSize)
512 os << (CFNumberSize - PrimitiveTypeSize)
513 <<
" bits of the CFNumber value will "
514 << (isCreate ?
"be garbage." :
"overwrite adjacent storage.");
516 os << (PrimitiveTypeSize - CFNumberSize)
517 <<
" bits of the integer value will be "
518 << (isCreate ?
"lost." :
"garbage.");
520 auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
522 C.emitReport(std::move(report));
531class CFRetainReleaseChecker :
public Checker<check::PreCall> {
532 const APIMisuse BT{
this,
"null passed to CF memory management function"};
533 const CallDescriptionSet ModelledCalls = {
534 {CDM::CLibrary, {
"CFRetain"}, 1},
535 {CDM::CLibrary, {
"CFRelease"}, 1},
536 {CDM::CLibrary, {
"CFMakeCollectable"}, 1},
537 {CDM::CLibrary, {
"CFAutorelease"}, 1},
541 void checkPreCall(
const CallEvent &
Call, CheckerContext &
C)
const;
545void CFRetainReleaseChecker::checkPreCall(
const CallEvent &
Call,
546 CheckerContext &
C)
const {
552 SVal ArgVal =
Call.getArgSVal(0);
553 std::optional<DefinedSVal> DefArgVal = ArgVal.
getAs<DefinedSVal>();
560 std::tie(stateNonNull, stateNull) = state->assume(*DefArgVal);
563 ExplodedNode *N =
C.generateErrorNode(stateNull);
568 raw_svector_ostream
OS(Str);
569 OS <<
"Null pointer argument in call to "
572 auto report = std::make_unique<PathSensitiveBugReport>(BT,
OS.str(), N);
573 report->addRange(
Call.getArgSourceRange(0));
575 C.emitReport(std::move(report));
580 C.addTransition(stateNonNull);
588class ClassReleaseChecker :
public Checker<check::PreObjCMessage> {
589 mutable Selector releaseS;
590 mutable Selector retainS;
591 mutable Selector autoreleaseS;
592 mutable Selector drainS;
594 this,
"message incorrectly sent to class instead of class instance"};
597 void checkPreObjCMessage(
const ObjCMethodCall &msg, CheckerContext &
C)
const;
601void ClassReleaseChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
602 CheckerContext &
C)
const {
604 ASTContext &Ctx =
C.getASTContext();
617 if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
620 if (ExplodedNode *N =
C.generateNonFatalErrorNode()) {
621 SmallString<200> buf;
622 llvm::raw_svector_ostream os(buf);
626 os <<
"' message should be sent to instances "
627 "of class '" <<
Class->getName()
628 <<
"' and not the class directly";
630 auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
632 C.emitReport(std::move(report));
642class VariadicMethodTypeChecker :
public Checker<check::PreObjCMessage> {
643 mutable Selector arrayWithObjectsS;
644 mutable Selector dictionaryWithObjectsAndKeysS;
645 mutable Selector setWithObjectsS;
646 mutable Selector orderedSetWithObjectsS;
647 mutable Selector initWithObjectsS;
648 mutable Selector initWithObjectsAndKeysS;
649 const APIMisuse BT{
this,
"Arguments passed to variadic method aren't all "
650 "Objective-C pointer types"};
652 bool isVariadicMessage(
const ObjCMethodCall &msg)
const;
655 void checkPreObjCMessage(
const ObjCMethodCall &msg, CheckerContext &
C)
const;
662VariadicMethodTypeChecker::isVariadicMessage(
const ObjCMethodCall &msg)
const {
663 const ObjCMethodDecl *MD = msg.
getDecl();
683 return S == initWithObjectsS;
685 return S == initWithObjectsAndKeysS;
694 return S == arrayWithObjectsS;
696 return S == orderedSetWithObjectsS;
698 return S == setWithObjectsS;
700 return S == dictionaryWithObjectsAndKeysS;
707void VariadicMethodTypeChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
708 CheckerContext &
C)
const {
709 if (arrayWithObjectsS.
isNull()) {
710 ASTContext &Ctx =
C.getASTContext();
712 dictionaryWithObjectsAndKeysS =
721 if (!isVariadicMessage(msg))
730 unsigned variadicArgsEnd = msg.
getNumArgs() - 1;
732 if (variadicArgsEnd <= variadicArgsBegin)
736 std::optional<ExplodedNode *> errorNode;
738 for (
unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
752 if (
C.getASTContext().isObjCNSObjectType(ArgTy))
761 errorNode =
C.generateNonFatalErrorNode();
766 SmallString<128> sbuf;
767 llvm::raw_svector_ostream os(sbuf);
771 os <<
"Argument to '" <<
TypeName <<
"' method '";
773 os <<
"Argument to method '";
776 os <<
"' should be an Objective-C pointer type, not '";
777 ArgTy.
print(os,
C.getLangOpts());
780 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), *errorNode);
782 C.emitReport(std::move(R));
797 :
public Checker<check::PostStmt<ObjCForCollectionStmt>,
798 check::PostObjCMessage,
800 check::PointerEscape > {
801 mutable IdentifierInfo *CountSelectorII =
nullptr;
803 bool isCollectionCountMethod(
const ObjCMethodCall &M,
804 CheckerContext &
C)
const;
807 ObjCLoopChecker() =
default;
808 void checkPostStmt(
const ObjCForCollectionStmt *FCS, CheckerContext &
C)
const;
809 void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
810 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &
C)
const;
813 const CallEvent *
Call,
850 std::optional<DefinedSVal> KnownCollection =
852 if (!KnownCollection)
856 std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
857 if (StNil && !StNonNil) {
883 std::optional<Loc> ElementLoc;
884 if (
const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
886 assert(ElemDecl->
getInit() ==
nullptr);
887 ElementLoc = State->getLValue(ElemDecl, LCtx);
889 ElementLoc = State->getSVal(Element, LCtx).getAs<
Loc>();
896 SVal Val = State->getSVal(*ElementLoc);
904 SymbolRef CollectionS,
bool Assumption) {
905 if (!State || !CollectionS)
908 const SymbolRef *CountS = State->get<ContainerCountMap>(CollectionS);
910 const bool *KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
912 return State->set<ContainerNonEmptyMap>(CollectionS, Assumption);
913 return (Assumption == *KnownNonEmpty) ? State :
nullptr;
917 SVal CountGreaterThanZeroVal =
920 SvalBuilder.
makeIntVal(0, (*CountS)->getType()),
922 std::optional<DefinedSVal> CountGreaterThanZero =
924 if (!CountGreaterThanZero) {
930 return State->assume(*CountGreaterThanZero, Assumption);
952 return BE->getSrc()->getLoopTarget() == FCS;
964void ObjCLoopChecker::checkPostStmt(
const ObjCForCollectionStmt *FCS,
965 CheckerContext &
C)
const {
981 C.generateSink(
C.getState(),
C.getPredecessor());
982 else if (State !=
C.getState())
983 C.addTransition(State);
986bool ObjCLoopChecker::isCollectionCountMethod(
const ObjCMethodCall &M,
987 CheckerContext &
C)
const {
990 if (!CountSelectorII)
991 CountSelectorII = &
C.getASTContext().Idents.get(
"count");
998void ObjCLoopChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
999 CheckerContext &
C)
const {
1020 if (!isCollectionCountMethod(M,
C))
1024 SymbolRef CountS =
C.getSVal(MsgExpr).getAsSymbol();
1028 C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1029 State = State->set<ContainerCountMap>(ContainerS, CountS);
1031 if (
const bool *NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1032 State = State->remove<ContainerNonEmptyMap>(ContainerS);
1036 C.addTransition(State);
1054 StaticClass = Message->getOriginExpr()->getReceiverInterface();
1075 return Message->getReceiverSVal().getAsSymbol();
1081 const CallEvent *
Call,
1091 if (Sym == ImmutableReceiver)
1096 State = State->remove<ContainerCountMap>(Sym);
1097 State = State->remove<ContainerNonEmptyMap>(Sym);
1102void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1103 CheckerContext &
C)
const {
1107 ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1108 for (
SymbolRef Sym : llvm::make_first_range(Tracked)) {
1109 if (SymReaper.
isDead(Sym)) {
1110 State = State->remove<ContainerCountMap>(Sym);
1111 State = State->remove<ContainerNonEmptyMap>(Sym);
1115 C.addTransition(State);
1122class ObjCNonNilReturnValueChecker
1123 :
public Checker<check::PostObjCMessage,
1124 check::PostStmt<ObjCArrayLiteral>,
1125 check::PostStmt<ObjCDictionaryLiteral>,
1126 check::PostStmt<ObjCBoxedExpr> > {
1128 mutable Selector ObjectAtIndex;
1129 mutable Selector ObjectAtIndexedSubscript;
1130 mutable Selector NullSelector;
1133 ObjCNonNilReturnValueChecker() =
default;
1137 CheckerContext &
C)
const;
1138 void assumeExprIsNonNull(
const Expr *E, CheckerContext &
C)
const {
1139 C.addTransition(assumeExprIsNonNull(E,
C.getState(),
C));
1142 void checkPostStmt(
const ObjCArrayLiteral *E, CheckerContext &
C)
const {
1143 assumeExprIsNonNull(E,
C);
1145 void checkPostStmt(
const ObjCDictionaryLiteral *E, CheckerContext &
C)
const {
1146 assumeExprIsNonNull(E,
C);
1148 void checkPostStmt(
const ObjCBoxedExpr *E, CheckerContext &
C)
const {
1149 assumeExprIsNonNull(E,
C);
1152 void checkPostObjCMessage(
const ObjCMethodCall &M, CheckerContext &
C)
const;
1157ObjCNonNilReturnValueChecker::assumeExprIsNonNull(
const Expr *NonNullExpr,
1159 CheckerContext &
C)
const {
1160 SVal Val =
C.getSVal(NonNullExpr);
1161 if (std::optional<DefinedOrUnknownSVal> DV =
1162 Val.
getAs<DefinedOrUnknownSVal>())
1163 return State->assume(*DV,
true);
1167void ObjCNonNilReturnValueChecker::checkPostObjCMessage(
const ObjCMethodCall &M,
1173 ASTContext &Ctx =
C.getASTContext();
1175 ObjectAtIndexedSubscript =
GetUnarySelector(
"objectAtIndexedSubscript", Ctx);
1190 if (!
C.inTopFrame() && M.
getDecl() &&
1203 if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1217 C.addTransition(State);
1224void ento::registerNilArgChecker(CheckerManager &mgr) {
1228bool ento::shouldRegisterNilArgChecker(
const CheckerManager &mgr) {
1232void ento::registerCFNumberChecker(CheckerManager &mgr) {
1236bool ento::shouldRegisterCFNumberChecker(
const CheckerManager &mgr) {
1240void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
1244bool ento::shouldRegisterCFRetainReleaseChecker(
const CheckerManager &mgr) {
1248void ento::registerClassReleaseChecker(CheckerManager &mgr) {
1252bool ento::shouldRegisterClassReleaseChecker(
const CheckerManager &mgr) {
1256void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) {
1260bool ento::shouldRegisterVariadicMethodTypeChecker(
const CheckerManager &mgr) {
1264void ento::registerObjCLoopChecker(CheckerManager &mgr) {
1268bool ento::shouldRegisterObjCLoopChecker(
const CheckerManager &mgr) {
1272void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
1276bool 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 ...
static CanQualType getCanonicalType(QualType T)
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
const T * getAs() const
Member-template getAs<specific type>'.
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.
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.