[cfe-commits] r143979 - in /cfe/trunk: lib/ARCMigrate/TransGCAttrs.cpp lib/ARCMigrate/TransProperties.cpp lib/ARCMigrate/Transforms.cpp lib/ARCMigrate/Transforms.h test/ARCMT/GC.m test/ARCMT/GC.m.result

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Nov 7 10:46:46 PST 2011


Author: akirtzidis
Date: Mon Nov  7 12:46:46 2011
New Revision: 143979

URL: http://llvm.org/viewvc/llvm-project?rev=143979&view=rev
Log:
[arcmt] In GC, handle (assign) @properties.

-Move __strong/__weak added to a property type to the property attribute,
e.g.  "@property (assign) __weak Foo *prop;" --> "@property (weak) Foo *prop;"

-Remove (assign) in a property so that it becomes strong-by-default in ARC.

Modified:
    cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp
    cfe/trunk/lib/ARCMigrate/TransProperties.cpp
    cfe/trunk/lib/ARCMigrate/Transforms.cpp
    cfe/trunk/lib/ARCMigrate/Transforms.h
    cfe/trunk/test/ARCMT/GC.m
    cfe/trunk/test/ARCMT/GC.m.result

Modified: cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp?rev=143979&r1=143978&r2=143979&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp Mon Nov  7 12:46:46 2011
@@ -13,6 +13,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Analysis/Support/SaveAndRestore.h"
 #include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/TinyPtrVector.h"
 
 using namespace clang;
 using namespace arcmt;
@@ -24,11 +25,14 @@
 class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
   MigrationContext &MigrateCtx;
   bool FullyMigratable;
+  std::vector<ObjCPropertyDecl *> &AllProps;
 
   typedef RecursiveASTVisitor<GCAttrsCollector> base;
 public:
-  explicit GCAttrsCollector(MigrationContext &ctx)
-    : MigrateCtx(ctx), FullyMigratable(false) { }
+  GCAttrsCollector(MigrationContext &ctx,
+                   std::vector<ObjCPropertyDecl *> &AllProps)
+    : MigrateCtx(ctx), FullyMigratable(false),
+      AllProps(AllProps) { }
 
   bool shouldWalkTypesOfTypeLocs() const { return false; }
 
@@ -41,13 +45,14 @@
     if (!D || D->isImplicit())
       return true;
 
-    bool migratable = isMigratable(D);
-    SaveAndRestore<bool> Save(FullyMigratable, migratable);
+    SaveAndRestore<bool> Save(FullyMigratable, isMigratable(D));
     
-    if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
-      lookForAttribute(DD, DD->getTypeSourceInfo());
-    else if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D))
+    if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) {
       lookForAttribute(PropD, PropD->getTypeSourceInfo());
+      AllProps.push_back(PropD);
+    } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+      lookForAttribute(DD, DD->getTypeSourceInfo());
+    }
     return base::TraverseDecl(D);
   }
 
@@ -56,11 +61,14 @@
       return;
     TypeLoc TL = TInfo->getTypeLoc();
     while (TL) {
-      if (const AttributedTypeLoc *Attr = dyn_cast<AttributedTypeLoc>(&TL)) {
+      if (const QualifiedTypeLoc *QL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+        TL = QL->getUnqualifiedLoc();
+      } else if (const AttributedTypeLoc *
+                   Attr = dyn_cast<AttributedTypeLoc>(&TL)) {
         if (handleAttr(*Attr, D))
           break;
         TL = Attr->getModifiedLoc();
-      } if (const ArrayTypeLoc *Arr = dyn_cast<ArrayTypeLoc>(&TL)) {
+      } else if (const ArrayTypeLoc *Arr = dyn_cast<ArrayTypeLoc>(&TL)) {
         TL = Arr->getElementLoc();
       } else if (const PointerTypeLoc *PT = dyn_cast<PointerTypeLoc>(&TL)) {
         TL = PT->getPointeeLoc();
@@ -108,10 +116,6 @@
     Attr.ModifiedType = TL.getModifiedLoc().getType();
     Attr.Dcl = D;
     Attr.FullyMigratable = FullyMigratable;
-
-    if (ObjCPropertyDecl *PD = dyn_cast_or_null<ObjCPropertyDecl>(D))
-      MigrateCtx.PropGCAttrs[PD] = MigrateCtx.GCAttrs.size() - 1;
-
     return true;
   }
 
@@ -125,15 +129,8 @@
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
       return FD->hasBody();
 
-    if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
-      if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
-        return ID->getImplementation() != 0;
-      if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
-        return CD->getImplementation() != 0;
-      if (isa<ObjCImplDecl>(ContD))
-        return true;
-      return false;
-    }
+    if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D))
+      return hasObjCImpl(ContD);
 
     if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
       for (CXXRecordDecl::method_iterator
@@ -147,6 +144,21 @@
     return isMigratable(cast<Decl>(D->getDeclContext()));
   }
 
