blob: e208e8471bd78f62bf6fa9b0786f069ed7037664 [file] [log] [blame]
John McCalld70fb982011-06-15 23:25:17 +00001//===--- Tranforms.cpp - Tranformations to ARC mode -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
John McCalld70fb982011-06-15 23:25:17 +00009
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000010#include "Transforms.h"
John McCalld70fb982011-06-15 23:25:17 +000011#include "Internals.h"
12#include "clang/Sema/SemaDiagnostic.h"
13#include "clang/AST/RecursiveASTVisitor.h"
14#include "clang/AST/StmtVisitor.h"
John McCalld70fb982011-06-15 23:25:17 +000015#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
16#include "clang/Lex/Lexer.h"
17#include "clang/Basic/SourceManager.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/ADT/DenseSet.h"
20#include <map>
21
22using namespace clang;
23using namespace arcmt;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000024using namespace trans;
John McCalld70fb982011-06-15 23:25:17 +000025
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000026ASTTraverser::~ASTTraverser() { }
27
John McCalld70fb982011-06-15 23:25:17 +000028//===----------------------------------------------------------------------===//
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000029// Helpers.
John McCalld70fb982011-06-15 23:25:17 +000030//===----------------------------------------------------------------------===//
31
Argyrios Kyrtzidisce9b7392011-07-12 22:05:17 +000032/// \brief True if the class is one that does not support weak.
33static bool isClassInWeakBlacklist(ObjCInterfaceDecl *cls) {
34 if (!cls)
35 return false;
36
37 bool inList = llvm::StringSwitch<bool>(cls->getName())
38 .Case("NSColorSpace", true)
39 .Case("NSFont", true)
40 .Case("NSFontPanel", true)
41 .Case("NSImage", true)
42 .Case("NSLazyBrowserCell", true)
43 .Case("NSWindow", true)
44 .Case("NSWindowController", true)
Argyrios Kyrtzidis3befb8c2011-11-08 05:56:08 +000045 .Case("NSViewController", true)
Argyrios Kyrtzidisce9b7392011-07-12 22:05:17 +000046 .Case("NSMenuView", true)
47 .Case("NSPersistentUIWindowInfo", true)
48 .Case("NSTableCellView", true)
49 .Case("NSATSTypeSetter", true)
50 .Case("NSATSGlyphStorage", true)
51 .Case("NSLineFragmentRenderingContext", true)
52 .Case("NSAttributeDictionary", true)
53 .Case("NSParagraphStyle", true)
54 .Case("NSTextTab", true)
55 .Case("NSSimpleHorizontalTypesetter", true)
56 .Case("_NSCachedAttributedString", true)
57 .Case("NSStringDrawingTextStorage", true)
58 .Case("NSTextView", true)
59 .Case("NSSubTextStorage", true)
60 .Default(false);
61
62 if (inList)
63 return true;
64
65 return isClassInWeakBlacklist(cls->getSuperClass());
66}
67
Argyrios Kyrtzidise80d4f22011-11-07 18:40:29 +000068bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
69 bool AllowOnUnknownClass) {
Argyrios Kyrtzidisce9b7392011-07-12 22:05:17 +000070 if (!Ctx.getLangOptions().ObjCRuntimeHasWeak)
71 return false;
72
73 QualType T = type;
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +000074 if (T.isNull())
75 return false;
76
Argyrios Kyrtzidisce9b7392011-07-12 22:05:17 +000077 while (const PointerType *ptr = T->getAs<PointerType>())
78 T = ptr->getPointeeType();
79 if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
80 ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
Argyrios Kyrtzidise80d4f22011-11-07 18:40:29 +000081 if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
Argyrios Kyrtzidisce9b7392011-07-12 22:05:17 +000082 return false; // id/NSObject is not safe for weak.
Argyrios Kyrtzidise80d4f22011-11-07 18:40:29 +000083 if (!AllowOnUnknownClass && Class->isForwardDecl())
Argyrios Kyrtzidisa2009732011-07-12 22:16:25 +000084 return false; // forward classes are not verifiable, therefore not safe.
Argyrios Kyrtzidisce9b7392011-07-12 22:05:17 +000085 if (Class->isArcWeakrefUnavailable())
86 return false;
87 if (isClassInWeakBlacklist(Class))
88 return false;
89 }
90
91 return true;
92}
93
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +000094/// \brief 'Loc' is the end of a statement range. This returns the location
95/// immediately after the semicolon following the statement.
96/// If no semicolon is found or the location is inside a macro, the returned
97/// source location will be invalid.
98SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
99 ASTContext &Ctx) {
Argyrios Kyrtzidiscbbc0142011-09-01 20:53:18 +0000100 SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
101 if (SemiLoc.isInvalid())
102 return SourceLocation();
Argyrios Kyrtzidise6e67de2011-09-19 20:40:19 +0000103 return SemiLoc.getLocWithOffset(1);
Argyrios Kyrtzidiscbbc0142011-09-01 20:53:18 +0000104}
105
106/// \brief \arg Loc is the end of a statement range. This returns the location
107/// of the semicolon following the statement.
108/// If no semicolon is found or the location is inside a macro, the returned
109/// source location will be invalid.
110SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
111 ASTContext &Ctx) {
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000112 SourceManager &SM = Ctx.getSourceManager();
113 if (loc.isMacroID()) {
Chandler Carruthe2c09eb2011-07-14 08:20:40 +0000114 if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000115 return SourceLocation();
Chandler Carruth6d28d7f2011-07-25 16:56:02 +0000116 loc = SM.getExpansionRange(loc).second;
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000117 }
118 loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
119
120 // Break down the source location.
121 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
122
123 // Try to load the file buffer.
124 bool invalidTemp = false;
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000125 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000126 if (invalidTemp)
127 return SourceLocation();
128
129 const char *tokenBegin = file.data() + locInfo.second;
130
131 // Lex from the start of the given location.
132 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
133 Ctx.getLangOptions(),
134 file.begin(), tokenBegin, file.end());
135 Token tok;
136 lexer.LexFromRawLexer(tok);
137 if (tok.isNot(tok::semi))
138 return SourceLocation();
139
Argyrios Kyrtzidiscbbc0142011-09-01 20:53:18 +0000140 return tok.getLocation();
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000141}
142
143bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
144 if (!E || !E->HasSideEffects(Ctx))
145 return false;
146
147 E = E->IgnoreParenCasts();
148 ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
149 if (!ME)
150 return true;
151 switch (ME->getMethodFamily()) {
152 case OMF_autorelease:
153 case OMF_dealloc:
154 case OMF_release:
155 case OMF_retain:
156 switch (ME->getReceiverKind()) {
157 case ObjCMessageExpr::SuperInstance:
158 return false;
159 case ObjCMessageExpr::Instance:
160 return hasSideEffects(ME->getInstanceReceiver(), Ctx);
161 default:
162 break;
163 }
164 break;
165 default:
166 break;
167 }
168
169 return true;
170}
171
Argyrios Kyrtzidisf2a27f42011-07-14 23:32:04 +0000172bool trans::isGlobalVar(Expr *E) {
173 E = E->IgnoreParenCasts();
174 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000175 return DRE->getDecl()->getDeclContext()->isFileContext() &&
176 DRE->getDecl()->getLinkage() == ExternalLinkage;
Argyrios Kyrtzidisf2a27f42011-07-14 23:32:04 +0000177 if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
178 return isGlobalVar(condOp->getTrueExpr()) &&
179 isGlobalVar(condOp->getFalseExpr());
180
181 return false;
182}
183
Argyrios Kyrtzidis93907472011-07-27 05:28:18 +0000184StringRef trans::getNilString(ASTContext &Ctx) {
185 if (Ctx.Idents.get("nil").hasMacroDefinition())
186 return "nil";
187 else
188 return "0";
189}
190
John McCalld70fb982011-06-15 23:25:17 +0000191namespace {
192
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000193class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
194 ExprSet &Refs;
195public:
196 ReferenceClear(ExprSet &refs) : Refs(refs) { }
197 bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
198 bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Refs.erase(E); return true; }
199};
200
201class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
202 ValueDecl *Dcl;
203 ExprSet &Refs;
John McCalld70fb982011-06-15 23:25:17 +0000204
205public:
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000206 ReferenceCollector(ValueDecl *D, ExprSet &refs)
207 : Dcl(D), Refs(refs) { }
208
209 bool VisitDeclRefExpr(DeclRefExpr *E) {
210 if (E->getDecl() == Dcl)
211 Refs.insert(E);
212 return true;
213 }
214
215 bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
216 if (E->getDecl() == Dcl)
217 Refs.insert(E);
218 return true;
219 }
220};
221
222class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
223 ExprSet &Removables;
224
225public:
226 RemovablesCollector(ExprSet &removables)
John McCalld70fb982011-06-15 23:25:17 +0000227 : Removables(removables) { }
228
229 bool shouldWalkTypesOfTypeLocs() const { return false; }
230
231 bool TraverseStmtExpr(StmtExpr *E) {
232 CompoundStmt *S = E->getSubStmt();
233 for (CompoundStmt::body_iterator
234 I = S->body_begin(), E = S->body_end(); I != E; ++I) {
235 if (I != E - 1)
236 mark(*I);
237 TraverseStmt(*I);
238 }
239 return true;
240 }
241
242 bool VisitCompoundStmt(CompoundStmt *S) {
243 for (CompoundStmt::body_iterator
244 I = S->body_begin(), E = S->body_end(); I != E; ++I)
245 mark(*I);
246 return true;
247 }
248
249 bool VisitIfStmt(IfStmt *S) {
250 mark(S->getThen());
251 mark(S->getElse());
252 return true;
253 }
254
255 bool VisitWhileStmt(WhileStmt *S) {
256 mark(S->getBody());
257 return true;
258 }
259
260 bool VisitDoStmt(DoStmt *S) {
261 mark(S->getBody());
262 return true;
263 }
264
265 bool VisitForStmt(ForStmt *S) {
266 mark(S->getInit());
267 mark(S->getInc());
268 mark(S->getBody());
269 return true;
270 }
271
272private:
273 void mark(Stmt *S) {
274 if (!S) return;
275
John McCall4db5c3c2011-07-07 06:58:02 +0000276 while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
277 S = Label->getSubStmt();
278 S = S->IgnoreImplicit();
John McCalld70fb982011-06-15 23:25:17 +0000279 if (Expr *E = dyn_cast<Expr>(S))
280 Removables.insert(E);
281 }
282};
283
John McCalld70fb982011-06-15 23:25:17 +0000284} // end anonymous namespace
285
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000286void trans::clearRefsIn(Stmt *S, ExprSet &refs) {
287 ReferenceClear(refs).TraverseStmt(S);
John McCalld70fb982011-06-15 23:25:17 +0000288}
289
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000290void trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
291 ReferenceCollector(D, refs).TraverseStmt(S);
John McCalld70fb982011-06-15 23:25:17 +0000292}
293
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000294void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
295 RemovablesCollector(exprs).TraverseStmt(S);
John McCalld70fb982011-06-15 23:25:17 +0000296}
297
298//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000299// MigrationContext
300//===----------------------------------------------------------------------===//
301
302namespace {
303
304class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
305 MigrationContext &MigrateCtx;
Argyrios Kyrtzidisd5697912011-11-07 18:46:50 +0000306 typedef RecursiveASTVisitor<ASTTransform> base;
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000307
308public:
309 ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
310
Argyrios Kyrtzidise43ae792011-11-06 18:58:03 +0000311 bool shouldWalkTypesOfTypeLocs() const { return false; }
312
Argyrios Kyrtzidisaaa99962011-11-06 18:57:57 +0000313 bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
314 ObjCImplementationContext ImplCtx(MigrateCtx, D);
315 for (MigrationContext::traverser_iterator
316 I = MigrateCtx.traversers_begin(),
317 E = MigrateCtx.traversers_end(); I != E; ++I)
318 (*I)->traverseObjCImplementation(ImplCtx);
319
Argyrios Kyrtzidisd5697912011-11-07 18:46:50 +0000320 return base::TraverseObjCImplementationDecl(D);
Argyrios Kyrtzidisaaa99962011-11-06 18:57:57 +0000321 }
322
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000323 bool TraverseStmt(Stmt *rootS) {
324 if (!rootS)
325 return true;
326
327 BodyContext BodyCtx(MigrateCtx, rootS);
328 for (MigrationContext::traverser_iterator
329 I = MigrateCtx.traversers_begin(),
330 E = MigrateCtx.traversers_end(); I != E; ++I)
331 (*I)->traverseBody(BodyCtx);
332
333 return true;
334 }
335};
336
337}
338
339MigrationContext::~MigrationContext() {
340 for (traverser_iterator
341 I = traversers_begin(), E = traversers_end(); I != E; ++I)
342 delete *I;
343}
344
Argyrios Kyrtzidis6b2d47d2011-11-04 23:43:03 +0000345bool MigrationContext::isGCOwnedNonObjC(QualType T) {
346 while (!T.isNull()) {
347 if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
348 if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
349 return !AttrT->getModifiedType()->isObjCRetainableType();
350 }
351
352 if (T->isArrayType())
353 T = Pass.Ctx.getBaseElementType(T);
354 else if (const PointerType *PT = T->getAs<PointerType>())
355 T = PT->getPointeeType();
356 else if (const ReferenceType *RT = T->getAs<ReferenceType>())
357 T = RT->getPointeeType();
358 else
359 break;
360 }
361
362 return false;
363}
364
Argyrios Kyrtzidis722d21c2011-11-07 18:46:46 +0000365bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
366 StringRef toAttr,
367 SourceLocation atLoc) {
368 if (atLoc.isMacroID())
369 return false;
370
371 SourceManager &SM = Pass.Ctx.getSourceManager();
372
373 // Break down the source location.
374 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
375
376 // Try to load the file buffer.
377 bool invalidTemp = false;
378 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
379 if (invalidTemp)
380 return false;
381
382 const char *tokenBegin = file.data() + locInfo.second;
383
384 // Lex from the start of the given location.
385 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
386 Pass.Ctx.getLangOptions(),
387 file.begin(), tokenBegin, file.end());
388 Token tok;
389 lexer.LexFromRawLexer(tok);
390 if (tok.isNot(tok::at)) return false;
391 lexer.LexFromRawLexer(tok);
392 if (tok.isNot(tok::raw_identifier)) return false;
393 if (StringRef(tok.getRawIdentifierData(), tok.getLength())
394 != "property")
395 return false;
396 lexer.LexFromRawLexer(tok);
397 if (tok.isNot(tok::l_paren)) return false;
398
399 Token BeforeTok = tok;
400 Token AfterTok;
401 AfterTok.startToken();
402 SourceLocation AttrLoc;
403
404 lexer.LexFromRawLexer(tok);
405 if (tok.is(tok::r_paren))
406 return false;
407
408 while (1) {
409 if (tok.isNot(tok::raw_identifier)) return false;
410 StringRef ident(tok.getRawIdentifierData(), tok.getLength());
411 if (ident == fromAttr) {
412 if (!toAttr.empty()) {
413 Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
414 return true;
415 }
416 // We want to remove the attribute.
417 AttrLoc = tok.getLocation();
418 }
419
420 do {
421 lexer.LexFromRawLexer(tok);
422 if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
423 AfterTok = tok;
424 } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
425 if (tok.is(tok::r_paren))
426 break;
427 if (AttrLoc.isInvalid())
428 BeforeTok = tok;
429 lexer.LexFromRawLexer(tok);
430 }
431
432 if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
433 // We want to remove the attribute.
434 if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
435 Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
436 AfterTok.getLocation()));
437 } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
438 Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
439 } else {
440 Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
441 }
442
443 return true;
444 }
445
446 return false;
447}
448
Argyrios Kyrtzidiseca1f362011-11-28 02:04:36 +0000449bool MigrationContext::addPropertyAttribute(StringRef attr,
450 SourceLocation atLoc) {
451 if (atLoc.isMacroID())
452 return false;
453
454 SourceManager &SM = Pass.Ctx.getSourceManager();
455
456 // Break down the source location.
457 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
458
459 // Try to load the file buffer.
460 bool invalidTemp = false;
461 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
462 if (invalidTemp)
463 return false;
464
465 const char *tokenBegin = file.data() + locInfo.second;
466
467 // Lex from the start of the given location.
468 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
469 Pass.Ctx.getLangOptions(),
470 file.begin(), tokenBegin, file.end());
471 Token tok;
472 lexer.LexFromRawLexer(tok);
473 if (tok.isNot(tok::at)) return false;
474 lexer.LexFromRawLexer(tok);
475 if (tok.isNot(tok::raw_identifier)) return false;
476 if (StringRef(tok.getRawIdentifierData(), tok.getLength())
477 != "property")
478 return false;
479 lexer.LexFromRawLexer(tok);
480
481 if (tok.isNot(tok::l_paren)) {
482 Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
483 return true;
484 }
485
486 lexer.LexFromRawLexer(tok);
487 if (tok.is(tok::r_paren)) {
488 Pass.TA.insert(tok.getLocation(), attr);
489 return true;
490 }
491
492 if (tok.isNot(tok::raw_identifier)) return false;
493
494 Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
495 return true;
496}
497
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000498void MigrationContext::traverse(TranslationUnitDecl *TU) {
Argyrios Kyrtzidise43ae792011-11-06 18:58:03 +0000499 for (traverser_iterator
500 I = traversers_begin(), E = traversers_end(); I != E; ++I)
501 (*I)->traverseTU(*this);
502
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000503 ASTTransform(*this).TraverseDecl(TU);
504}
505
506//===----------------------------------------------------------------------===//
John McCalld70fb982011-06-15 23:25:17 +0000507// getAllTransformations.
508//===----------------------------------------------------------------------===//
509
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000510static void traverseAST(MigrationPass &pass) {
511 MigrationContext MigrateCtx(pass);
512
513 if (pass.isGCMigration()) {
514 MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
Argyrios Kyrtzidise43ae792011-11-06 18:58:03 +0000515 MigrateCtx.addTraverser(new GCAttrsTraverser());
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000516 }
Argyrios Kyrtzidisaaa99962011-11-06 18:57:57 +0000517 MigrateCtx.addTraverser(new PropertyRewriteTraverser());
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000518
519 MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
520}
521
John McCalld70fb982011-06-15 23:25:17 +0000522static void independentTransforms(MigrationPass &pass) {
523 rewriteAutoreleasePool(pass);
Argyrios Kyrtzidisd2b91122011-11-04 15:58:22 +0000524 removeRetainReleaseDeallocFinalize(pass);
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000525 rewriteUnusedInitDelegate(pass);
Argyrios Kyrtzidisd2b91122011-11-04 15:58:22 +0000526 removeZeroOutPropsInDeallocFinalize(pass);
John McCalld70fb982011-06-15 23:25:17 +0000527 makeAssignARCSafe(pass);
Argyrios Kyrtzidise5b475c2011-06-21 20:20:39 +0000528 rewriteUnbridgedCasts(pass);
John McCalld70fb982011-06-15 23:25:17 +0000529 rewriteBlockObjCVariable(pass);
Argyrios Kyrtzidis73a0d322011-07-18 07:44:45 +0000530 checkAPIUses(pass);
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000531 traverseAST(pass);
John McCalld70fb982011-06-15 23:25:17 +0000532}
533
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +0000534std::vector<TransformFn> arcmt::getAllTransformations(
535 LangOptions::GCMode OrigGCMode) {
John McCalld70fb982011-06-15 23:25:17 +0000536 std::vector<TransformFn> transforms;
537
John McCalld70fb982011-06-15 23:25:17 +0000538 transforms.push_back(independentTransforms);
Argyrios Kyrtzidise5acb842011-06-21 20:20:42 +0000539 // This depends on previous transformations removing various expressions.
Argyrios Kyrtzidisd2b91122011-11-04 15:58:22 +0000540 transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
John McCalld70fb982011-06-15 23:25:17 +0000541
542 return transforms;
543}