39 using namespace clang;
40 using namespace arcmt;
41 using namespace trans;
45 class PropertiesRewriter {
52 PropAction_RetainReplacedWithStrong,
53 PropAction_AssignRemoved,
54 PropAction_AssignRewritten,
55 PropAction_MaybeAddWeakOrUnsafe
64 : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
68 typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
69 AtPropDeclsTy AtProps;
70 llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
74 : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
77 AtPropDeclsTy *PrevAtProps =
nullptr) {
79 if (Prop->getAtLoc().isInvalid())
81 unsigned RawLoc = Prop->getAtLoc().getRawEncoding();
83 if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
85 PropsTy &props = AtProps[RawLoc];
86 props.push_back(Prop);
96 collectProperties(iface, AtProps);
100 collectProperties(Ext, AtProps);
104 for (prop_impl_iterator
106 E = prop_impl_iterator(D->
decls_end()); I != E; ++I) {
117 AtPropDeclsTy::iterator findAtLoc = AtProps.find(rawAtLoc);
118 if (findAtLoc == AtProps.end())
121 PropsTy &props = findAtLoc->second;
122 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
123 if (I->PropD == propD) {
131 for (AtPropDeclsTy::iterator
132 I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
134 PropsTy &props = I->second;
135 if (!getPropertyType(props)->isObjCRetainableType())
137 if (hasIvarWithExplicitARCOwnership(props))
141 rewriteProperty(props, atLoc);
146 void doPropAction(PropActionKind
kind,
148 bool markAction =
true) {
150 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
151 ActionOnProp[I->PropD->getIdentifier()] =
kind;
154 case PropAction_None:
156 case PropAction_RetainReplacedWithStrong: {
157 StringRef toAttr =
"strong";
161 case PropAction_AssignRemoved:
162 return removeAssignForDefaultStrong(props, atLoc);
163 case PropAction_AssignRewritten:
164 return rewriteAssign(props, atLoc);
165 case PropAction_MaybeAddWeakOrUnsafe:
166 return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
181 return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
184 bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
187 if (HasIvarAssignedAPlusOneObject)
188 return doPropAction(PropAction_AssignRemoved, props, atLoc);
189 return doPropAction(PropAction_AssignRewritten, props, atLoc);
192 if (HasIvarAssignedAPlusOneObject ||
196 return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
199 void removeAssignForDefaultStrong(PropsTy &props,
201 removeAttribute(
"retain", atLoc);
202 if (!removeAttribute(
"assign", atLoc))
205 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
208 diag::err_arc_assign_property_ownership,
209 diag::err_arc_inconsistent_property_ownership,
210 I->IvarD->getLocation());
217 const char *toWhich =
218 (Pass.
isGCMigration() && !hasGCWeak(props, atLoc)) ?
"strong" :
219 (canUseWeak ?
"weak" :
"unsafe_unretained");
221 bool rewroteAttr = rewriteAttribute(
"assign", toWhich, atLoc);
225 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
226 if (isUserDeclared(I->IvarD)) {
229 const char *toWhich =
230 (Pass.
isGCMigration() && !hasGCWeak(props, atLoc)) ?
"__strong " :
231 (canUseWeak ?
"__weak " :
"__unsafe_unretained ");
232 Pass.
TA.
insert(I->IvarD->getLocation(), toWhich);
237 diag::err_arc_assign_property_ownership,
238 diag::err_arc_inconsistent_property_ownership,
239 I->IvarD->getLocation());
243 void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
248 bool addedAttr = addAttribute(canUseWeak ?
"weak" :
"unsafe_unretained",
253 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
254 if (isUserDeclared(I->IvarD)) {
257 Pass.
TA.
insert(I->IvarD->getLocation(),
258 canUseWeak ?
"__weak " :
"__unsafe_unretained ");
262 diag::err_arc_assign_property_ownership,
263 diag::err_arc_inconsistent_property_ownership,
264 I->IvarD->getLocation());
266 diag::err_arc_objc_property_default_assign_on_object,
267 I->ImplD->getLocation());
272 bool removeAttribute(StringRef fromAttr,
SourceLocation atLoc)
const {
276 bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
293 if (RE->getDecl() != Ivar)
304 bool hasIvarAssignedAPlusOneObject(PropsTy &props)
const {
305 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
306 PlusOneAssign oneAssign(I->IvarD);
307 bool notFound = oneAssign.TraverseDecl(CurImplD);
315 bool hasIvarWithExplicitARCOwnership(PropsTy &props)
const {
319 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
320 if (isUserDeclared(I->IvarD)) {
321 if (isa<AttributedType>(I->IvarD->getType()))
323 if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
345 QualType getPropertyType(PropsTy &props)
const {
346 assert(!props.empty());
347 QualType ty = props[0].PropD->getType().getUnqualifiedType();
350 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
351 assert(ty == I->PropD->getType().getUnqualifiedType());
358 getPropertyAttrs(PropsTy &props)
const {
359 assert(!props.empty());
361 attrs = props[0].PropD->getPropertyAttributesAsWritten();
364 for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
365 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
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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.