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 collectProperties(Ext, AtProps);
105 for (prop_impl_iterator
112 if (!propD || propD->isInvalidDecl())
115 if (!ivarD || ivarD->isInvalidDecl())
119 if (findAtLoc == AtProps.end())
122 PropsTy &props = findAtLoc->second;
124 if (
I->PropD == propD) {
133 I = AtProps.begin(),
E = AtProps.end();
I !=
E; ++
I) {
135 PropsTy &props =
I->second;
136 if (!getPropertyType(props)->isObjCRetainableType())
138 if (hasIvarWithExplicitARCOwnership(props))
142 rewriteProperty(props, atLoc);
147 void doPropAction(PropActionKind
kind,
149 bool markAction =
true) {
152 ActionOnProp[
I->PropD->getIdentifier()] =
kind;
155 case PropAction_None:
157 case PropAction_RetainReplacedWithStrong: {
158 StringRef toAttr =
"strong";
159 MigrateCtx.rewritePropertyAttribute(
"retain", toAttr, atLoc);
162 case PropAction_AssignRemoved:
163 return removeAssignForDefaultStrong(props, atLoc);
164 case PropAction_AssignRewritten:
165 return rewriteAssign(props, atLoc);
166 case PropAction_MaybeAddWeakOrUnsafe:
167 return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
182 return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
185 bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
188 if (HasIvarAssignedAPlusOneObject)
189 return doPropAction(PropAction_AssignRemoved, props, atLoc);
190 return doPropAction(PropAction_AssignRewritten, props, atLoc);
193 if (HasIvarAssignedAPlusOneObject ||
194 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
197 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
200 void removeAssignForDefaultStrong(PropsTy &props,
202 removeAttribute(
"retain", atLoc);
203 if (!removeAttribute(
"assign", atLoc))
208 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
209 diag::err_arc_assign_property_ownership,
210 diag::err_arc_inconsistent_property_ownership,
211 I->IvarD->getLocation());
216 bool canUseWeak =
canApplyWeak(Pass.Ctx, getPropertyType(props),
217 Pass.isGCMigration());
218 const char *toWhich =
219 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ?
"strong" :
220 (canUseWeak ?
"weak" :
"unsafe_unretained");
222 bool rewroteAttr = rewriteAttribute(
"assign", toWhich, atLoc);
227 if (isUserDeclared(
I->IvarD)) {
230 const char *toWhich =
231 (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ?
"__strong " :
232 (canUseWeak ?
"__weak " :
"__unsafe_unretained ");
233 Pass.TA.insert(
I->IvarD->getLocation(), toWhich);
237 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
238 diag::err_arc_assign_property_ownership,
239 diag::err_arc_inconsistent_property_ownership,
240 I->IvarD->getLocation());
244 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
246 bool canUseWeak =
canApplyWeak(Pass.Ctx, getPropertyType(props),
247 Pass.isGCMigration());
249 bool addedAttr = addAttribute(canUseWeak ?
"weak" :
"unsafe_unretained",
255 if (isUserDeclared(
I->IvarD)) {
258 Pass.TA.insert(
I->IvarD->getLocation(),
259 canUseWeak ?
"__weak " :
"__unsafe_unretained ");
262 Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
263 diag::err_arc_assign_property_ownership,
264 diag::err_arc_inconsistent_property_ownership,
265 I->IvarD->getLocation());
266 Pass.TA.clearDiagnostic(
267 diag::err_arc_objc_property_default_assign_on_object,
268 I->ImplD->getLocation());
273 bool removeAttribute(StringRef fromAttr,
SourceLocation atLoc)
const {
274 return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
277 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
279 return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
283 return MigrateCtx.addPropertyAttribute(attr, atLoc);
294 if (RE->getDecl() != Ivar)
305 bool hasIvarAssignedAPlusOneObject(PropsTy &props)
const {
307 PlusOneAssign oneAssign(
I->IvarD);
308 bool notFound = oneAssign.TraverseDecl(CurImplD);
316 bool hasIvarWithExplicitARCOwnership(PropsTy &props)
const {
317 if (Pass.isGCMigration())
321 if (isUserDeclared(
I->IvarD)) {
322 if (isa<AttributedType>(
I->IvarD->getType()))
324 if (
I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
335 if (!Pass.isGCMigration())
346 QualType getPropertyType(PropsTy &props)
const {
347 assert(!props.empty());
348 QualType ty = props[0].PropD->getType().getUnqualifiedType();
352 assert(ty ==
I->PropD->getType().getUnqualifiedType());
359 getPropertyAttrs(PropsTy &props)
const {
360 assert(!props.empty());
362 attrs = props[0].PropD->getPropertyAttributesAsWritten();
366 assert(attrs ==
I->PropD->getPropertyAttributesAsWritten());
A (possibly-)qualified type.
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.
ObjCContainerDecl - Represents a container for method declarations.
A builtin binary operation expression such as "x + y" or "x <= y".
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
bool isPlusOneAssign(const BinaryOperator *E)
decl_iterator decls_begin() const
detail::InMemoryDirectory::const_iterator I
SourceLocation getAtLoc() const
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Expr - This represents one expression.
ObjCIvarDecl * getPropertyIvarDecl() const
ObjCImplementationDecl * getImplementationDecl()
bool canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass=false)
Determine whether we can add weak to the given type.
Assigning into this object requires the old value to be released and the new value to be retained...
Encodes a location in the source.
const TemplateArgument * iterator
bool getSynthesize() const
const ObjCInterfaceDecl * getClassInterface() const
Represents one property declaration in an Objective-C interface.
detail::InMemoryDirectory::const_iterator E
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
instprop_range instance_properties() const
ObjCIvarRefExpr - A reference to an ObjC instance variable.
ObjCPropertyDecl * getPropertyDecl() const
Reading or writing from this object requires a barrier call.
ObjCIvarDecl - Represents an ObjC instance variable.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
visible_extensions_range visible_extensions() const