]> granicus.if.org Git - clang/commitdiff
[arcmt] Collect all the places where GC attributes __strong/__weak occur.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 6 Nov 2011 18:58:03 +0000 (18:58 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 6 Nov 2011 18:58:03 +0000 (18:58 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143883 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ARCMigrate/CMakeLists.txt
lib/ARCMigrate/TransGCAttrs.cpp [new file with mode: 0644]
lib/ARCMigrate/TransGCCalls.cpp
lib/ARCMigrate/TransProperties.cpp
lib/ARCMigrate/Transforms.cpp
lib/ARCMigrate/Transforms.h

index 90c2bbf54e58b187f181d8e9f6474a348cbfd686..1a64b12721d968bd3254aa71451cde1e4dbdb0b5 100644 (file)
@@ -12,6 +12,7 @@ add_clang_library(clangARCMigrate
   TransEmptyStatementsAndDealloc.cpp
   TransformActions.cpp
   Transforms.cpp
+  TransGCAttrs.cpp
   TransGCCalls.cpp
   TransProperties.cpp
   TransRetainReleaseDealloc.cpp
diff --git a/lib/ARCMigrate/TransGCAttrs.cpp b/lib/ARCMigrate/TransGCAttrs.cpp
new file mode 100644 (file)
index 0000000..60573a4
--- /dev/null
@@ -0,0 +1,191 @@
+//===--- TransGCAttrs.cpp - Transformations to ARC mode --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Analysis/Support/SaveAndRestore.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+
+namespace {
+
+/// \brief Collects all the places where GC attributes __strong/__weak occur.
+class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
+  MigrationContext &MigrateCtx;
+  bool FullyMigratable;
+
+  typedef RecursiveASTVisitor<GCAttrsCollector> base;
+public:
+  explicit GCAttrsCollector(MigrationContext &ctx)
+    : MigrateCtx(ctx), FullyMigratable(false) { }
+
+  bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+  bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+    handleAttr(TL);
+    return true;
+  }
+
+  bool TraverseDecl(Decl *D) {
+    if (!D || D->isImplicit())
+      return true;
+
+    bool migratable = isMigratable(D);
+    SaveAndRestore<bool> Save(FullyMigratable, migratable);
+    
+    if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
+      lookForAttribute(DD, DD->getTypeSourceInfo());
+    else if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D))
+      lookForAttribute(PropD, PropD->getTypeSourceInfo());
+    return base::TraverseDecl(D);
+  }
+
+  void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) {
+    if (!TInfo)
+      return;
+    TypeLoc TL = TInfo->getTypeLoc();
+    while (TL) {
+      if (const AttributedTypeLoc *Attr = dyn_cast<AttributedTypeLoc>(&TL)) {
+        if (handleAttr(*Attr, D))
+          break;
+        TL = Attr->getModifiedLoc();
+      } if (const ArrayTypeLoc *Arr = dyn_cast<ArrayTypeLoc>(&TL)) {
+        TL = Arr->getElementLoc();
+      } else if (const PointerTypeLoc *PT = dyn_cast<PointerTypeLoc>(&TL)) {
+        TL = PT->getPointeeLoc();
+      } else if (const ReferenceTypeLoc *RT = dyn_cast<ReferenceTypeLoc>(&TL))
+        TL = RT->getPointeeLoc();
+      else
+        break;
+    }
+  }
+
+  bool handleAttr(AttributedTypeLoc TL, Decl *D = 0) {
+    if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
+      return false;
+
+    SourceLocation Loc = TL.getAttrNameLoc();
+    unsigned RawLoc = Loc.getRawEncoding();
+    if (MigrateCtx.AttrSet.count(RawLoc))
+      return true;
+
+    ASTContext &Ctx = MigrateCtx.Pass.Ctx;
+    SourceManager &SM = Ctx.getSourceManager();
+    llvm::SmallString<32> Buf;
+    bool Invalid = false;
+    StringRef Spell = Lexer::getSpelling(
+                                  SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
+                                  Buf, SM, Ctx.getLangOptions(), &Invalid);
+    if (Invalid)
+      return false;
+    MigrationContext::GCAttrOccurrence::AttrKind Kind;
+    if (Spell == "strong")
+      Kind = MigrationContext::GCAttrOccurrence::Strong;
+    else if (Spell == "weak")
+      Kind = MigrationContext::GCAttrOccurrence::Weak;
+    else
+      return false;
+    MigrateCtx.AttrSet.insert(RawLoc);
+    MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence());
+    MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back();
+
+    Attr.Kind = Kind;
+    Attr.Loc = Loc;
+    Attr.ModifiedType = TL.getModifiedLoc().getType();
+    Attr.Dcl = D;
+    Attr.FullyMigratable = FullyMigratable;
+    return true;
+  }
+
+  bool isMigratable(Decl *D) {
+    if (isa<TranslationUnitDecl>(D))
+      return false;
+
+    if (isInMainFile(D))
+      return true;
+
+    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 (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+      for (CXXRecordDecl::method_iterator
+             MI = RD->method_begin(), ME = RD->method_end(); MI != ME; ++MI) {
+        if ((*MI)->isOutOfLine())
+          return true;
+      }
+      return false;
+    }
+
+    return isMigratable(cast<Decl>(D->getDeclContext()));
+  }
+
+  bool isInMainFile(Decl *D) {
+    if (!D)
+      return false;
+
+    for (Decl::redecl_iterator
+           I = D->redecls_begin(), E = D->redecls_end(); I != E; ++I)
+      if (!isInMainFile((*I)->getLocation()))
+        return false;
+    
+    return true;
+  }
+
+  bool isInMainFile(SourceLocation Loc) {
+    if (Loc.isInvalid())
+      return false;
+
+    SourceManager &SM = MigrateCtx.Pass.Ctx.getSourceManager();
+    return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID());
+  }
+};
+
+} // anonymous namespace
+
+void GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) {
+  GCAttrsCollector(MigrateCtx).TraverseDecl(
+                                  MigrateCtx.Pass.Ctx.getTranslationUnitDecl());
+#if 0
+  llvm::errs() << "\n################\n";
+  for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
+    MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
+    llvm::errs() << "KIND: "
+        << (Attr.Kind == MigrationContext::GCAttrOccurrence::Strong ? "strong"
+                                                                    : "weak");
+    llvm::errs() << "\nLOC: ";
+    Attr.Loc.dump(MigrateCtx.Pass.Ctx.getSourceManager());
+    llvm::errs() << "\nTYPE: ";
+    Attr.ModifiedType.dump();
+    if (Attr.Dcl) {
+      llvm::errs() << "DECL:\n";
+      Attr.Dcl->dump();
+    } else {
+      llvm::errs() << "DECL: NONE";
+    }
+    llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable;
+    llvm::errs() << "\n----------------\n";
+  }
+  llvm::errs() << "\n################\n";
+#endif
+}
index 94e965df188f38220428f639a2c2246fdfd08467..7c0819a677c8363efc890677ef452393912786ce 100644 (file)
@@ -27,13 +27,15 @@ class GCCollectableCallsChecker :
 public:
   GCCollectableCallsChecker(MigrationContext &ctx, ParentMap &map)
     : MigrateCtx(ctx), PMap(map) {
-    IdentifierTable &Ids = MigrateCtx.getPass().Ctx.Idents;
+    IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
     NSMakeCollectableII = &Ids.get("NSMakeCollectable");
     CFMakeCollectableII = &Ids.get("CFMakeCollectable");
   }
 
