30#include "llvm/ADT/DenseMap.h"
51class DirectIvarAssignment :
52 public Checker<check::ASTDecl<ObjCImplementationDecl> > {
54 typedef llvm::DenseMap<
const ObjCIvarDecl*,
55 const ObjCPropertyDecl*> IvarToPropertyMapTy;
59 class MethodCrawler :
public ConstStmtVisitor<MethodCrawler> {
60 const IvarToPropertyMapTy &IvarToPropMap;
61 const ObjCMethodDecl *MD;
62 const ObjCInterfaceDecl *InterfD;
64 const CheckerBase *Checker;
68 MethodCrawler(
const IvarToPropertyMapTy &InMap,
const ObjCMethodDecl *InMD,
69 const ObjCInterfaceDecl *InID, BugReporter &InBR,
70 const CheckerBase *Checker, AnalysisDeclContext *InDCtx)
71 : IvarToPropMap(InMap), MD(InMD), InterfD(InID), BR(InBR),
72 Checker(Checker), DCtx(InDCtx) {}
74 void VisitStmt(
const Stmt *S) { VisitChildren(S); }
76 void VisitBinaryOperator(
const BinaryOperator *BO);
78 void VisitChildren(
const Stmt *S) {
79 for (
const Stmt *Child : S->
children())
86 bool (*ShouldSkipMethod)(
const ObjCMethodDecl *);
88 DirectIvarAssignment() : ShouldSkipMethod(&DefaultMethodFilter) {}
90 void checkASTDecl(
const ObjCImplementationDecl *D, AnalysisManager& Mgr,
91 BugReporter &BR)
const;
122 IvarToPropertyMapTy IvarToPropMap;
127 const ObjCIvarDecl *
ID = findPropertyBackingIvar(PD, InterD,
134 IvarToPropMap[
ID] = PD;
137 if (IvarToPropMap.empty())
143 if ((*ShouldSkipMethod)(M))
146 const Stmt *Body = M->
getBody();
157static bool isAnnotatedToAllowDirectAssignment(
const Decl *D) {
159 if (Ann->getAnnotation() ==
160 "objc_allow_direct_instance_variable_assignment")
165void DirectIvarAssignment::MethodCrawler::VisitBinaryOperator(
166 const BinaryOperator *BO) {
170 const ObjCIvarRefExpr *IvarRef =
176 if (
const ObjCIvarDecl *D = IvarRef->
getDecl()) {
177 IvarToPropertyMapTy::const_iterator I = IvarToPropMap.find(D);
179 if (I != IvarToPropMap.end()) {
180 const ObjCPropertyDecl *PD = I->second;
185 if (isAnnotatedToAllowDirectAssignment(PD) ||
186 isAnnotatedToAllowDirectAssignment(D))
189 ObjCMethodDecl *GetterMethod =
191 ObjCMethodDecl *SetterMethod =
202 "Direct assignment to an instance variable backing a property; "
203 "use the setter instead",
214 if (Ann->getAnnotation() ==
"objc_no_direct_instance_variable_assignment")
221void ento::registerDirectIvarAssignment(CheckerManager &mgr) {
224 "AnnotatedFunctions"))
228bool ento::shouldRegisterDirectIvarAssignment(
const CheckerManager &mgr) {
static bool AttrFilter(const ObjCMethodDecl *M)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static bool isAssignmentOp(Opcode Opc)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
One of these records is kept for each identifier that is lexed.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
instmeth_range instance_methods() const
instprop_range instance_properties() const
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
const ObjCInterfaceDecl * getClassInterface() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCMethodDecl - Represents an instance or class method declaration.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isSynthesizedAccessorStub() const
Selector getSelector() const
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Represents one property declaration in an Objective-C interface.
ObjCIvarDecl * getPropertyIvarDecl() const
Selector getSetterName() const
Selector getGetterName() const
IdentifierInfo * getDefaultSynthIvarName(ASTContext &Ctx) const
Get the default name of the synthesized ivar.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
ASTContext & getASTContext() override
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerFrontend *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})
const AnalyzerOptions & getAnalyzerOptions() const
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.
const char *const CoreFoundationObjectiveC
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
The JSON file list parser is used to communicate input to InstallAPI.