#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Analysis/SelectorExtras.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
usingnamespaceclang;
usingnamespaceento;
usingnamespacellvm;
namespace {
class APIMisuse : public BugType { … };
}
static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) { … }
enum FoundationClass { … };
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID,
bool IncludeSuperclasses = true) { … }
namespace {
class NilArgChecker : public Checker<check::PreObjCMessage,
check::PostStmt<ObjCDictionaryLiteral>,
check::PostStmt<ObjCArrayLiteral>,
EventDispatcher<ImplicitNullDerefEvent>> { … };
}
void NilArgChecker::warnIfNilExpr(const Expr *E,
const char *Msg,
CheckerContext &C) const { … }
void NilArgChecker::warnIfNilArg(CheckerContext &C,
const ObjCMethodCall &msg,
unsigned int Arg,
FoundationClass Class,
bool CanBeSubscript) const { … }
void NilArgChecker::generateBugReport(ExplodedNode *N,
StringRef Msg,
SourceRange Range,
const Expr *E,
CheckerContext &C) const { … }
void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const { … }
void NilArgChecker::checkPostStmt(const ObjCArrayLiteral *AL,
CheckerContext &C) const { … }
void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
CheckerContext &C) const { … }
namespace {
class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > { … };
}
enum CFNumberType { … };
static std::optional<uint64_t> GetCFNumberSize(ASTContext &Ctx, uint64_t i) { … }
#if 0
static const char* GetCFNumberTypeStr(uint64_t i) {
static const char* Names[] = {
"kCFNumberSInt8Type",
"kCFNumberSInt16Type",
"kCFNumberSInt32Type",
"kCFNumberSInt64Type",
"kCFNumberFloat32Type",
"kCFNumberFloat64Type",
"kCFNumberCharType",
"kCFNumberShortType",
"kCFNumberIntType",
"kCFNumberLongType",
"kCFNumberLongLongType",
"kCFNumberFloatType",
"kCFNumberDoubleType",
"kCFNumberCFIndexType",
"kCFNumberNSIntegerType",
"kCFNumberCGFloatType"
};
return i <= kCFNumberCGFloatType ? Names[i-1] : "Invalid CFNumberType";
}
#endif
void CFNumberChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const { … }
namespace {
class CFRetainReleaseChecker : public Checker<check::PreCall> { … };
}
void CFRetainReleaseChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const { … }
namespace {
class ClassReleaseChecker : public Checker<check::PreObjCMessage> { … };
}
void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const { … }
namespace {
class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> { … };
}
bool
VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const { … }
void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const { … }
REGISTER_MAP_WITH_PROGRAMSTATE(…)
REGISTER_MAP_WITH_PROGRAMSTATE(…) …
namespace {
class ObjCLoopChecker
: public Checker<check::PostStmt<ObjCForCollectionStmt>,
check::PostObjCMessage,
check::DeadSymbols,
check::PointerEscape > { … };
}
static bool isKnownNonNilCollectionType(QualType T) { … }
static ProgramStateRef checkCollectionNonNil(CheckerContext &C,
ProgramStateRef State,
const ObjCForCollectionStmt *FCS) { … }
static ProgramStateRef checkElementNonNil(CheckerContext &C,
ProgramStateRef State,
const ObjCForCollectionStmt *FCS) { … }
static ProgramStateRef
assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
SymbolRef CollectionS, bool Assumption) { … }
static ProgramStateRef
assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
const ObjCForCollectionStmt *FCS,
bool Assumption) { … }
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
const ObjCForCollectionStmt *FCS) { … }
void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
CheckerContext &C) const { … }
bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
CheckerContext &C) const { … }
void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
CheckerContext &C) const { … }
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call) { … }
ProgramStateRef
ObjCLoopChecker::checkPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind) const { … }
void ObjCLoopChecker::checkDeadSymbols(SymbolReaper &SymReaper,
CheckerContext &C) const { … }
namespace {
class ObjCNonNilReturnValueChecker
: public Checker<check::PostObjCMessage,
check::PostStmt<ObjCArrayLiteral>,
check::PostStmt<ObjCDictionaryLiteral>,
check::PostStmt<ObjCBoxedExpr> > { … };
}
ProgramStateRef
ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr,
ProgramStateRef State,
CheckerContext &C) const { … }
void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
CheckerContext &C)
const { … }
void ento::registerNilArgChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterNilArgChecker(const CheckerManager &mgr) { … }
void ento::registerCFNumberChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterCFNumberChecker(const CheckerManager &mgr) { … }
void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterCFRetainReleaseChecker(const CheckerManager &mgr) { … }
void ento::registerClassReleaseChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterClassReleaseChecker(const CheckerManager &mgr) { … }
void ento::registerVariadicMethodTypeChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterVariadicMethodTypeChecker(const CheckerManager &mgr) { … }
void ento::registerObjCLoopChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterObjCLoopChecker(const CheckerManager &mgr) { … }
void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) { … }
bool ento::shouldRegisterObjCNonNilReturnValueChecker(const CheckerManager &mgr) { … }