+  bool shouldWalkTypesOfTypeLocs() const { return false; }
+
   bool VisitCallExpr(CallExpr *E) {
-    TransformActions &TA = MigrateCtx.getPass().TA;
+    TransformActions &TA = MigrateCtx.Pass.TA;
 
     if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
       TA.reportError("call returns pointer to GC managed memory; "
index 6f9166fb9839c65f28a27af9e3b6485d89232c58..85eb156935c547b98916ea62657c63b74f8c2efc 100644 (file)
@@ -528,6 +528,6 @@ public:
 
 void PropertyRewriteTraverser::traverseObjCImplementation(
                                            ObjCImplementationContext &ImplCtx) {
-  PropertiesRewriter(ImplCtx.getMigrationContext().getPass())
+  PropertiesRewriter(ImplCtx.getMigrationContext().Pass)
                                   .doTransform(ImplCtx.getImplementationDecl());
 }
index 5ea454a917d8d42831161cf96f79d0876dc28cc0..c82f075bca8ca89f71871a1a3451127556b662ee 100644 (file)
@@ -302,6 +302,8 @@ class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
 public:
   ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
 
+  bool shouldWalkTypesOfTypeLocs() const { return false; }
+
   bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
     ObjCImplementationContext ImplCtx(MigrateCtx, D);
     for (MigrationContext::traverser_iterator
@@ -355,6 +357,10 @@ bool MigrationContext::isGCOwnedNonObjC(QualType T) {
 }
 
 void MigrationContext::traverse(TranslationUnitDecl *TU) {
+  for (traverser_iterator
+         I = traversers_begin(), E = traversers_end(); I != E; ++I)
+    (*I)->traverseTU(*this);
+
   ASTTransform(*this).TraverseDecl(TU);
 }
 
@@ -367,6 +373,7 @@ static void traverseAST(MigrationPass &pass) {
 
   if (pass.isGCMigration()) {
     MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
+    MigrateCtx.addTraverser(new GCAttrsTraverser());
   }
   MigrateCtx.addTraverser(new PropertyRewriteTraverser());
 
index 4ff35a5daf0d9d4dad1df6811c3b077f237656ed..540426b81a2b0a98344cdfc5faf51be2e3f0929e 100644 (file)
@@ -79,14 +79,26 @@ public:
 };
 
 class MigrationContext {
-  MigrationPass &Pass;
   std::vector<ASTTraverser *> Traversers;
 
 public:
+  MigrationPass &Pass;
+
+  struct GCAttrOccurrence {
+    enum AttrKind { Weak, Strong } Kind;
+    SourceLocation Loc;
+    QualType ModifiedType;
+    Decl *Dcl;
+    /// \brief true if the attribute is owned, e.g. it is in a body and not just
+    /// in an interface.
+    bool FullyMigratable;
+  };
+  std::vector<GCAttrOccurrence> GCAttrs;
+
+  llvm::DenseSet<unsigned> AttrSet;
+
   explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
   ~MigrationContext();
-
-  MigrationPass &getPass() { return Pass; }
   
   typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
   traverser_iterator traversers_begin() { return Traversers.begin(); }
@@ -108,6 +120,11 @@ public:
 
 // GC transformations
 
+class GCAttrsTraverser : public ASTTraverser {
+public:
+  virtual void traverseTU(MigrationContext &MigrateCtx);
+};
+
 class GCCollectableCallsTraverser : public ASTTraverser {
 public:
   virtual void traverseBody(BodyContext &BodyCtx);