[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / lib / ARCMigrate / Transforms.h
blob37e2d6b2a7e12f330def7434e8e365a7e06ce8ba
1 //===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
10 #define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
12 #include "clang/AST/ParentMap.h"
13 #include "clang/AST/RecursiveASTVisitor.h"
14 #include "llvm/ADT/DenseSet.h"
15 #include "llvm/Support/SaveAndRestore.h"
17 namespace clang {
18 class Decl;
19 class Stmt;
20 class BlockDecl;
21 class ObjCMethodDecl;
22 class FunctionDecl;
24 namespace arcmt {
25 class MigrationPass;
27 namespace trans {
29 class MigrationContext;
31 //===----------------------------------------------------------------------===//
32 // Transformations.
33 //===----------------------------------------------------------------------===//
35 void rewriteAutoreleasePool(MigrationPass &pass);
36 void rewriteUnbridgedCasts(MigrationPass &pass);
37 void makeAssignARCSafe(MigrationPass &pass);
38 void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
39 void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
40 void rewriteUnusedInitDelegate(MigrationPass &pass);
41 void checkAPIUses(MigrationPass &pass);
43 void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
45 class BodyContext {
46 MigrationContext &MigrateCtx;
47 ParentMap PMap;
48 Stmt *TopStmt;
50 public:
51 BodyContext(MigrationContext &MigrateCtx, Stmt *S)
52 : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
54 MigrationContext &getMigrationContext() { return MigrateCtx; }
55 ParentMap &getParentMap() { return PMap; }
56 Stmt *getTopStmt() { return TopStmt; }
59 class ObjCImplementationContext {
60 MigrationContext &MigrateCtx;
61 ObjCImplementationDecl *ImpD;
63 public:
64 ObjCImplementationContext(MigrationContext &MigrateCtx,
65 ObjCImplementationDecl *D)
66 : MigrateCtx(MigrateCtx), ImpD(D) {}
68 MigrationContext &getMigrationContext() { return MigrateCtx; }
69 ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
72 class ASTTraverser {
73 public:
74 virtual ~ASTTraverser();
75 virtual void traverseTU(MigrationContext &MigrateCtx) { }
76 virtual void traverseBody(BodyContext &BodyCtx) { }
77 virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
80 class MigrationContext {
81 std::vector<ASTTraverser *> Traversers;
83 public:
84 MigrationPass &Pass;
86 struct GCAttrOccurrence {
87 enum AttrKind { Weak, Strong } Kind;
88 SourceLocation Loc;
89 QualType ModifiedType;
90 Decl *Dcl;
91 /// true if the attribute is owned, e.g. it is in a body and not just
92 /// in an interface.
93 bool FullyMigratable;
95 std::vector<GCAttrOccurrence> GCAttrs;
96 llvm::DenseSet<SourceLocation> AttrSet;
97 llvm::DenseSet<SourceLocation> RemovedAttrSet;
99 /// Set of raw '@' locations for 'assign' properties group that contain
100 /// GC __weak.
101 llvm::DenseSet<SourceLocation> AtPropsWeak;
103 explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
104 ~MigrationContext();
106 typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
107 traverser_iterator traversers_begin() { return Traversers.begin(); }
108 traverser_iterator traversers_end() { return Traversers.end(); }
110 void addTraverser(ASTTraverser *traverser) {
111 Traversers.push_back(traverser);
114 bool isGCOwnedNonObjC(QualType T);
115 bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
116 return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
118 bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
119 SourceLocation atLoc);
120 bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
122 void traverse(TranslationUnitDecl *TU);
124 void dumpGCAttrs();
127 class PropertyRewriteTraverser : public ASTTraverser {
128 public:
129 void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override;
132 class BlockObjCVariableTraverser : public ASTTraverser {
133 public:
134 void traverseBody(BodyContext &BodyCtx) override;
137 class ProtectedScopeTraverser : public ASTTraverser {
138 public:
139 void traverseBody(BodyContext &BodyCtx) override;
142 // GC transformations
144 class GCAttrsTraverser : public ASTTraverser {
145 public:
146 void traverseTU(MigrationContext &MigrateCtx) override;
149 class GCCollectableCallsTraverser : public ASTTraverser {
150 public:
151 void traverseBody(BodyContext &BodyCtx) override;
154 //===----------------------------------------------------------------------===//
155 // Helpers.
156 //===----------------------------------------------------------------------===//
158 /// Determine whether we can add weak to the given type.
159 bool canApplyWeak(ASTContext &Ctx, QualType type,
160 bool AllowOnUnknownClass = false);
162 bool isPlusOneAssign(const BinaryOperator *E);
163 bool isPlusOne(const Expr *E);
165 /// 'Loc' is the end of a statement range. This returns the location
166 /// immediately after the semicolon following the statement.
167 /// If no semicolon is found or the location is inside a macro, the returned
168 /// source location will be invalid.
169 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,
170 bool IsDecl = false);
172 /// 'Loc' is the end of a statement range. This returns the location
173 /// of the semicolon following the statement.
174 /// If no semicolon is found or the location is inside a macro, the returned
175 /// source location will be invalid.
176 SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,
177 bool IsDecl = false);
179 bool hasSideEffects(Expr *E, ASTContext &Ctx);
180 bool isGlobalVar(Expr *E);
181 /// Returns "nil" or "0" if 'nil' macro is not actually defined.
182 StringRef getNilString(MigrationPass &Pass);
184 template <typename BODY_TRANS>
185 class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
186 MigrationPass &Pass;
187 Decl *ParentD;
189 typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
190 public:
191 BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
193 bool TraverseStmt(Stmt *rootS) {
194 if (rootS)
195 BODY_TRANS(Pass).transformBody(rootS, ParentD);
196 return true;
199 bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
200 SaveAndRestore<Decl *> SetParent(ParentD, D);
201 return base::TraverseObjCMethodDecl(D);
205 typedef llvm::DenseSet<Expr *> ExprSet;
207 void clearRefsIn(Stmt *S, ExprSet &refs);
208 template <typename iterator>
209 void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
210 for (; begin != end; ++begin)
211 clearRefsIn(*begin, refs);
214 void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
216 void collectRemovables(Stmt *S, ExprSet &exprs);
218 } // end namespace trans
220 } // end namespace arcmt
222 } // end namespace clang
224 #endif