+  static bool hasObjCImpl(Decl *D) {
+    if (!D)
+      return false;
+    if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
+      if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
+        return ID->getImplementation() != 0;
+      if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
+        return CD->getImplementation() != 0;
+      if (isa<ObjCImplDecl>(ContD))
+        return true;
+      return false;
+    }
+    return false;
+  }
+
   bool isInMainFile(Decl *D) {
     if (!D)
       return false;
@@ -214,8 +226,7 @@
 
   for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
     MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
-    if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak &&
-        Attr.FullyMigratable) {
+    if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak) {
       if (Attr.ModifiedType.isNull() ||
           !Attr.ModifiedType->isObjCRetainableType())
         continue;
@@ -231,13 +242,113 @@
   }
 }
 
+typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
+
+static void checkAllAtProps(MigrationContext &MigrateCtx,
+                            SourceLocation AtLoc,
+                            IndivPropsTy &IndProps) {
+  if (IndProps.empty())
+    return;
+
+  for (IndivPropsTy::iterator
+         PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
+    QualType T = (*PI)->getType();
+    if (T.isNull() || !T->isObjCRetainableType())
+      return;
+  }
+
+  SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs;
+  bool hasWeak = false, hasStrong = false;
+  for (IndivPropsTy::iterator
+         PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
+    ObjCPropertyDecl *PD = *PI;
+    TypeSourceInfo *TInfo = PD->getTypeSourceInfo();
+    if (!TInfo)
+      return;
+    TypeLoc TL = TInfo->getTypeLoc();
+    if (AttributedTypeLoc *ATL = dyn_cast<AttributedTypeLoc>(&TL)) {
+      ATLs.push_back(std::make_pair(*ATL, PD));
+      if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+        hasWeak = true;
+      } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong)
+        hasStrong = true;
+      else
+        return;
+    }
+  }
+  if (ATLs.empty())
+    return;
+  if (hasWeak && hasStrong)
+    return;
+
+  TransformActions &TA = MigrateCtx.Pass.TA;
+  Transaction Trans(TA);
+
+  if (GCAttrsCollector::hasObjCImpl(
+                              cast<Decl>(IndProps.front()->getDeclContext()))) {
+    if (hasWeak)
+      MigrateCtx.AtPropsWeak.insert(AtLoc.getRawEncoding());
+
+  } else {
+    StringRef toAttr = "strong";
+    if (hasWeak) {
+      if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(),
+                       /*AllowOnUnkwownClass=*/true))
+        toAttr = "weak";
+      else
+        toAttr = "unsafe_unretained";
+    }
+    if (!MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc)) {
+      return;
+    }
+  }
+
+  for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
+    SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
+    if (Loc.isMacroID())
+      Loc = MigrateCtx.Pass.Ctx.getSourceManager()
+                                         .getImmediateExpansionRange(Loc).first;
+    TA.remove(Loc);
+    TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
+    TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
+                       ATLs[i].second->getLocation());
+  }
+}
+
+static void checkAllProps(MigrationContext &MigrateCtx,
+                          std::vector<ObjCPropertyDecl *> &AllProps) {
+  typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
+  llvm::DenseMap<unsigned, IndivPropsTy> AtProps;
+
+  for (unsigned i = 0, e = AllProps.size(); i != e; ++i) {
+    ObjCPropertyDecl *PD = AllProps[i];
+    if (PD->getPropertyAttributesAsWritten() &
+          ObjCPropertyDecl::OBJC_PR_assign) {
+      SourceLocation AtLoc = PD->getAtLoc();
+      if (AtLoc.isInvalid())
+        continue;
+      unsigned RawAt = AtLoc.getRawEncoding();
+      AtProps[RawAt].push_back(PD);
+    }
+  }
+
+  for (llvm::DenseMap<unsigned, IndivPropsTy>::iterator
+         I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
+    SourceLocation AtLoc = SourceLocation::getFromRawEncoding(I->first);
+    IndivPropsTy &IndProps = I->second;
+    checkAllAtProps(MigrateCtx, AtLoc, IndProps);
+  }
+}
+
 void GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) {
-  GCAttrsCollector(MigrateCtx).TraverseDecl(
+  std::vector<ObjCPropertyDecl *> AllProps;
+  GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl(
                                   MigrateCtx.Pass.Ctx.getTranslationUnitDecl());
 
   clearRedundantStrongs(MigrateCtx);
   errorForGCAttrsOnNonObjC(MigrateCtx);
   checkWeakGCAttrs(MigrateCtx);
+  checkAllProps(MigrateCtx, AllProps);
 }
 
 void MigrationContext::dumpGCAttrs() {

Modified: cfe/trunk/lib/ARCMigrate/TransProperties.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransProperties.cpp?rev=143979&r1=143978&r2=143979&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransProperties.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransProperties.cpp Mon Nov  7 12:46:46 2011
@@ -44,6 +44,7 @@
 namespace {
 
 class PropertiesRewriter {
+  MigrationContext &MigrateCtx;
   MigrationPass &Pass;
   ObjCImplementationDecl *CurImplD;
   
@@ -51,7 +52,7 @@
     PropAction_None,
     PropAction_RetainToStrong,
     PropAction_RetainRemoved,
-    PropAction_AssignToStrong,
+    PropAction_AssignRemoved,
     PropAction_AssignRewritten,
     PropAction_MaybeAddStrong,
     PropAction_MaybeAddWeakOrUnsafe
@@ -71,7 +72,8 @@
   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) {
     for (ObjCInterfaceDecl::prop_iterator
@@ -167,9 +169,8 @@
     case PropAction_RetainRemoved:
       removeAttribute("retain", atLoc);
       return;
-    case PropAction_AssignToStrong:
-      rewriteAttribute("assign", "strong", atLoc);
-      return;
+    case PropAction_AssignRemoved:
+      return removeAssignForDefaultStrong(props, atLoc);
     case PropAction_AssignRewritten:
       return rewriteAssign(props, atLoc);
     case PropAction_MaybeAddStrong:
@@ -205,21 +206,39 @@
         return doPropAction(PropAction_RetainRemoved, props, atLoc);
     }
 
+    bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
+
     if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
-      if (hasIvarAssignedAPlusOneObject(props)) {
-        return doPropAction(PropAction_AssignToStrong, props, atLoc);
+      if (HasIvarAssignedAPlusOneObject ||
+          (Pass.isGCMigration() && !hasGCWeak(props, atLoc))) {
+        return doPropAction(PropAction_AssignRemoved, props, atLoc);
       }
       return doPropAction(PropAction_AssignRewritten, props, atLoc);
     }
 
-    if (hasIvarAssignedAPlusOneObject(props))
+    if (HasIvarAssignedAPlusOneObject ||
+        (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
       return doPropAction(PropAction_MaybeAddStrong, props, atLoc);
 
     return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
   }
 
+  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 (I->ImplD)
+        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
+                                I->ImplD->getLocation());
+    }
+  }
+
   void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
-    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
+    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
+                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
 
     bool rewroteAttr = rewriteAttribute("assign",
                                      canUseWeak ? "weak" : "unsafe_unretained",
@@ -241,7 +260,8 @@
                                           SourceLocation atLoc) const {
     ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
 
-    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
+    bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
+                                  /*AllowOnUnknownClass=*/Pass.isGCMigration());
     if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
         !hasAllIvarsBacked(props)) {
       bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
@@ -289,85 +309,7 @@
 
   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;
-    
-    Token BeforeTok = tok;
-    Token AfterTok;
-    AfterTok.startToken();
-    SourceLocation AttrLoc;
-    
-    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) {
-        if (!toAttr.empty()) {
-          Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
-          return true;
-        }
-        // We want to remove the attribute.
-        AttrLoc = tok.getLocation();
-      }
-
-      do {
-        lexer.LexFromRawLexer(tok);
-        if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
-          AfterTok = tok;
-      } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
-      if (tok.is(tok::r_paren))
-        break;
-      if (AttrLoc.isInvalid())
-        BeforeTok = tok;
-      lexer.LexFromRawLexer(tok);
-    }
-
-    if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
-      // We want to remove the attribute.
-      if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
-        Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
-                                   AfterTok.getLocation()));
-      } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
-        Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
-      } else {
-        Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
-      }
-
-      return true;
-    }
-    
-    return false;
+    return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
   }
 
   bool addAttribute(StringRef attr, SourceLocation atLoc) const {
@@ -482,6 +424,15 @@
     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();
   }
