45class PropertiesRewriter {
52 PropAction_RetainReplacedWithStrong,
53 PropAction_AssignRemoved,
54 PropAction_AssignRewritten,
55 PropAction_MaybeAddWeakOrUnsafe
64 : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
68 typedef std::map<SourceLocation, PropsTy> AtPropDeclsTy;
69 AtPropDeclsTy AtProps;
70 llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
74 : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
77 AtPropDeclsTy *PrevAtProps =
nullptr) {
78 for (
auto *Prop :
D->instance_properties()) {
83 if (PrevAtProps->find(
Loc) != PrevAtProps->end())
85 PropsTy &props = AtProps[
Loc];
86 props.push_back(Prop);
96 collectProperties(iface, AtProps);
100 collectProperties(Ext, AtProps);
104 for (prop_impl_iterator
105 I = prop_impl_iterator(
D->decls_begin()),
106 E = prop_impl_iterator(
D->decls_end()); I !=
E; ++I) {
116 AtPropDeclsTy::iterator findAtLoc = AtProps.find(propD->
getAtLoc());
117 if (findAtLoc == AtProps.end())
120 PropsTy &props = findAtLoc->second;
121 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I) {
122 if (I->PropD == propD) {
130 for (AtPropDeclsTy::iterator
131 I = AtProps.begin(),
E = AtProps.end(); I !=
E; ++I) {
133 PropsTy &props = I->second;
134 if (!getPropertyType(props)->isObjCRetainableType())
136 if (hasIvarWithExplicitARCOwnership(props))
140 rewriteProperty(props, atLoc);
145 void doPropAction(PropActionKind kind,
147 bool markAction =
true) {
149 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I)
150 ActionOnProp[I->PropD->getIdentifier()] =
kind;
153 case PropAction_None:
155 case PropAction_RetainReplacedWithStrong: {
156 StringRef toAttr =
"strong";
160 case PropAction_AssignRemoved:
161 return removeAssignForDefaultStrong(props, atLoc);
162 case PropAction_AssignRewritten:
163 return rewriteAssign(props, atLoc);
164 case PropAction_MaybeAddWeakOrUnsafe:
165 return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
180 return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
183 bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
186 if (HasIvarAssignedAPlusOneObject)
187 return doPropAction(PropAction_AssignRemoved, props, atLoc);
188 return doPropAction(PropAction_AssignRewritten, props, atLoc);
191 if (HasIvarAssignedAPlusOneObject ||
195 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
198 void removeAssignForDefaultStrong(PropsTy &props,
200 removeAttribute(
"retain", atLoc);
201 if (!removeAttribute(
"assign", atLoc))
204 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I) {
207 diag::err_arc_assign_property_ownership,
208 diag::err_arc_inconsistent_property_ownership,
209 I->IvarD->getLocation());
216 const char *toWhich =
217 (Pass.
isGCMigration() && !hasGCWeak(props, atLoc)) ?
"strong" :
218 (canUseWeak ?
"weak" :
"unsafe_unretained");
220 bool rewroteAttr = rewriteAttribute(
"assign", toWhich, atLoc);
224 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I) {
225 if (isUserDeclared(I->IvarD)) {
228 const char *toWhich =
229 (Pass.
isGCMigration() && !hasGCWeak(props, atLoc)) ?
"__strong " :
230 (canUseWeak ?
"__weak " :
"__unsafe_unretained ");
231 Pass.
TA.
insert(I->IvarD->getLocation(), toWhich);
236 diag::err_arc_assign_property_ownership,
237 diag::err_arc_inconsistent_property_ownership,
238 I->IvarD->getLocation());
242 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
247 bool addedAttr = addAttribute(canUseWeak ?
"weak" :
"unsafe_unretained",
252 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I) {
253 if (isUserDeclared(I->IvarD)) {
256 Pass.
TA.
insert(I->IvarD->getLocation(),
257 canUseWeak ?
"__weak " :
"__unsafe_unretained ");
261 diag::err_arc_assign_property_ownership,
262 diag::err_arc_inconsistent_property_ownership,
263 I->IvarD->getLocation());
265 diag::err_arc_objc_property_default_assign_on_object,
266 I->ImplD->getLocation());
271 bool removeAttribute(StringRef fromAttr,
SourceLocation atLoc)
const {
275 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
290 if (
E->getOpcode() != BO_Assign)
295 if (RE->getDecl() != Ivar)
306 bool hasIvarAssignedAPlusOneObject(PropsTy &props)
const {
307 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I) {
308 PlusOneAssign oneAssign(I->IvarD);
309 bool notFound = oneAssign.TraverseDecl(CurImplD);
317 bool hasIvarWithExplicitARCOwnership(PropsTy &props)
const {
321 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I) {
322 if (isUserDeclared(I->IvarD)) {
323 if (isa<AttributedType>(I->IvarD->getType()))
325 if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
347 QualType getPropertyType(PropsTy &props)
const {
348 assert(!props.empty());
349 QualType ty = props[0].PropD->getType().getUnqualifiedType();
352 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I)
353 assert(ty == I->PropD->getType().getUnqualifiedType());
360 assert(!props.empty());
362 props[0].PropD->getPropertyAttributesAsWritten();
365 for (PropsTy::iterator I = props.begin(),
E = props.end(); I !=
E; ++I)
366 assert(attrs == I->PropD->getPropertyAttributesAsWritten());
Defines the SourceManager interface.
A builtin binary operation expression such as "x + y" or "x <= y".
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
bool isInvalidDecl() const
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
ObjCContainerDecl - Represents a container for method declarations.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
visible_extensions_range visible_extensions() const
ObjCIvarDecl - Represents an ObjC instance variable.
bool getSynthesize() const
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Represents one property declaration in an Objective-C interface.
SourceLocation getAtLoc() const
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
ObjCIvarDecl * getPropertyIvarDecl() const
Kind getPropertyImplementation() const
ObjCPropertyDecl * getPropertyDecl() const
A (possibly-)qualified type.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Encodes a location in the source.
bool isGCMigration() const
bool addPropertyAttribute(StringRef attr, SourceLocation atLoc)
bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc)
llvm::DenseSet< SourceLocation > AtPropsWeak
Set of raw '@' locations for 'assign' properties group that contain GC __weak.
bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, SourceLocation atLoc)
MigrationContext & getMigrationContext()
ObjCImplementationDecl * getImplementationDecl()
void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override
bool canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass=false)
Determine whether we can add weak to the given type.
bool isPlusOneAssign(const BinaryOperator *E)
unsigned kind
All of the diagnostics that can be emitted by the frontend.
The JSON file list parser is used to communicate input to InstallAPI.