summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp328
1 files changed, 154 insertions, 174 deletions
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
index ca845b6..cc85fe2 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
@@ -44,8 +44,17 @@ using namespace trans;
namespace {
class PropertiesRewriter {
+ MigrationContext &MigrateCtx;
MigrationPass &Pass;
ObjCImplementationDecl *CurImplD;
+
+ enum PropActionKind {
+ PropAction_None,
+ PropAction_RetainReplacedWithStrong,
+ PropAction_AssignRemoved,
+ PropAction_AssignRewritten,
+ PropAction_MaybeAddWeakOrUnsafe
+ };
struct PropData {
ObjCPropertyDecl *PropD;
@@ -58,9 +67,27 @@ class PropertiesRewriter {
typedef SmallVector<PropData, 2> PropsTy;
typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
AtPropDeclsTy AtProps;
+ llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
public:
- PropertiesRewriter(MigrationPass &pass) : Pass(pass) { }
+ explicit PropertiesRewriter(MigrationContext &MigrateCtx)
+ : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
+
+ static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
+ AtPropDeclsTy *PrevAtProps = 0) {
+ for (ObjCInterfaceDecl::prop_iterator
+ propI = D->prop_begin(),
+ propE = D->prop_end(); propI != propE; ++propI) {
+ if (propI->getAtLoc().isInvalid())
+ continue;
+ unsigned RawLoc = propI->getAtLoc().getRawEncoding();
+ if (PrevAtProps)
+ if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
+ continue;
+ PropsTy &props = AtProps[RawLoc];
+ props.push_back(*propI);
+ }
+ }
void doTransform(ObjCImplementationDecl *D) {
CurImplD = D;
@@ -68,14 +95,7 @@ public:
if (!iface)
return;
- for (ObjCInterfaceDecl::prop_iterator
- propI = iface->prop_begin(),
- propE = iface->prop_end(); propI != propE; ++propI) {
- if (propI->getAtLoc().isInvalid())
- continue;
- PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
- props.push_back(*propI);
- }
+ collectProperties(iface, AtProps);
typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
prop_impl_iterator;
@@ -110,19 +130,66 @@ public:
I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
PropsTy &props = I->second;
- QualType ty = getPropertyType(props);
- if (!ty->isObjCRetainableType())
+ if (!getPropertyType(props)->isObjCRetainableType())
continue;
- if (hasIvarWithExplicitOwnership(props))
+ if (hasIvarWithExplicitARCOwnership(props))
continue;
Transaction Trans(Pass.TA);
rewriteProperty(props, atLoc);
}
+
+ AtPropDeclsTy AtExtProps;
+ // Look through extensions.
+ for (ObjCCategoryDecl *Cat = iface->getCategoryList();
+ Cat; Cat = Cat->getNextClassCategory())
+ if (Cat->IsClassExtension())
+ collectProperties(Cat, AtExtProps, &AtProps);
+
+ for (AtPropDeclsTy::iterator
+ I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
+ SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
+ PropsTy &props = I->second;
+ Transaction Trans(Pass.TA);
+ doActionForExtensionProp(props, atLoc);
+ }
}
private:
- void rewriteProperty(PropsTy &props, SourceLocation atLoc) const {
+ void doPropAction(PropActionKind kind,
+ PropsTy &props, SourceLocation atLoc,
+ bool markAction = true) {
+ if (markAction)
+ for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
+ ActionOnProp[I->PropD->getIdentifier()] = kind;
+
+ switch (kind) {
+ case PropAction_None:
+ return;
+ case PropAction_RetainReplacedWithStrong: {
+ StringRef toAttr = "strong";
+ MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
+ return;
+ }
+ case PropAction_AssignRemoved:
+ return removeAssignForDefaultStrong(props, atLoc);
+ case PropAction_AssignRewritten:
+ return rewriteAssign(props, atLoc);
+ case PropAction_MaybeAddWeakOrUnsafe:
+ return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
+ }
+ }
+
+ void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
+ llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
+ I = ActionOnProp.find(props[0].PropD->getIdentifier());
+ if (I == ActionOnProp.end())
+ return;
+
+ doPropAction(I->second, props, atLoc, false);
+ }
+
+ void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
@@ -132,79 +199,82 @@ private:
return;
if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
- rewriteAttribute("retain", "strong", atLoc);
- return;
+ // strong is the default.
+ return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
}
+ bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
+
if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
- if (hasIvarAssignedAPlusOneObject(props)) {
- rewriteAttribute("assign", "strong", atLoc);
- return;
- }
- return rewriteAssign(props, atLoc);
+ if (HasIvarAssignedAPlusOneObject)
+ return doPropAction(PropAction_AssignRemoved, props, atLoc);
+ return doPropAction(PropAction_AssignRewritten, props, atLoc);
}
- if (hasIvarAssignedAPlusOneObject(props))
- return maybeAddStrongAttr(props, atLoc);
+ if (HasIvarAssignedAPlusOneObject ||
+ (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
+ return; // 'strong' by default.
- return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
+ return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
}
- void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
- bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
-
- bool rewroteAttr = rewriteAttribute("assign",
- canUseWeak ? "weak" : "unsafe_unretained",
- atLoc);
- if (!rewroteAttr)
- canUseWeak = false;
+ void removeAssignForDefaultStrong(PropsTy &props,
+ SourceLocation atLoc) const {
+ removeAttribute("retain", atLoc);
+ if (!removeAttribute("assign", atLoc))
+ return;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD))
- Pass.TA.insert(I->IvarD->getLocation(),
- canUseWeak ? "__weak " : "__unsafe_unretained ");
if (I->ImplD)
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
I->ImplD->getLocation());
}
}
- void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
- SourceLocation atLoc) const {
- ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
+ void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
+ bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
+ /*AllowOnUnknownClass=*/Pass.isGCMigration());
+ const char *toWhich =
+ (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
+ (canUseWeak ? "weak" : "unsafe_unretained");
- bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
- if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
- !hasAllIvarsBacked(props)) {
- bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
- atLoc);
- if (!addedAttr)
- canUseWeak = false;
- }
+ bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
+ if (!rewroteAttr)
+ canUseWeak = false;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD))
- Pass.TA.insert(I->IvarD->getLocation(),
- canUseWeak ? "__weak " : "__unsafe_unretained ");
- if (I->ImplD) {
+ if (isUserDeclared(I->IvarD)) {
+ if (I->IvarD &&
+ I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
+ const char *toWhich =
+ (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
+ (canUseWeak ? "__weak " : "__unsafe_unretained ");
+ Pass.TA.insert(I->IvarD->getLocation(), toWhich);
+ }
+ }
+ if (I->ImplD)
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
I->ImplD->getLocation());
- Pass.TA.clearDiagnostic(
- diag::err_arc_objc_property_default_assign_on_object,
- I->ImplD->getLocation());
- }
}
}
- void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const {
- ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
+ void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
+ SourceLocation atLoc) const {
+ bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
+ /*AllowOnUnknownClass=*/Pass.isGCMigration());
- if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
- !hasAllIvarsBacked(props)) {
- addAttribute("strong", atLoc);
- }
+ bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
+ atLoc);
+ if (!addedAttr)
+ canUseWeak = false;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
+ if (isUserDeclared(I->IvarD)) {
+ if (I->IvarD &&
+ I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
+ Pass.TA.insert(I->IvarD->getLocation(),
+ canUseWeak ? "__weak " : "__unsafe_unretained ");
+ }
if (I->ImplD) {
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
I->ImplD->getLocation());
@@ -215,108 +285,17 @@ private:
}
}
+ bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
+ return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
+ }
+
bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
SourceLocation atLoc) const {
- if (atLoc.isMacroID())
- return false;
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Pass.Ctx.getLangOptions(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::at)) return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::raw_identifier)) return false;
- if (StringRef(tok.getRawIdentifierData(), tok.getLength())
- != "property")
- return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::l_paren)) return false;
-
- lexer.LexFromRawLexer(tok);
- if (tok.is(tok::r_paren))
- return false;
-
- while (1) {
- if (tok.isNot(tok::raw_identifier)) return false;
- StringRef ident(tok.getRawIdentifierData(), tok.getLength());
- if (ident == fromAttr) {
- Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
- return true;
- }
-
- do {
- lexer.LexFromRawLexer(tok);
- } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
- if (tok.is(tok::r_paren))
- break;
- lexer.LexFromRawLexer(tok);
- }
-
- return false;
+ return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
}
bool addAttribute(StringRef attr, SourceLocation atLoc) const {
- if (atLoc.isMacroID())
- return false;
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Pass.Ctx.getLangOptions(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::at)) return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::raw_identifier)) return false;
- if (StringRef(tok.getRawIdentifierData(), tok.getLength())
- != "property")
- return false;
- lexer.LexFromRawLexer(tok);
-
- if (tok.isNot(tok::l_paren)) {
- Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
- return true;
- }
-
- lexer.LexFromRawLexer(tok);
- if (tok.is(tok::r_paren)) {
- Pass.TA.insert(tok.getLocation(), attr);
- return true;
- }
-
- if (tok.isNot(tok::raw_identifier)) return false;
-
- Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
- return true;
+ return MigrateCtx.addPropertyAttribute(attr, atLoc);
}
class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
@@ -358,7 +337,10 @@ private:
return false;
}
- bool hasIvarWithExplicitOwnership(PropsTy &props) const {
+ bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
+ if (Pass.isGCMigration())
+ return false;
+
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
if (isUserDeclared(I->IvarD)) {
if (isa<AttributedType>(I->IvarD->getType()))
@@ -380,17 +362,26 @@ private:
return true;
}
+ // \brief Returns true if all declarations in the @property have GC __weak.
+ bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
+ if (!Pass.isGCMigration())
+ return false;
+ if (props.empty())
+ return false;
+ return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
+ }
+
bool isUserDeclared(ObjCIvarDecl *ivarD) const {
return ivarD && !ivarD->getSynthesize();
}
QualType getPropertyType(PropsTy &props) const {
assert(!props.empty());
- QualType ty = props[0].PropD->getType();
+ QualType ty = props[0].PropD->getType().getUnqualifiedType();
#ifndef NDEBUG
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
- assert(ty == I->PropD->getType());
+ assert(ty == I->PropD->getType().getUnqualifiedType());
#endif
return ty;
@@ -411,21 +402,10 @@ private:
}
};
-class ImplementationChecker :
- public RecursiveASTVisitor<ImplementationChecker> {
- MigrationPass &Pass;
-
-public:
- ImplementationChecker(MigrationPass &pass) : Pass(pass) { }
-
- bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
- PropertiesRewriter(Pass).doTransform(D);
- return true;
- }
-};
-
} // anonymous namespace
-void trans::rewriteProperties(MigrationPass &pass) {
- ImplementationChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+void PropertyRewriteTraverser::traverseObjCImplementation(
+ ObjCImplementationContext &ImplCtx) {
+ PropertiesRewriter(ImplCtx.getMigrationContext())
+ .doTransform(ImplCtx.getImplementationDecl());
}
OpenPOWER on IntegriCloud