1249423Sdim//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===// 2224135Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6224135Sdim// 7224135Sdim//===----------------------------------------------------------------------===// 8224135Sdim 9224135Sdim#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 10224135Sdim#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H 11224135Sdim 12249423Sdim#include "clang/AST/ParentMap.h" 13224135Sdim#include "clang/AST/RecursiveASTVisitor.h" 14224135Sdim#include "llvm/ADT/DenseSet.h" 15239462Sdim#include "llvm/Support/SaveAndRestore.h" 16224135Sdim 17224135Sdimnamespace clang { 18224135Sdim class Decl; 19224135Sdim class Stmt; 20224135Sdim class BlockDecl; 21224135Sdim class ObjCMethodDecl; 22224135Sdim class FunctionDecl; 23224135Sdim 24224135Sdimnamespace arcmt { 25224135Sdim class MigrationPass; 26224135Sdim 27224135Sdimnamespace trans { 28224135Sdim 29234353Sdim class MigrationContext; 30234353Sdim 31224135Sdim//===----------------------------------------------------------------------===// 32224135Sdim// Transformations. 33224135Sdim//===----------------------------------------------------------------------===// 34224135Sdim 35224135Sdimvoid rewriteAutoreleasePool(MigrationPass &pass); 36224135Sdimvoid rewriteUnbridgedCasts(MigrationPass &pass); 37224135Sdimvoid makeAssignARCSafe(MigrationPass &pass); 38234353Sdimvoid removeRetainReleaseDeallocFinalize(MigrationPass &pass); 39234353Sdimvoid removeZeroOutPropsInDeallocFinalize(MigrationPass &pass); 40224135Sdimvoid rewriteUnusedInitDelegate(MigrationPass &pass); 41226633Sdimvoid checkAPIUses(MigrationPass &pass); 42224135Sdim 43234353Sdimvoid removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass); 44224135Sdim 45234353Sdimclass BodyContext { 46234353Sdim MigrationContext &MigrateCtx; 47234353Sdim ParentMap PMap; 48234353Sdim Stmt *TopStmt; 49234353Sdim 50234353Sdimpublic: 51234353Sdim BodyContext(MigrationContext &MigrateCtx, Stmt *S) 52234353Sdim : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {} 53234353Sdim 54234353Sdim MigrationContext &getMigrationContext() { return MigrateCtx; } 55234353Sdim ParentMap &getParentMap() { return PMap; } 56234353Sdim Stmt *getTopStmt() { return TopStmt; } 57234353Sdim}; 58234353Sdim 59234353Sdimclass ObjCImplementationContext { 60234353Sdim MigrationContext &MigrateCtx; 61234353Sdim ObjCImplementationDecl *ImpD; 62234353Sdim 63234353Sdimpublic: 64234353Sdim ObjCImplementationContext(MigrationContext &MigrateCtx, 65234353Sdim ObjCImplementationDecl *D) 66234353Sdim : MigrateCtx(MigrateCtx), ImpD(D) {} 67234353Sdim 68234353Sdim MigrationContext &getMigrationContext() { return MigrateCtx; } 69234353Sdim ObjCImplementationDecl *getImplementationDecl() { return ImpD; } 70234353Sdim}; 71234353Sdim 72234353Sdimclass ASTTraverser { 73234353Sdimpublic: 74234353Sdim virtual ~ASTTraverser(); 75234353Sdim virtual void traverseTU(MigrationContext &MigrateCtx) { } 76234353Sdim virtual void traverseBody(BodyContext &BodyCtx) { } 77234353Sdim virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {} 78234353Sdim}; 79234353Sdim 80234353Sdimclass MigrationContext { 81234353Sdim std::vector<ASTTraverser *> Traversers; 82234353Sdim 83234353Sdimpublic: 84234353Sdim MigrationPass &Pass; 85234353Sdim 86234353Sdim struct GCAttrOccurrence { 87234353Sdim enum AttrKind { Weak, Strong } Kind; 88234353Sdim SourceLocation Loc; 89234353Sdim QualType ModifiedType; 90234353Sdim Decl *Dcl; 91341825Sdim /// true if the attribute is owned, e.g. it is in a body and not just 92234353Sdim /// in an interface. 93234353Sdim bool FullyMigratable; 94234353Sdim }; 95234353Sdim std::vector<GCAttrOccurrence> GCAttrs; 96234353Sdim llvm::DenseSet<unsigned> AttrSet; 97234353Sdim llvm::DenseSet<unsigned> RemovedAttrSet; 98234353Sdim 99341825Sdim /// Set of raw '@' locations for 'assign' properties group that contain 100234353Sdim /// GC __weak. 101234353Sdim llvm::DenseSet<unsigned> AtPropsWeak; 102234353Sdim 103234353Sdim explicit MigrationContext(MigrationPass &pass) : Pass(pass) {} 104234353Sdim ~MigrationContext(); 105341825Sdim 106234353Sdim typedef std::vector<ASTTraverser *>::iterator traverser_iterator; 107234353Sdim traverser_iterator traversers_begin() { return Traversers.begin(); } 108234353Sdim traverser_iterator traversers_end() { return Traversers.end(); } 109234353Sdim 110234353Sdim void addTraverser(ASTTraverser *traverser) { 111234353Sdim Traversers.push_back(traverser); 112234353Sdim } 113234353Sdim 114234353Sdim bool isGCOwnedNonObjC(QualType T); 115234353Sdim bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) { 116234353Sdim return rewritePropertyAttribute(fromAttr, StringRef(), atLoc); 117234353Sdim } 118234353Sdim bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, 119234353Sdim SourceLocation atLoc); 120234353Sdim bool addPropertyAttribute(StringRef attr, SourceLocation atLoc); 121234353Sdim 122234353Sdim void traverse(TranslationUnitDecl *TU); 123234353Sdim 124234353Sdim void dumpGCAttrs(); 125234353Sdim}; 126234353Sdim 127234353Sdimclass PropertyRewriteTraverser : public ASTTraverser { 128234353Sdimpublic: 129276479Sdim void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override; 130234353Sdim}; 131234353Sdim 132234353Sdimclass BlockObjCVariableTraverser : public ASTTraverser { 133234353Sdimpublic: 134276479Sdim void traverseBody(BodyContext &BodyCtx) override; 135234353Sdim}; 136234353Sdim 137249423Sdimclass ProtectedScopeTraverser : public ASTTraverser { 138249423Sdimpublic: 139276479Sdim void traverseBody(BodyContext &BodyCtx) override; 140249423Sdim}; 141249423Sdim 142234353Sdim// GC transformations 143234353Sdim 144234353Sdimclass GCAttrsTraverser : public ASTTraverser { 145234353Sdimpublic: 146276479Sdim void traverseTU(MigrationContext &MigrateCtx) override; 147234353Sdim}; 148234353Sdim 149234353Sdimclass GCCollectableCallsTraverser : public ASTTraverser { 150234353Sdimpublic: 151276479Sdim void traverseBody(BodyContext &BodyCtx) override; 152234353Sdim}; 153234353Sdim 154224135Sdim//===----------------------------------------------------------------------===// 155224135Sdim// Helpers. 156224135Sdim//===----------------------------------------------------------------------===// 157224135Sdim 158341825Sdim/// Determine whether we can add weak to the given type. 159234353Sdimbool canApplyWeak(ASTContext &Ctx, QualType type, 160234353Sdim bool AllowOnUnknownClass = false); 161224135Sdim 162239462Sdimbool isPlusOneAssign(const BinaryOperator *E); 163249423Sdimbool isPlusOne(const Expr *E); 164239462Sdim 165341825Sdim/// 'Loc' is the end of a statement range. This returns the location 166224135Sdim/// immediately after the semicolon following the statement. 167224135Sdim/// If no semicolon is found or the location is inside a macro, the returned 168224135Sdim/// source location will be invalid. 169261991SdimSourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, 170261991Sdim bool IsDecl = false); 171224135Sdim 172341825Sdim/// 'Loc' is the end of a statement range. This returns the location 173226633Sdim/// of the semicolon following the statement. 174226633Sdim/// If no semicolon is found or the location is inside a macro, the returned 175226633Sdim/// source location will be invalid. 176261991SdimSourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, 177261991Sdim bool IsDecl = false); 178226633Sdim 179224135Sdimbool hasSideEffects(Expr *E, ASTContext &Ctx); 180224135Sdimbool isGlobalVar(Expr *E); 181341825Sdim/// Returns "nil" or "0" if 'nil' macro is not actually defined. 182288943SdimStringRef getNilString(MigrationPass &Pass); 183224135Sdim 184224135Sdimtemplate <typename BODY_TRANS> 185224135Sdimclass BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { 186224135Sdim MigrationPass &Pass; 187239462Sdim Decl *ParentD; 188224135Sdim 189239462Sdim typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base; 190224135Sdimpublic: 191276479Sdim BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { } 192224135Sdim 193224135Sdim bool TraverseStmt(Stmt *rootS) { 194226633Sdim if (rootS) 195239462Sdim BODY_TRANS(Pass).transformBody(rootS, ParentD); 196224135Sdim return true; 197224135Sdim } 198239462Sdim 199239462Sdim bool TraverseObjCMethodDecl(ObjCMethodDecl *D) { 200239462Sdim SaveAndRestore<Decl *> SetParent(ParentD, D); 201239462Sdim return base::TraverseObjCMethodDecl(D); 202239462Sdim } 203224135Sdim}; 204224135Sdim 205224135Sdimtypedef llvm::DenseSet<Expr *> ExprSet; 206224135Sdim 207224135Sdimvoid clearRefsIn(Stmt *S, ExprSet &refs); 208224135Sdimtemplate <typename iterator> 209224135Sdimvoid clearRefsIn(iterator begin, iterator end, ExprSet &refs) { 210224135Sdim for (; begin != end; ++begin) 211224135Sdim clearRefsIn(*begin, refs); 212224135Sdim} 213224135Sdim 214224135Sdimvoid collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs); 215224135Sdim 216224135Sdimvoid collectRemovables(Stmt *S, ExprSet &exprs); 217224135Sdim 218224135Sdim} // end namespace trans 219224135Sdim 220224135Sdim} // end namespace arcmt 221224135Sdim 222224135Sdim} // end namespace clang 223224135Sdim 224224135Sdim#endif 225