@@ -513,23 +464,10 @@
   }
 };
 
-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 PropertyRewriteTraverser::traverseObjCImplementation(
                                            ObjCImplementationContext &ImplCtx) {
-  PropertiesRewriter(ImplCtx.getMigrationContext().Pass)
+  PropertiesRewriter(ImplCtx.getMigrationContext())
                                   .doTransform(ImplCtx.getImplementationDecl());
 }

Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=143979&r1=143978&r2=143979&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Mon Nov  7 12:46:46 2011
@@ -70,6 +70,9 @@
     return false;
 
   QualType T = type;
+  if (T.isNull())
+    return false;
+
   while (const PointerType *ptr = T->getAs<PointerType>())
     T = ptr->getPointeeType();
   if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
@@ -357,6 +360,90 @@
   return false;
 }
 
+bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
+                                                StringRef toAttr,
+                                                SourceLocation atLoc) {
+  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;
+  
+  Token BeforeTok = tok;
+  Token AfterTok;
+  AfterTok.startToken();
+  SourceLocation AttrLoc;
+  
+  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) {
+      if (!toAttr.empty()) {
+        Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
+        return true;
+      }
+      // We want to remove the attribute.
+      AttrLoc = tok.getLocation();
+    }
+
+    do {
+      lexer.LexFromRawLexer(tok);
+      if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
+        AfterTok = tok;
+    } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
+    if (tok.is(tok::r_paren))
+      break;
+    if (AttrLoc.isInvalid())
+      BeforeTok = tok;
+    lexer.LexFromRawLexer(tok);
+  }
+
+  if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
+    // We want to remove the attribute.
+    if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
+      Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
+                                 AfterTok.getLocation()));
+    } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
+      Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
+    } else {
+      Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
+    }
+
+    return true;
+  }
+  
+  return false;
+}
+
 void MigrationContext::traverse(TranslationUnitDecl *TU) {
   for (traverser_iterator
          I = traversers_begin(), E = traversers_end(); I != E; ++I)

Modified: cfe/trunk/lib/ARCMigrate/Transforms.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.h?rev=143979&r1=143978&r2=143979&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Transforms.h (original)
+++ cfe/trunk/lib/ARCMigrate/Transforms.h Mon Nov  7 12:46:46 2011
@@ -96,8 +96,9 @@
   std::vector<GCAttrOccurrence> GCAttrs;
   llvm::DenseSet<unsigned> AttrSet;
 
-  /// \brief Map of property decl to the index in the GCAttrs vector.
-  llvm::DenseMap<ObjCPropertyDecl *, unsigned> PropGCAttrs;
+  /// \brief Set of raw '@' locations for 'assign' properties group that contain
+  /// GC __weak.
+  llvm::DenseSet<unsigned> AtPropsWeak;
 
   explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
   ~MigrationContext();
@@ -111,6 +112,8 @@
   }
 
   bool isGCOwnedNonObjC(QualType T);
