Path: blob/main/contrib/llvm-project/clang/lib/ARCMigrate/Transforms.h
35236 views
//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H9#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H1011#include "clang/AST/ParentMap.h"12#include "clang/AST/RecursiveASTVisitor.h"13#include "llvm/ADT/DenseSet.h"14#include "llvm/Support/SaveAndRestore.h"1516namespace clang {17class Decl;18class Stmt;19class BlockDecl;20class ObjCMethodDecl;21class FunctionDecl;2223namespace arcmt {24class MigrationPass;2526namespace trans {2728class MigrationContext;2930//===----------------------------------------------------------------------===//31// Transformations.32//===----------------------------------------------------------------------===//3334void rewriteAutoreleasePool(MigrationPass &pass);35void rewriteUnbridgedCasts(MigrationPass &pass);36void makeAssignARCSafe(MigrationPass &pass);37void removeRetainReleaseDeallocFinalize(MigrationPass &pass);38void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);39void rewriteUnusedInitDelegate(MigrationPass &pass);40void checkAPIUses(MigrationPass &pass);4142void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);4344class BodyContext {45MigrationContext &MigrateCtx;46ParentMap PMap;47Stmt *TopStmt;4849public:50BodyContext(MigrationContext &MigrateCtx, Stmt *S)51: MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}5253MigrationContext &getMigrationContext() { return MigrateCtx; }54ParentMap &getParentMap() { return PMap; }55Stmt *getTopStmt() { return TopStmt; }56};5758class ObjCImplementationContext {59MigrationContext &MigrateCtx;60ObjCImplementationDecl *ImpD;6162public:63ObjCImplementationContext(MigrationContext &MigrateCtx,64ObjCImplementationDecl *D)65: MigrateCtx(MigrateCtx), ImpD(D) {}6667MigrationContext &getMigrationContext() { return MigrateCtx; }68ObjCImplementationDecl *getImplementationDecl() { return ImpD; }69};7071class ASTTraverser {72public:73virtual ~ASTTraverser();74virtual void traverseTU(MigrationContext &MigrateCtx) { }75virtual void traverseBody(BodyContext &BodyCtx) { }76virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}77};7879class MigrationContext {80std::vector<ASTTraverser *> Traversers;8182public:83MigrationPass &Pass;8485struct GCAttrOccurrence {86enum AttrKind { Weak, Strong } Kind;87SourceLocation Loc;88QualType ModifiedType;89Decl *Dcl;90/// true if the attribute is owned, e.g. it is in a body and not just91/// in an interface.92bool FullyMigratable;93};94std::vector<GCAttrOccurrence> GCAttrs;95llvm::DenseSet<SourceLocation> AttrSet;96llvm::DenseSet<SourceLocation> RemovedAttrSet;9798/// Set of raw '@' locations for 'assign' properties group that contain99/// GC __weak.100llvm::DenseSet<SourceLocation> AtPropsWeak;101102explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}103~MigrationContext();104105typedef std::vector<ASTTraverser *>::iterator traverser_iterator;106traverser_iterator traversers_begin() { return Traversers.begin(); }107traverser_iterator traversers_end() { return Traversers.end(); }108109void addTraverser(ASTTraverser *traverser) {110Traversers.push_back(traverser);111}112113bool isGCOwnedNonObjC(QualType T);114bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {115return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);116}117bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,118SourceLocation atLoc);119bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);120121void traverse(TranslationUnitDecl *TU);122123void dumpGCAttrs();124};125126class PropertyRewriteTraverser : public ASTTraverser {127public:128void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override;129};130131class BlockObjCVariableTraverser : public ASTTraverser {132public:133void traverseBody(BodyContext &BodyCtx) override;134};135136class ProtectedScopeTraverser : public ASTTraverser {137public:138void traverseBody(BodyContext &BodyCtx) override;139};140141// GC transformations142143class GCAttrsTraverser : public ASTTraverser {144public:145void traverseTU(MigrationContext &MigrateCtx) override;146};147148class GCCollectableCallsTraverser : public ASTTraverser {149public:150void traverseBody(BodyContext &BodyCtx) override;151};152153//===----------------------------------------------------------------------===//154// Helpers.155//===----------------------------------------------------------------------===//156157/// Determine whether we can add weak to the given type.158bool canApplyWeak(ASTContext &Ctx, QualType type,159bool AllowOnUnknownClass = false);160161bool isPlusOneAssign(const BinaryOperator *E);162bool isPlusOne(const Expr *E);163164/// 'Loc' is the end of a statement range. This returns the location165/// immediately after the semicolon following the statement.166/// If no semicolon is found or the location is inside a macro, the returned167/// source location will be invalid.168SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,169bool IsDecl = false);170171/// 'Loc' is the end of a statement range. This returns the location172/// of the semicolon following the statement.173/// If no semicolon is found or the location is inside a macro, the returned174/// source location will be invalid.175SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,176bool IsDecl = false);177178bool hasSideEffects(Expr *E, ASTContext &Ctx);179bool isGlobalVar(Expr *E);180/// Returns "nil" or "0" if 'nil' macro is not actually defined.181StringRef getNilString(MigrationPass &Pass);182183template <typename BODY_TRANS>184class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {185MigrationPass &Pass;186Decl *ParentD;187188typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;189public:190BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }191192bool TraverseStmt(Stmt *rootS) {193if (rootS)194BODY_TRANS(Pass).transformBody(rootS, ParentD);195return true;196}197198bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {199SaveAndRestore<Decl *> SetParent(ParentD, D);200return base::TraverseObjCMethodDecl(D);201}202};203204typedef llvm::DenseSet<Expr *> ExprSet;205206void clearRefsIn(Stmt *S, ExprSet &refs);207template <typename iterator>208void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {209for (; begin != end; ++begin)210clearRefsIn(*begin, refs);211}212213void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);214215void collectRemovables(Stmt *S, ExprSet &exprs);216217} // end namespace trans218219} // end namespace arcmt220221} // end namespace clang222223#endif224225226