1 //===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
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
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"
29 class MigrationContext
;
31 //===----------------------------------------------------------------------===//
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
);
46 MigrationContext
&MigrateCtx
;
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
;
64 ObjCImplementationContext(MigrationContext
&MigrateCtx
,
65 ObjCImplementationDecl
*D
)
66 : MigrateCtx(MigrateCtx
), ImpD(D
) {}
68 MigrationContext
&getMigrationContext() { return MigrateCtx
; }
69 ObjCImplementationDecl
*getImplementationDecl() { return ImpD
; }
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
;
86 struct GCAttrOccurrence
{
87 enum AttrKind
{ Weak
, Strong
} Kind
;
89 QualType ModifiedType
;
91 /// true if the attribute is owned, e.g. it is in a body and not just
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
101 llvm::DenseSet
<SourceLocation
> AtPropsWeak
;
103 explicit MigrationContext(MigrationPass
&pass
) : Pass(pass
) {}
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
);
127 class PropertyRewriteTraverser
: public ASTTraverser
{
129 void traverseObjCImplementation(ObjCImplementationContext
&ImplCtx
) override
;
132 class BlockObjCVariableTraverser
: public ASTTraverser
{
134 void traverseBody(BodyContext
&BodyCtx
) override
;
137 class ProtectedScopeTraverser
: public ASTTraverser
{
139 void traverseBody(BodyContext
&BodyCtx
) override
;
142 // GC transformations
144 class GCAttrsTraverser
: public ASTTraverser
{
146 void traverseTU(MigrationContext
&MigrateCtx
) override
;
149 class GCCollectableCallsTraverser
: public ASTTraverser
{
151 void traverseBody(BodyContext
&BodyCtx
) override
;
154 //===----------------------------------------------------------------------===//
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
> > {
189 typedef RecursiveASTVisitor
<BodyTransform
<BODY_TRANS
> > base
;
191 BodyTransform(MigrationPass
&pass
) : Pass(pass
), ParentD(nullptr) { }
193 bool TraverseStmt(Stmt
*rootS
) {
195 BODY_TRANS(Pass
).transformBody(rootS
, ParentD
);
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