35class NonnullGlobalConstantsChecker :
public Checker<check::Location> {
36 mutable IdentifierInfo *NSStringII =
nullptr;
37 mutable IdentifierInfo *CFStringRefII =
nullptr;
38 mutable IdentifierInfo *CFBooleanRefII =
nullptr;
39 mutable IdentifierInfo *CFNullRefII =
nullptr;
42 NonnullGlobalConstantsChecker() {}
44 void checkLocation(SVal l,
bool isLoad,
const Stmt *S,
45 CheckerContext &
C)
const;
48 void initIdentifierInfo(ASTContext &Ctx)
const;
50 bool isGlobalConstString(SVal
V)
const;
52 bool isNonnullType(QualType Ty)
const;
58void NonnullGlobalConstantsChecker::initIdentifierInfo(
ASTContext &Ctx)
const {
63 CFStringRefII = &Ctx.
Idents.
get(
"CFStringRef");
64 CFBooleanRefII = &Ctx.
Idents.
get(
"CFBooleanRef");
65 CFNullRefII = &Ctx.
Idents.
get(
"CFNullRef");
69void NonnullGlobalConstantsChecker::checkLocation(SVal location,
bool isLoad,
71 CheckerContext &
C)
const {
72 initIdentifierInfo(
C.getASTContext());
73 if (!isLoad || !location.
isValid())
78 if (isGlobalConstString(location)) {
79 SVal
V = State->getSVal(location.
castAs<Loc>());
80 std::optional<DefinedOrUnknownSVal> Constr =
81 V.getAs<DefinedOrUnknownSVal>();
87 C.addTransition(OutputState);
94bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal
V)
const {
95 std::optional<loc::MemRegionVal> RegionVal =
V.getAs<loc::MemRegionVal>();
98 auto *Region = dyn_cast<VarRegion>(RegionVal->getAsRegion());
101 const VarDecl *
Decl = Region->getDecl();
103 if (!
Decl->hasGlobalStorage())
106 QualType Ty =
Decl->getType();
108 if (isNonnullType(Ty) && HasConst)
113 if (
const auto *AT = dyn_cast<AttributedType>(
T)) {
114 if (AT->getAttrKind() == attr::TypeNonNull)
116 Ty = AT->getModifiedType();
117 }
else if (
const auto *TT = dyn_cast<TypedefType>(
T)) {
118 Ty = TT->getDecl()->getUnderlyingType();
122 if (isNonnullType(Ty) && HasConst)
132bool NonnullGlobalConstantsChecker::isNonnullType(QualType Ty)
const {
137 if (
auto *
T = dyn_cast<ObjCObjectPointerType>(Ty)) {
138 return T->getInterfaceDecl() &&
139 T->getInterfaceDecl()->getIdentifier() == NSStringII;
140 }
else if (
auto *
T = Ty->
getAs<TypedefType>()) {
141 IdentifierInfo* II =
T->getDecl()->getIdentifier();
142 return II == CFStringRefII || II == CFBooleanRefII || II == CFNullRefII;
147void ento::registerNonnullGlobalConstantsChecker(CheckerManager &Mgr) {
151bool ento::shouldRegisterNonnullGlobalConstantsChecker(
const CheckerManager &mgr) {
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
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.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
@ Type
The name was classified as a type.