40 using namespace clang;
41 using namespace arcmt;
42 using namespace trans;
46 class PropertiesRewriter {
53 PropAction_RetainReplacedWithStrong,
54 PropAction_AssignRemoved,
55 PropAction_AssignRewritten,
56 PropAction_MaybeAddWeakOrUnsafe
65 : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
69 typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
70 AtPropDeclsTy AtProps;
71 llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
75 : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
78 AtPropDeclsTy *PrevAtProps =
nullptr) {
80 if (Prop->getAtLoc().isInvalid())
82 unsigned RawLoc = Prop->getAtLoc().getRawEncoding();
84 if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
86 PropsTy &props = AtProps[RawLoc];
87 props.push_back(Prop);
97 collectProperties(iface, AtProps);
101 for (prop_impl_iterator
103 E = prop_impl_iterator(D->
decls_end()); I != E; ++I) {
114 AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
115 if (findAtLoc == AtProps.end())
118 PropsTy &props = findAtLoc->second;
119 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
120 if (I->PropD == propD) {
128 for (AtPropDeclsTy::iterator
129 I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
131 PropsTy &props = I->second;
132 if (!getPropertyType(props)->isObjCRetainableType())
134 if (hasIvarWithExplicitARCOwnership(props))
138 rewriteProperty(props, atLoc);
141 AtPropDeclsTy AtExtProps;
144 collectProperties(Ext, AtExtProps, &AtProps);
146 for (AtPropDeclsTy::iterator
147 I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
149 PropsTy &props = I->second;
151 doActionForExtensionProp(props, atLoc);
156 void doPropAction(PropActionKind
kind,
158 bool markAction =
true) {
160 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
161 ActionOnProp[I->PropD->getIdentifier()] =
kind;
164 case PropAction_None:
166 case PropAction_RetainReplacedWithStrong: {
167 StringRef toAttr =
"strong";
168 MigrateCtx.rewritePropertyAttribute(
"retain", toAttr, atLoc);
171 case PropAction_AssignRemoved:
172 return removeAssignForDefaultStrong(props, atLoc);
173 case PropAction_AssignRewritten:
174 return rewriteAssign(props, atLoc);
175 case PropAction_MaybeAddWeakOrUnsafe:
176 return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
180 void doActionForExtensionProp(PropsTy &props,
SourceLocation atLoc) {
181 llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
182 I = ActionOnProp.find(props[0].PropD->getIdentifier());
183 if (I == ActionOnProp.end())
186 doPropAction(I->second, props, atLoc,
false);
200 return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
203 bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
206 if (HasIvarAssignedAPlusOneObject)
207 return doPropAction(PropAction_AssignRemoved, props, atLoc);
208 return doPropAction(PropAction_AssignRewritten, props, atLoc);
211 if (HasIvarAssignedAPlusOneObject ||
212 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
215 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
218 void removeAssignForDefaultStrong(PropsTy &props,
220 removeAttribute(
"retain", atLoc);
221 if (!removeAttribute(
"assign", atLoc))
224 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
226 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
227 diag::err_arc_assign_property_ownership,
228 diag::err_arc_inconsistent_property_ownership,
229 I->IvarD->getLocation());
234 bool canUseWeak =
canApplyWeak(Pass.Ctx, getPropertyType(props),
235 Pass.isGCMigration());
236 const char *toWhich =
237 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ?
"strong" :
238 (canUseWeak ?
"weak" :
"unsafe_unretained");
240 bool rewroteAttr = rewriteAttribute(
"assign", toWhich, atLoc);
244 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
245 if (isUserDeclared(I->IvarD)) {
248 const char *toWhich =
249 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ?
"__strong " :
250 (canUseWeak ?
"__weak " :
"__unsafe_unretained ");
251 Pass.TA.insert(I->IvarD->getLocation(), toWhich);
255 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
256 diag::err_arc_assign_property_ownership,
257 diag::err_arc_inconsistent_property_ownership,
258 I->IvarD->getLocation());
262 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
264 bool canUseWeak =
canApplyWeak(Pass.Ctx, getPropertyType(props),
265 Pass.isGCMigration());
267 bool addedAttr = addAttribute(canUseWeak ?
"weak" :
"unsafe_unretained",
272 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
273 if (isUserDeclared(I->IvarD)) {
276 Pass.TA.insert(I->IvarD->getLocation(),
277 canUseWeak ?
"__weak " :
"__unsafe_unretained ");
280 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
281 diag::err_arc_assign_property_ownership,
282 diag::err_arc_inconsistent_property_ownership,
283 I->IvarD->getLocation());
284 Pass.TA.clearDiagnostic(
285 diag::err_arc_objc_property_default_assign_on_object,
286 I->ImplD->getLocation());
291 bool removeAttribute(StringRef fromAttr,
SourceLocation atLoc)
const {
292 return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
295 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
297 return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
301 return MigrateCtx.addPropertyAttribute(attr, atLoc);
312 if (RE->getDecl() != Ivar)
323 bool hasIvarAssignedAPlusOneObject(PropsTy &props)
const {
324 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
325 PlusOneAssign oneAssign(I->IvarD);
326 bool notFound = oneAssign.TraverseDecl(CurImplD);
334 bool hasIvarWithExplicitARCOwnership(PropsTy &props)
const {
335 if (Pass.isGCMigration())
338 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
339 if (isUserDeclared(I->IvarD)) {
340 if (isa<AttributedType>(I->IvarD->getType()))
342 if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
353 if (!Pass.isGCMigration())
364 QualType getPropertyType(PropsTy &props)
const {
365 assert(!props.empty());
366 QualType ty = props[0].PropD->getType().getUnqualifiedType();
369 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
370 assert(ty == I->PropD->getType().getUnqualifiedType());
377 getPropertyAttrs(PropsTy &props)
const {
378 assert(!props.empty());
380 attrs = props[0].PropD->getPropertyAttributesAsWritten();
383 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
384 assert(attrs == I->PropD->getPropertyAttributesAsWritten());
Defines the SourceManager interface.
MigrationContext & getMigrationContext()
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override
decl_iterator decls_end() const
Kind getPropertyImplementation() const
static SourceLocation getFromRawEncoding(unsigned Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
A builtin binary operation expression such as "x + y" or "x <= y".
A class that does preorder depth-first traversal on the entire Clang AST and visits each node...
Represents an ObjC class declaration.
bool isPlusOneAssign(const BinaryOperator *E)
decl_iterator decls_begin() const
SourceLocation getAtLoc() const
ObjCIvarDecl * getPropertyIvarDecl() const
ObjCImplementationDecl * getImplementationDecl()
bool canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass=false)
Determine whether we can add weak to the given type.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
bool getSynthesize() const
const ObjCInterfaceDecl * getClassInterface() const
Represents one property declaration in an Objective-C interface.
prop_range properties() const
bool isInvalidDecl() const
Expr * IgnoreParenImpCasts() LLVM_READONLY
ObjCIvarRefExpr - A reference to an ObjC instance variable.
ObjCPropertyDecl * getPropertyDecl() const
Reading or writing from this object requires a barrier call.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
visible_extensions_range visible_extensions() const