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
107 E = prop_impl_iterator(D->
decls_end()); I != E; ++I) {
118 AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
119 if (findAtLoc == AtProps.end())
122 PropsTy &props = findAtLoc->second;
123 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
124 if (I->PropD == propD) {
132 for (AtPropDeclsTy::iterator
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) {
151 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
152 ActionOnProp[I->PropD->getIdentifier()] =
kind;
155 case PropAction_None:
157 case PropAction_RetainReplacedWithStrong: {
158 StringRef toAttr =
"strong";
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 ||
197 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
200 void removeAssignForDefaultStrong(PropsTy &props,
202 removeAttribute(
"retain", atLoc);
203 if (!removeAttribute(
"assign", atLoc))
206 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
209 diag::err_arc_assign_property_ownership,
210 diag::err_arc_inconsistent_property_ownership,
211 I->IvarD->getLocation());
218 const char *toWhich =
219 (Pass.
isGCMigration() && !hasGCWeak(props, atLoc)) ?
"strong" :
220 (canUseWeak ?
"weak" :
"unsafe_unretained");
222 bool rewroteAttr = rewriteAttribute(
"assign", toWhich, atLoc);
226 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
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);
238 diag::err_arc_assign_property_ownership,
239 diag::err_arc_inconsistent_property_ownership,
240 I->IvarD->getLocation());
244 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
249 bool addedAttr = addAttribute(canUseWeak ?
"weak" :
"unsafe_unretained",
254 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
255 if (isUserDeclared(I->IvarD)) {
258 Pass.
TA.
insert(I->IvarD->getLocation(),
259 canUseWeak ?
"__weak " :
"__unsafe_unretained ");
263 diag::err_arc_assign_property_ownership,
264 diag::err_arc_inconsistent_property_ownership,
265 I->IvarD->getLocation());
267 diag::err_arc_objc_property_default_assign_on_object,
268 I->ImplD->getLocation());
273 bool removeAttribute(StringRef fromAttr,
SourceLocation atLoc)
const {
277 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
294 if (RE->getDecl() != Ivar)
305 bool hasIvarAssignedAPlusOneObject(PropsTy &props)
const {
306 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
307 PlusOneAssign oneAssign(I->IvarD);
308 bool notFound = oneAssign.TraverseDecl(CurImplD);
316 bool hasIvarWithExplicitARCOwnership(PropsTy &props)
const {
320 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
321 if (isUserDeclared(I->IvarD)) {
322 if (isa<AttributedType>(I->IvarD->getType()))
324 if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
346 QualType getPropertyType(PropsTy &props)
const {
347 assert(!props.empty());
348 QualType ty = props[0].PropD->getType().getUnqualifiedType();
351 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
352 assert(ty == I->PropD->getType().getUnqualifiedType());
359 getPropertyAttrs(PropsTy &props)
const {
360 assert(!props.empty());
362 attrs = props[0].PropD->getPropertyAttributesAsWritten();
365 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
366 assert(attrs == I->PropD->getPropertyAttributesAsWritten());
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
A (possibly-)qualified type.
ObjCIvarDecl * getPropertyIvarDecl() const
Defines the SourceManager interface.
MigrationContext & getMigrationContext()
void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override
bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, SourceLocation atLoc)
bool isInvalidDecl() const
instprop_range instance_properties() 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 preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
bool isPlusOneAssign(const BinaryOperator *E)
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
visible_extensions_range visible_extensions() const
This represents one expression.
ObjCImplementationDecl * getImplementationDecl()
bool addPropertyAttribute(StringRef attr, SourceLocation atLoc)
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.
bool getSynthesize() const
decl_iterator decls_begin() const
bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc)
Represents one property declaration in an Objective-C interface.
const ObjCInterfaceDecl * getClassInterface() const
Dataflow Directional Tag Classes.
Kind getPropertyImplementation() const
SourceLocation getAtLoc() const
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...
ObjCIvarRefExpr - A reference to an ObjC instance variable.
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.
bool isGCMigration() const
ObjCPropertyDecl * getPropertyDecl() const
decl_iterator decls_end() const
llvm::DenseSet< unsigned > AtPropsWeak
Set of raw '@' locations for 'assign' properties group that contain GC __weak.