blob: e208e8471bd78f62bf6fa9b0786f069ed7037664 [file] [log] [blame]
John McCall8f0e8d22011-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 McCall8f0e8d22011-06-15 23:25:17 +00009
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000010#include "Transforms.h"
John McCall8f0e8d22011-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 McCall8f0e8d22011-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 Kyrtzidis7196d062011-06-21 20:20:39 +000024using namespace trans;
John McCall8f0e8d22011-06-15 23:25:17 +000025
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000026ASTTraverser::~ASTTraverser() { }
27
John McCall8f0e8d22011-06-15 23:25:17 +000028//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000029// Helpers.
John McCall8f0e8d22011-06-15 23:25:17 +000030//===----------------------------------------------------------------------===//
31
Argyrios Kyrtzidis86625b52011-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 Kyrtzidis263d6672011-11-08 05:56:08 +000045 .Case("NSViewController", true)
Argyrios Kyrtzidis86625b52011-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 Kyrtzidis12192cf2011-11-07 18:40:29 +000068bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
69 bool AllowOnUnknownClass) {
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +000070 if (!Ctx.getLangOptions().ObjCRuntimeHasWeak)
71 return false;
72
73 QualType T = type;
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +000074 if (T.isNull())
75 return false;
76
Argyrios Kyrtzidis86625b52011-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 Kyrtzidis12192cf2011-11-07 18:40:29 +000081 if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
Argyrios Kyrtzidis86625b52011-07-12 22:05:17 +000082 return false; // id/NSObject is not safe for weak.
Argyrios Kyrtzidis12192cf2011-11-07 18:40:29 +000083 if (!AllowOnUnknownClass && Class->isForwardDecl())
Argyrios Kyrtzidis5363e8d2011-07-12 22:16:25 +000084 return false; // forward classes are not verifiable, therefore not safe.
Argyrios Kyrtzidis86625b52011-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 Kyrtzidis7196d062011-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 Kyrtzidisaec230d2011-09-01 20:53:18 +0000100 SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
101 if (SemiLoc.isInvalid())
102 return SourceLocation();
Argyrios Kyrtzidisa64ccef2011-09-19 20:40:19 +0000103 return SemiLoc.getLocWithOffset(1);
Argyrios Kyrtzidisaec230d2011-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 Kyrtzidis7196d062011-06-21 20:20:39 +0000112 SourceManager &SM = Ctx.getSourceManager();
113 if (loc.isMacroID()) {
Chandler Carruth433db062011-07-14 08:20:40 +0000114 if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000115 return SourceLocation();
Chandler Carruthedc3dcc2011-07-25 16:56:02 +0000116 loc = SM.getExpansionRange(loc).second;
Argyrios Kyrtzidis7196d062011-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 Lattner5f9e2722011-07-23 10:55:15 +0000125 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
Argyrios Kyrtzidis7196d062011-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 Kyrtzidisaec230d2011-09-01 20:53:18 +0000140 return tok.getLocation();
Argyrios Kyrtzidis7196d062011-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 Kyrtzidis2c18ca02011-07-14 23:32:04 +0000172bool trans::isGlobalVar(Expr *E) {
173 E = E->IgnoreParenCasts();
174 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000175 return DRE->getDecl()->getDeclContext()->isFileContext() &&
176 DRE->getDecl()->getLinkage() == ExternalLinkage;
Argyrios Kyrtzidis2c18ca02011-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 Kyrtzidis18fd0c62011-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 McCall8f0e8d22011-06-15 23:25:17 +0000191namespace {
192
Argyrios Kyrtzidis7196d062011-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 McCall8f0e8d22011-06-15 23:25:17 +0000204
205public:
Argyrios Kyrtzidis7196d062011-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 McCall8f0e8d22011-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 McCall7e5e5f42011-07-07 06:58:02 +0000276 while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
277 S = Label->getSubStmt();
278 S = S->IgnoreImplicit();
John McCall8f0e8d22011-06-15 23:25:17 +0000279 if (Expr *E = dyn_cast<Expr>(S))
280 Removables.insert(E);
281 }
282};
283
John McCall8f0e8d22011-06-15 23:25:17 +0000284} // end anonymous namespace
285
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000286void trans::clearRefsIn(Stmt *S, ExprSet &refs) {
287 ReferenceClear(refs).TraverseStmt(S);
John McCall8f0e8d22011-06-15 23:25:17 +0000288}
289
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000290void trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
291 ReferenceCollector(D, refs).TraverseStmt(S);
John McCall8f0e8d22011-06-15 23:25:17 +0000292}
293
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000294void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
295 RemovablesCollector(exprs).TraverseStmt(S);
John McCall8f0e8d22011-06-15 23:25:17 +0000296}
297
298//===----------------------------------------------------------------------===//
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000299// MigrationContext
300//===----------------------------------------------------------------------===//
301
302namespace {
303
304class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
305 MigrationContext &MigrateCtx;
Argyrios Kyrtzidisa33849b2011-11-07 18:46:50 +0000306 typedef RecursiveASTVisitor<ASTTransform> base;
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000307
308public:
309 ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
310
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000311 bool shouldWalkTypesOfTypeLocs() const { return false; }
312
Argyrios Kyrtzidisb0d5db12011-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 Kyrtzidisa33849b2011-11-07 18:46:50 +0000320 return base::TraverseObjCImplementationDecl(D);
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000321 }
322
Argyrios Kyrtzidise0ac7452011-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 Kyrtzidis1fe42032011-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 Kyrtzidisb0e1e122011-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 Kyrtzidis6da42742011-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 Kyrtzidise0ac7452011-11-04 15:58:08 +0000498void MigrationContext::traverse(TranslationUnitDecl *TU) {
Argyrios Kyrtzidisf38fa732011-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 Kyrtzidise0ac7452011-11-04 15:58:08 +0000503 ASTTransform(*this).TraverseDecl(TU);
504}
505
506//===----------------------------------------------------------------------===//
John McCall8f0e8d22011-06-15 23:25:17 +0000507// getAllTransformations.
508//===----------------------------------------------------------------------===//
509
Argyrios Kyrtzidise0ac7452011-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 Kyrtzidisf38fa732011-11-06 18:58:03 +0000515 MigrateCtx.addTraverser(new GCAttrsTraverser());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000516 }
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000517 MigrateCtx.addTraverser(new PropertyRewriteTraverser());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000518
519 MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
520}
521
John McCall8f0e8d22011-06-15 23:25:17 +0000522static void independentTransforms(MigrationPass &pass) {
523 rewriteAutoreleasePool(pass);
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +0000524 removeRetainReleaseDeallocFinalize(pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000525 rewriteUnusedInitDelegate(pass);
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +0000526 removeZeroOutPropsInDeallocFinalize(pass);
John McCall8f0e8d22011-06-15 23:25:17 +0000527 makeAssignARCSafe(pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000528 rewriteUnbridgedCasts(pass);
John McCall8f0e8d22011-06-15 23:25:17 +0000529 rewriteBlockObjCVariable(pass);
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +0000530 checkAPIUses(pass);
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000531 traverseAST(pass);
John McCall8f0e8d22011-06-15 23:25:17 +0000532}
533
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000534std::vector<TransformFn> arcmt::getAllTransformations(
535 LangOptions::GCMode OrigGCMode) {
John McCall8f0e8d22011-06-15 23:25:17 +0000536 std::vector<TransformFn> transforms;
537
John McCall8f0e8d22011-06-15 23:25:17 +0000538 transforms.push_back(independentTransforms);
Argyrios Kyrtzidisfd3455a2011-06-21 20:20:42 +0000539 // This depends on previous transformations removing various expressions.
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +0000540 transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
John McCall8f0e8d22011-06-15 23:25:17 +0000541
542 return transforms;
543}