+  bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
+                                SourceLocation atLoc);
 
   void traverse(TranslationUnitDecl *TU);
 

Modified: cfe/trunk/test/ARCMT/GC.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/GC.m?rev=143979&r1=143978&r2=143979&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/GC.m (original)
+++ cfe/trunk/test/ARCMT/GC.m Mon Nov  7 12:46:46 2011
@@ -48,3 +48,22 @@
   __weak QQ *q;
 }
 @end
+
+ at interface I3
+ at property (assign) I3 *__weak pw1, *__weak pw2;
+ at property (assign) I3 *__strong ps;
+ at property (assign) I3 * pds;
+ at end
+
+ at interface I4Impl {
+  I4Impl *pds2;
+}
+ at property (assign) I4Impl *__weak pw1, *__weak pw2;
+ at property (assign) I4Impl *__strong ps;
+ at property (assign) I4Impl * pds;
+ at property (assign) I4Impl * pds2;
+ at end
+
+ at implementation I4Impl
+ at synthesize pw1, pw2, ps, pds, pds2;
+ at end

Modified: cfe/trunk/test/ARCMT/GC.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/GC.m.result?rev=143979&r1=143978&r2=143979&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/GC.m.result (original)
+++ cfe/trunk/test/ARCMT/GC.m.result Mon Nov  7 12:46:46 2011
@@ -43,3 +43,22 @@
   __unsafe_unretained QQ *q;
 }
 @end
+
+ at interface I3
+ at property (weak) I3 * pw1, * pw2;
+ at property (strong) I3 * ps;
+ at property (assign) I3 * pds;
+ at end
+
+ at interface I4Impl {
+  I4Impl *pds2;
+}
+ at property (weak) I4Impl * pw1, * pw2;
+ at property  I4Impl * ps;
+ at property  I4Impl * pds;
+ at property  I4Impl * pds2;
+ at end
+
+ at implementation I4Impl
+ at synthesize pw1, pw2, ps, pds, pds2;
+ at end





More information about the cfe-commits mailing list