20#include "llvm/Support/Casting.h"
28class RawPtrRefMemberChecker
29 :
public Checker<check::ASTDecl<TranslationUnitDecl>> {
32 mutable BugReporter *BR;
33 mutable llvm::DenseSet<const ObjCIvarDecl *> IvarDeclsToIgnore;
36 const std::unique_ptr<PtrRefSafetyModel> Model;
39 RawPtrRefMemberChecker(
const char *description,
40 std::unique_ptr<PtrRefSafetyModel> Model)
41 : Bug(this, description,
"WebKit coding guidelines"),
42 Model(std::move(Model)) {}
44 std::optional<bool> isUnsafePtr(QualType QT,
bool IgnoreARC =
false)
const {
48 void checkASTDecl(
const TranslationUnitDecl *TUD, AnalysisManager &MGR,
49 BugReporter &BRArg)
const {
56 const RawPtrRefMemberChecker *Checker;
57 explicit LocalVisitor(
const RawPtrRefMemberChecker *Checker)
60 ShouldVisitTemplateInstantiations =
true;
61 ShouldVisitImplicitCode =
false;
64 bool VisitTypedefDecl(
const TypedefDecl *TD)
override {
65 if (
auto *RTC = Checker->Model->retainTypeChecker())
66 RTC->visitTypedef(TD);
70 bool VisitRecordDecl(
const RecordDecl *RD)
override {
71 Checker->visitRecordDecl(RD);
75 bool VisitObjCContainerDecl(
const ObjCContainerDecl *CD)
override {
76 Checker->visitObjCDecl(CD);
81 LocalVisitor visitor(
this);
82 if (
auto *RTC = Model->retainTypeChecker())
83 RTC->visitTranslationUnitDecl(TUD);
84 visitor.TraverseDecl(TUD);
87 void visitRecordDecl(
const RecordDecl *RD)
const {
88 if (shouldSkipDecl(RD))
95 void visitMember(
const FieldDecl *
Member,
const RecordDecl *RD)
const {
96 auto QT =
Member->getType();
97 const Type *MemberType = QT.getTypePtrOrNull();
100 auto IsUnsafePtr = isUnsafePtr(QT);
101 if (IsUnsafePtr && *IsUnsafePtr)
106 MemberType = QT.getTypePtrOrNull();
113 reportBug(
Member, MemberType, MemberCXXRD, RD);
115 reportBug(
Member, MemberType, ObjCDecl, RD);
118 void visitObjCDecl(
const ObjCContainerDecl *CD)
const {
119 if (BR->getSourceManager().isInSystemHeader(CD->
getLocation()))
122 if (
auto *ID = dyn_cast<ObjCImplementationDecl>(CD)) {
126 visitObjCPropertyDecl(CD, it.second);
130 visitIvarDecl(CD, Ivar);
132 for (
auto *PropImpl :
ID->property_impls())
133 visitPropImpl(CD, PropImpl);
134 for (
auto *Ivar :
ID->ivars())
135 visitIvarDecl(CD, Ivar);
140 void visitIvarDecl(
const ObjCContainerDecl *CD,
141 const ObjCIvarDecl *Ivar)
const {
142 if (BR->getSourceManager().isInSystemHeader(Ivar->
getLocation()))
145 if (IvarDeclsToIgnore.contains(Ivar))
153 auto IsUnsafePtr = isUnsafePtr(QT);
154 if (!IsUnsafePtr || !*IsUnsafePtr)
157 IvarDeclsToIgnore.insert(Ivar);
160 reportBug(Ivar, IvarType, MemberCXXRD, CD);
162 reportBug(Ivar, IvarType, ObjCDecl, CD);
165 void visitObjCPropertyDecl(
const ObjCContainerDecl *CD,
166 const ObjCPropertyDecl *PD)
const {
167 if (BR->getSourceManager().isInSystemHeader(PD->
getLocation()))
170 if (
const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CD)) {
171 auto *RTC = Model->retainTypeChecker();
172 if (!RTC || !RTC->defaultSynthProperties() ||
173 ID->isObjCRequiresPropertyDefs())
177 auto [IsUnsafe, PropType] = isPropImplUnsafePtr(PD);
181 if (
auto *MemberCXXRD = PropType->getPointeeCXXRecordDecl())
182 reportBug(PD, PropType, MemberCXXRD, CD);
184 reportBug(PD, PropType, ObjCDecl, CD);
187 void visitPropImpl(
const ObjCContainerDecl *CD,
188 const ObjCPropertyImplDecl *PID)
const {
189 if (BR->getSourceManager().isInSystemHeader(PID->
getLocation()))
197 if (IvarDeclsToIgnore.contains(IvarDecl))
199 IvarDeclsToIgnore.insert(IvarDecl);
201 auto [IsUnsafe, PropType] = isPropImplUnsafePtr(PropDecl);
205 if (
auto *MemberCXXRD = PropType->getPointeeCXXRecordDecl())
206 reportBug(PropDecl, PropType, MemberCXXRD, CD);
208 reportBug(PropDecl, PropType, ObjCDecl, CD);
211 std::pair<bool, const Type *>
212 isPropImplUnsafePtr(
const ObjCPropertyDecl *PD)
const {
214 return {
false,
nullptr};
219 return {
false,
nullptr};
227 auto IsUnsafePtr = isUnsafePtr(QT, ignoreARC);
228 return {IsUnsafePtr && *IsUnsafePtr && !HasSafeAttr, PropType};
231 bool shouldSkipDecl(
const RecordDecl *RD)
const {
244 if (!RDLocation.isValid())
248 if (Kind != TagTypeKind::Struct && Kind != TagTypeKind::Class &&
249 Kind != TagTypeKind::Union)
253 if (BR->getSourceManager().isInSystemHeader(RDLocation))
258 auto CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(RD);
265 template <
typename DeclType,
typename Po
inteeType,
typename ParentDeclType>
266 void reportBug(
const DeclType *
Member,
const Type *MemberType,
267 const PointeeType *Pointee,
268 const ParentDeclType *ClassCXXRD)
const {
273 SmallString<100> Buf;
274 llvm::raw_svector_ostream Os(Buf);
280 Os <<
"Instance variable ";
282 Os <<
"Member variable ";
287 if (
Member->getType().getTypePtrOrNull() == MemberType)
290 Os <<
" contains a ";
291 if (printPointer(Os, MemberType) == PrintDeclKind::Pointer) {
298 PathDiagnosticLocation BSLoc(
Member->getSourceRange().getBegin(),
299 BR->getSourceManager());
300 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str(), BSLoc);
302 BR->emitReport(std::move(
Report));
305 enum class PrintDeclKind { Pointee,
Pointer };
306 PrintDeclKind printPointer(llvm::raw_svector_ostream &Os,
307 const Type *
T)
const {
311 T->
getAs<TypedefType>()) {
312 Os << Model->typeName() <<
" ";
313 return PrintDeclKind::Pointer;
317 Os << (IsPtr ?
"raw pointer" :
"reference") <<
" to " << Model->typeName()
319 return PrintDeclKind::Pointee;
323class NoUncountedMemberChecker final :
public RawPtrRefMemberChecker {
325 NoUncountedMemberChecker()
326 : RawPtrRefMemberChecker(
"Member variable is a raw-pointer/reference to "
327 "reference-countable type",
331class NoUncheckedPtrMemberChecker final :
public RawPtrRefMemberChecker {
333 NoUncheckedPtrMemberChecker()
334 : RawPtrRefMemberChecker(
"Member variable is a raw-pointer/reference to "
335 "checked-pointer capable type",
339class NoUnretainedMemberChecker final :
public RawPtrRefMemberChecker {
341 NoUnretainedMemberChecker()
342 : RawPtrRefMemberChecker(
"Member variable is a raw-pointer/reference to "
353bool ento::shouldRegisterNoUncountedMemberChecker(
const CheckerManager &Mgr) {
357void ento::registerNoUncheckedPtrMemberChecker(
CheckerManager &Mgr) {
361bool ento::shouldRegisterNoUncheckedPtrMemberChecker(
366void ento::registerNoUnretainedMemberChecker(
CheckerManager &Mgr) {
370bool ento::shouldRegisterNoUnretainedMemberChecker(
const CheckerManager &Mgr) {
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
llvm::MapVector< std::pair< IdentifierInfo *, unsigned >, ObjCPropertyDecl * > PropertyMap
virtual void collectPropertiesToImplement(PropertyMap &PM) const
This routine collects list of properties to be implemented in the class.
bool isRetaining() const
isRetaining - Return true if the property retains its value.
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
SetterKind getSetterKind() const
getSetterKind - Return the method used for doing assignment in the property setter.
ObjCPropertyAttribute::Kind getPropertyAttributes() const
ObjCIvarDecl * getPropertyIvarDecl() const
Kind getPropertyImplementation() const
ObjCPropertyDecl * getPropertyDecl() const
const Type * getTypePtrOrNull() const
bool isLambda() const
Determine whether this record is a class describing a lambda function object.
field_range fields() const
bool isThisDeclarationADefinition() const
Return true if this declaration is a completion definition of the type.
TagKind getTagKind() const
bool isPointerType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
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>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
std::unique_ptr< PtrRefSafetyModel > makeCheckedPtrSafetyModel()
void printQuotedQualifiedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
void printQuotedName(llvm::raw_ostream &Os, const NamedDeclDerivedT &D)
DynamicRecursiveASTVisitorBase< true > ConstDynamicRecursiveASTVisitor
std::optional< bool > isUnsafePtrForStorage(const PtrRefSafetyModel &Model, QualType T, bool IgnoreARC=false)
Applies the memory-management exemptions that hold for a variable, member, or lambda capture (but not...
const FunctionProtoType * T
@ Type
The name was classified as a type.
bool isSmartPtr(const CXXRecordDecl *R)
ObjCInterfaceDecl * getObjCDeclFromObjCPtr(const Type *TypePtr)
std::unique_ptr< PtrRefSafetyModel > makeRefPtrSafetyModel()
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
std::unique_ptr< PtrRefSafetyModel > makeRetainPtrSafetyModel()