diff options
Diffstat (limited to 'lib/ARCMigrate/Transforms.cpp')
-rw-r--r-- | lib/ARCMigrate/Transforms.cpp | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index d342d1a..1175c36 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -9,11 +9,14 @@ #include "Transforms.h" #include "Internals.h" -#include "clang/Sema/SemaDiagnostic.h" +#include "clang/Analysis/DomainSpecific/CocoaConventions.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Lex/Lexer.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/DenseSet.h" #include <map> @@ -24,6 +27,13 @@ using namespace trans; ASTTraverser::~ASTTraverser() { } +bool MigrationPass::CFBridgingFunctionsDefined() { + if (!EnableCFBridgeFns.hasValue()) + EnableCFBridgeFns = SemaRef.isKnownName("CFBridgingRetain") && + SemaRef.isKnownName("CFBridgingRelease"); + return *EnableCFBridgeFns; +} + //===----------------------------------------------------------------------===// // Helpers. //===----------------------------------------------------------------------===// @@ -56,6 +66,47 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type, return true; } +bool trans::isPlusOneAssign(const BinaryOperator *E) { + if (E->getOpcode() != BO_Assign) + return false; + + if (const ObjCMessageExpr * + ME = dyn_cast<ObjCMessageExpr>(E->getRHS()->IgnoreParenCasts())) + if (ME->getMethodFamily() == OMF_retain) + return true; + + if (const CallExpr * + callE = dyn_cast<CallExpr>(E->getRHS()->IgnoreParenCasts())) { + if (const FunctionDecl *FD = callE->getDirectCallee()) { + if (FD->getAttr<CFReturnsRetainedAttr>()) + return true; + + if (FD->isGlobal() && + FD->getIdentifier() && + FD->getParent()->isTranslationUnit() && + FD->getLinkage() == ExternalLinkage && + ento::cocoa::isRefType(callE->getType(), "CF", + FD->getIdentifier()->getName())) { + StringRef fname = FD->getIdentifier()->getName(); + if (fname.endswith("Retain") || + fname.find("Create") != StringRef::npos || + fname.find("Copy") != StringRef::npos) { + return true; + } + } + } + } + + const ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS()); + while (implCE && implCE->getCastKind() == CK_BitCast) + implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr()); + + if (implCE && implCE->getCastKind() == CK_ARCConsumeObject) + return true; + + return false; +} + /// \brief 'Loc' is the end of a statement range. This returns the location /// immediately after the semicolon following the statement. /// If no semicolon is found or the location is inside a macro, the returned @@ -472,8 +523,8 @@ static void GCRewriteFinalize(MigrationPass &pass) { for (impl_iterator I = impl_iterator(DC->decls_begin()), E = impl_iterator(DC->decls_end()); I != E; ++I) { for (ObjCImplementationDecl::instmeth_iterator - MI = (*I)->instmeth_begin(), - ME = (*I)->instmeth_end(); MI != ME; ++MI) { + MI = I->instmeth_begin(), + ME = I->instmeth_end(); MI != ME; ++MI) { ObjCMethodDecl *MD = *MI; if (!MD->hasBody()) continue; |