};
static const ObjCIvarDecl *findPropertyBackingIvar(const ObjCPropertyDecl *PD,
- ObjCInterfaceDecl *InterD,
- ASTContext &Ctx) {
+ const ObjCInterfaceDecl *InterD,
+ ASTContext &Ctx) {
// Check for synthesized ivars.
ObjCIvarDecl *ID = PD->getPropertyIvarDecl();
if (ID)
return ID;
+ ObjCInterfaceDecl *NonConstInterD = const_cast<ObjCInterfaceDecl*>(InterD);
+
// Check for existing "_PropName".
- ID = InterD->lookupInstanceVariable(PD->getDefaultSynthIvarName(Ctx));
+ ID = NonConstInterD->lookupInstanceVariable(PD->getDefaultSynthIvarName(Ctx));
if (ID)
return ID;
// Check for existing "PropName".
IdentifierInfo *PropIdent = PD->getIdentifier();
- ID = InterD->lookupInstanceVariable(PropIdent);
+ ID = NonConstInterD->lookupInstanceVariable(PropIdent);
return ID;
}
ObjCPropertyDecl *PD = *I;
// Find the corresponding IVar.
- const ObjCIvarDecl *ID = findPropertyBackingIvar(PD,
- const_cast<ObjCInterfaceDecl*>(InterD),
- Mgr.getASTContext());
+ const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterD,
+ Mgr.getASTContext());
if (!ID)
continue;
ObjCMethodDecl *M = *I;
AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M);
+ // Skip the init, dealloc functions and any functions that might be doing
+ // initialization based on their name.
if (M->getMethodFamily() == OMF_init ||
M->getMethodFamily() == OMF_dealloc ||
- M->getSelector().getAsString().find("init") != StringRef::npos ||
- M->getSelector().getAsString().find("Init") != StringRef::npos)
+ M->getSelector().getNameForSlot(0).find("init") != StringRef::npos ||
+ M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos)
continue;
const Stmt *Body = M->getBody();
- if (!Body)
- continue;
+ assert(Body);
MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, DCtx);
MC.VisitStmt(Body);
if (!BO->isAssignmentOp())
return;
- const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(BO->getLHS());
+ const ObjCIvarRefExpr *IvarRef =
+ dyn_cast<ObjCIvarRefExpr>(BO->getLHS()->IgnoreParenCasts());
if (!IvarRef)
return;
if (GetterMethod && GetterMethod->getCanonicalDecl() == MD)
return;
-
- PathDiagnosticLocation IvarRefLocation =
- PathDiagnosticLocation::createBegin(IvarRef,
- BR.getSourceManager(), DCtx);
-
BR.EmitBasicReport(MD,
"Property access",
categories::CoreFoundationObjectiveC,
"Direct assignment to an instance variable backing a property; "
- "use the setter instead", IvarRefLocation);
+ "use the setter instead", PathDiagnosticLocation(IvarRef,
+ BR.getSourceManager(),
+ DCtx));
}
}
}
@property (assign, nonatomic) MyClass* Y; // automatically synthesized, implemented
- @property (assign, nonatomic) MyClass* Z; // non synthesized, implemented
+ @property (assign, nonatomic) MyClass* Z; // non synthesized ivar, implemented setter
@property (readonly) id nonSynth; // non synthesized, explicitly implemented to return ivar with expected name
- (id) initWithPtr:(MyClass*) value;
}
- (void) someMethod: (MyClass*)In {
- __A = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
+ (__A) = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
_X = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
_Y = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}
_Z = In; // expected-warning {{Direct assignment to an instance variable backing a property; use the setter instead}}