aboutsummaryrefslogtreecommitdiff
path: root/lib/ARCMigrate
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-11-06 18:58:03 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-11-06 18:58:03 +0000
commitf38fa73e605587abfa32ab6a39887cdebc0a320a (patch)
tree1cc24e7bc9ce0a2354e62d1f8f0e867a8e271314 /lib/ARCMigrate
parentb0d5db1b7cac1a0680877c17fe92c6d64cf1c730 (diff)
[arcmt] Collect all the places where GC attributes __strong/__weak occur.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143883 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ARCMigrate')
-rw-r--r--lib/ARCMigrate/CMakeLists.txt1
-rw-r--r--lib/ARCMigrate/TransGCAttrs.cpp191
-rw-r--r--lib/ARCMigrate/TransGCCalls.cpp6
-rw-r--r--lib/ARCMigrate/TransProperties.cpp2
-rw-r--r--lib/ARCMigrate/Transforms.cpp7
-rw-r--r--lib/ARCMigrate/Transforms.h23
6 files changed, 224 insertions, 6 deletions
diff --git a/lib/ARCMigrate/CMakeLists.txt b/lib/ARCMigrate/CMakeLists.txt
index 90c2bbf54e..1a64b12721 100644
--- a/lib/ARCMigrate/CMakeLists.txt
+++ b/lib/ARCMigrate/CMakeLists.txt
@@ -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
index 0000000000..60573a44e8
--- /dev/null
+++ b/lib/ARCMigrate/TransGCAttrs.cpp
@@ -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
+}
diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp
index 94e965df18..7c0819a677 100644
--- a/lib/ARCMigrate/TransGCCalls.cpp
+++ b/lib/ARCMigrate/TransGCCalls.cpp
@@ -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; "
diff --git a/lib/ARCMigrate/TransProperties.cpp b/lib/ARCMigrate/TransProperties.cpp
index 6f9166fb98..85eb156935 100644
--- a/lib/ARCMigrate/TransProperties.cpp
+++ b/lib/ARCMigrate/TransProperties.cpp
@@ -528,6 +528,6 @@ public:
void PropertyRewriteTraverser::traverseObjCImplementation(
ObjCImplementationContext &ImplCtx) {
- PropertiesRewriter(ImplCtx.getMigrationContext().getPass())
+ PropertiesRewriter(ImplCtx.getMigrationContext().Pass)
.doTransform(ImplCtx.getImplementationDecl());
}
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 5ea454a917..c82f075bca 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -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());
diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h
index 4ff35a5daf..540426b81a 100644
--- a/lib/ARCMigrate/Transforms.h
+++ b/lib/ARCMigrate/Transforms.h
@@ -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);