blob: a64124015cf62bd82dc330952f21eb788f9e91cf [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.
Douglas Gregor7723fec2011-12-15 20:29:51 +000083 if (!AllowOnUnknownClass && !Class->hasDefinition())
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()) {
Argyrios Kyrtzidis69bda4c2012-01-19 15:59:08 +0000114 if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions(), &loc))
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000115 return SourceLocation();
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000116 }
117 loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
118
119 // Break down the source location.
120 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
121
122 // Try to load the file buffer.
123 bool invalidTemp = false;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000124 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000125 if (invalidTemp)
126 return SourceLocation();
127
128 const char *tokenBegin = file.data() + locInfo.second;
129
130 // Lex from the start of the given location.
131 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
132 Ctx.getLangOptions(),
133 file.begin(), tokenBegin, file.end());
134 Token tok;
135 lexer.LexFromRawLexer(tok);
136 if (tok.isNot(tok::semi))
137 return SourceLocation();
138
Argyrios Kyrtzidisaec230d2011-09-01 20:53:18 +0000139 return tok.getLocation();
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000140}
141
142bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
143 if (!E || !E->HasSideEffects(Ctx))
144 return false;
145
146 E = E->IgnoreParenCasts();
147 ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
148 if (!ME)
149 return true;
150 switch (ME->getMethodFamily()) {
151 case OMF_autorelease:
152 case OMF_dealloc:
153 case OMF_release:
154 case OMF_retain:
155 switch (ME->getReceiverKind()) {
156 case ObjCMessageExpr::SuperInstance:
157 return false;
158 case ObjCMessageExpr::Instance:
159 return hasSideEffects(ME->getInstanceReceiver(), Ctx);
160 default:
161 break;
162 }
163 break;
164 default:
165 break;
166 }
167
168 return true;
169}
170
Argyrios Kyrtzidis2c18ca02011-07-14 23:32:04 +0000171bool trans::isGlobalVar(Expr *E) {
172 E = E->IgnoreParenCasts();
173 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000174 return DRE->getDecl()->getDeclContext()->isFileContext() &&
175 DRE->getDecl()->getLinkage() == ExternalLinkage;
Argyrios Kyrtzidis2c18ca02011-07-14 23:32:04 +0000176 if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
177 return isGlobalVar(condOp->getTrueExpr()) &&
178 isGlobalVar(condOp->getFalseExpr());
179
180 return false;
181}
182
Argyrios Kyrtzidis18fd0c62011-07-27 05:28:18 +0000183StringRef trans::getNilString(ASTContext &Ctx) {
184 if (Ctx.Idents.get("nil").hasMacroDefinition())
185 return "nil";
186 else
187 return "0";
188}
189
John McCall8f0e8d22011-06-15 23:25:17 +0000190namespace {
191
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000192class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
193 ExprSet &Refs;
194public:
195 ReferenceClear(ExprSet &refs) : Refs(refs) { }
196 bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
197 bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Refs.erase(E); return true; }
198};
199
200class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
201 ValueDecl *Dcl;
202 ExprSet &Refs;
John McCall8f0e8d22011-06-15 23:25:17 +0000203
204public:
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000205 ReferenceCollector(ValueDecl *D, ExprSet &refs)
206 : Dcl(D), Refs(refs) { }
207
208 bool VisitDeclRefExpr(DeclRefExpr *E) {
209 if (E->getDecl() == Dcl)
210 Refs.insert(E);
211 return true;
212 }
213
214 bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
215 if (E->getDecl() == Dcl)
216 Refs.insert(E);
217 return true;
218 }
219};
220
221class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
222 ExprSet &Removables;
223
224public:
225 RemovablesCollector(ExprSet &removables)
John McCall8f0e8d22011-06-15 23:25:17 +0000226 : Removables(removables) { }
227
228 bool shouldWalkTypesOfTypeLocs() const { return false; }
229
230 bool TraverseStmtExpr(StmtExpr *E) {
231 CompoundStmt *S = E->getSubStmt();
232 for (CompoundStmt::body_iterator
233 I = S->body_begin(), E = S->body_end(); I != E; ++I) {
234 if (I != E - 1)
235 mark(*I);
236 TraverseStmt(*I);
237 }
238 return true;
239 }
240
241 bool VisitCompoundStmt(CompoundStmt *S) {
242 for (CompoundStmt::body_iterator
243 I = S->body_begin(), E = S->body_end(); I != E; ++I)
244 mark(*I);
245 return true;
246 }
247
248 bool VisitIfStmt(IfStmt *S) {
249 mark(S->getThen());
250 mark(S->getElse());
251 return true;
252 }
253
254 bool VisitWhileStmt(WhileStmt *S) {
255 mark(S->getBody());
256 return true;
257 }
258
259 bool VisitDoStmt(DoStmt *S) {
260 mark(S->getBody());
261 return true;
262 }
263
264 bool VisitForStmt(ForStmt *S) {
265 mark(S->getInit());
266 mark(S->getInc());
267 mark(S->getBody());
268 return true;
269 }
270
271private:
272 void mark(Stmt *S) {
273 if (!S) return;
274
John McCall7e5e5f42011-07-07 06:58:02 +0000275 while (LabelStmt *Label = dyn_cast<LabelStmt>(S))
276 S = Label->getSubStmt();
277 S = S->IgnoreImplicit();
John McCall8f0e8d22011-06-15 23:25:17 +0000278 if (Expr *E = dyn_cast<Expr>(S))
279 Removables.insert(E);
280 }
281};
282
John McCall8f0e8d22011-06-15 23:25:17 +0000283} // end anonymous namespace
284
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000285void trans::clearRefsIn(Stmt *S, ExprSet &refs) {
286 ReferenceClear(refs).TraverseStmt(S);
John McCall8f0e8d22011-06-15 23:25:17 +0000287}
288
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000289void trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
290 ReferenceCollector(D, refs).TraverseStmt(S);
John McCall8f0e8d22011-06-15 23:25:17 +0000291}
292
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000293void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
294 RemovablesCollector(exprs).TraverseStmt(S);
John McCall8f0e8d22011-06-15 23:25:17 +0000295}
296
297//===----------------------------------------------------------------------===//
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000298// MigrationContext
299//===----------------------------------------------------------------------===//
300
301namespace {
302
303class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
304 MigrationContext &MigrateCtx;
Argyrios Kyrtzidisa33849b2011-11-07 18:46:50 +0000305 typedef RecursiveASTVisitor<ASTTransform> base;
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000306
307public:
308 ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
309
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000310 bool shouldWalkTypesOfTypeLocs() const { return false; }
311
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000312 bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
313 ObjCImplementationContext ImplCtx(MigrateCtx, D);
314 for (MigrationContext::traverser_iterator
315 I = MigrateCtx.traversers_begin(),
316 E = MigrateCtx.traversers_end(); I != E; ++I)
317 (*I)->traverseObjCImplementation(ImplCtx);
318
Argyrios Kyrtzidisa33849b2011-11-07 18:46:50 +0000319 return base::TraverseObjCImplementationDecl(D);
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000320 }
321
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000322 bool TraverseStmt(Stmt *rootS) {
323 if (!rootS)
324 return true;
325
326 BodyContext BodyCtx(MigrateCtx, rootS);
327 for (MigrationContext::traverser_iterator
328 I = MigrateCtx.traversers_begin(),
329 E = MigrateCtx.traversers_end(); I != E; ++I)
330 (*I)->traverseBody(BodyCtx);
331
332 return true;
333 }
334};
335
336}
337
338MigrationContext::~MigrationContext() {
339 for (traverser_iterator
340 I = traversers_begin(), E = traversers_end(); I != E; ++I)
341 delete *I;
342}
343
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +0000344bool MigrationContext::isGCOwnedNonObjC(QualType T) {
345 while (!T.isNull()) {
346 if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
347 if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
348 return !AttrT->getModifiedType()->isObjCRetainableType();
349 }
350
351 if (T->isArrayType())
352 T = Pass.Ctx.getBaseElementType(T);
353 else if (const PointerType *PT = T->getAs<PointerType>())
354 T = PT->getPointeeType();
355 else if (const ReferenceType *RT = T->getAs<ReferenceType>())
356 T = RT->getPointeeType();
357 else
358 break;
359 }
360
361 return false;
362}
363
Argyrios Kyrtzidisb0e1e122011-11-07 18:46:46 +0000364bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
365 StringRef toAttr,
366 SourceLocation atLoc) {
367 if (atLoc.isMacroID())
368 return false;
369
370 SourceManager &SM = Pass.Ctx.getSourceManager();
371
372 // Break down the source location.
373 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
374
375 // Try to load the file buffer.
376 bool invalidTemp = false;
377 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
378 if (invalidTemp)
379 return false;
380
381 const char *tokenBegin = file.data() + locInfo.second;
382
383 // Lex from the start of the given location.
384 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
385 Pass.Ctx.getLangOptions(),
386 file.begin(), tokenBegin, file.end());
387 Token tok;
388 lexer.LexFromRawLexer(tok);
389 if (tok.isNot(tok::at)) return false;
390 lexer.LexFromRawLexer(tok);
391 if (tok.isNot(tok::raw_identifier)) return false;
392 if (StringRef(tok.getRawIdentifierData(), tok.getLength())
393 != "property")
394 return false;
395 lexer.LexFromRawLexer(tok);
396 if (tok.isNot(tok::l_paren)) return false;
397
398 Token BeforeTok = tok;
399 Token AfterTok;
400 AfterTok.startToken();
401 SourceLocation AttrLoc;
402
403 lexer.LexFromRawLexer(tok);
404 if (tok.is(tok::r_paren))
405 return false;
406
407 while (1) {
408 if (tok.isNot(tok::raw_identifier)) return false;
409 StringRef ident(tok.getRawIdentifierData(), tok.getLength());
410 if (ident == fromAttr) {
411 if (!toAttr.empty()) {
412 Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
413 return true;
414 }
415 // We want to remove the attribute.
416 AttrLoc = tok.getLocation();
417 }
418
419 do {
420 lexer.LexFromRawLexer(tok);
421 if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
422 AfterTok = tok;
423 } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
424 if (tok.is(tok::r_paren))
425 break;
426 if (AttrLoc.isInvalid())
427 BeforeTok = tok;
428 lexer.LexFromRawLexer(tok);
429 }
430
431 if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
432 // We want to remove the attribute.
433 if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
434 Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
435 AfterTok.getLocation()));
436 } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
437 Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
438 } else {
439 Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
440 }
441
442 return true;
443 }
444
445 return false;
446}
447
Argyrios Kyrtzidis6da42742011-11-28 02:04:36 +0000448bool MigrationContext::addPropertyAttribute(StringRef attr,
449 SourceLocation atLoc) {
450 if (atLoc.isMacroID())
451 return false;
452
453 SourceManager &SM = Pass.Ctx.getSourceManager();
454
455 // Break down the source location.
456 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
457
458 // Try to load the file buffer.
459 bool invalidTemp = false;
460 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
461 if (invalidTemp)
462 return false;
463
464 const char *tokenBegin = file.data() + locInfo.second;
465
466 // Lex from the start of the given location.
467 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
468 Pass.Ctx.getLangOptions(),
469 file.begin(), tokenBegin, file.end());
470 Token tok;
471 lexer.LexFromRawLexer(tok);
472 if (tok.isNot(tok::at)) return false;
473 lexer.LexFromRawLexer(tok);
474 if (tok.isNot(tok::raw_identifier)) return false;
475 if (StringRef(tok.getRawIdentifierData(), tok.getLength())
476 != "property")
477 return false;
478 lexer.LexFromRawLexer(tok);
479
480 if (tok.isNot(tok::l_paren)) {
481 Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
482 return true;
483 }
484
485 lexer.LexFromRawLexer(tok);
486 if (tok.is(tok::r_paren)) {
487 Pass.TA.insert(tok.getLocation(), attr);
488 return true;
489 }
490
491 if (tok.isNot(tok::raw_identifier)) return false;
492
493 Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
494 return true;
495}
496
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000497void MigrationContext::traverse(TranslationUnitDecl *TU) {
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000498 for (traverser_iterator
499 I = traversers_begin(), E = traversers_end(); I != E; ++I)
500 (*I)->traverseTU(*this);
501
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000502 ASTTransform(*this).TraverseDecl(TU);
503}
504
505//===----------------------------------------------------------------------===//
John McCall8f0e8d22011-06-15 23:25:17 +0000506// getAllTransformations.
507//===----------------------------------------------------------------------===//
508
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000509static void traverseAST(MigrationPass &pass) {
510 MigrationContext MigrateCtx(pass);
511
512 if (pass.isGCMigration()) {
513 MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +0000514 MigrateCtx.addTraverser(new GCAttrsTraverser());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000515 }
Argyrios Kyrtzidisb0d5db12011-11-06 18:57:57 +0000516 MigrateCtx.addTraverser(new PropertyRewriteTraverser());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000517
518 MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
519}
520
John McCall8f0e8d22011-06-15 23:25:17 +0000521static void independentTransforms(MigrationPass &pass) {
522 rewriteAutoreleasePool(pass);
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +0000523 removeRetainReleaseDeallocFinalize(pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000524 rewriteUnusedInitDelegate(pass);
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +0000525 removeZeroOutPropsInDeallocFinalize(pass);
John McCall8f0e8d22011-06-15 23:25:17 +0000526 makeAssignARCSafe(pass);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +0000527 rewriteUnbridgedCasts(pass);
John McCall8f0e8d22011-06-15 23:25:17 +0000528 rewriteBlockObjCVariable(pass);
Argyrios Kyrtzidisfd103982011-07-18 07:44:45 +0000529 checkAPIUses(pass);
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000530 traverseAST(pass);
John McCall8f0e8d22011-06-15 23:25:17 +0000531}
532
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +0000533std::vector<TransformFn> arcmt::getAllTransformations(
534 LangOptions::GCMode OrigGCMode) {
John McCall8f0e8d22011-06-15 23:25:17 +0000535 std::vector<TransformFn> transforms;
536
John McCall8f0e8d22011-06-15 23:25:17 +0000537 transforms.push_back(independentTransforms);
Argyrios Kyrtzidisfd3455a2011-06-21 20:20:42 +0000538 // This depends on previous transformations removing various expressions.
Argyrios Kyrtzidise7ef8552011-11-04 15:58:22 +0000539 transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
John McCall8f0e8d22011-06-15 23:25:17 +0000540
541 return transforms;
542}