clang: lib/ARCMigrate/Transforms.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

21

22using namespace clang;

23using namespace arcmt;

24using namespace trans;

25

27

29 if (!EnableCFBridgeFns)

30 EnableCFBridgeFns = SemaRef.ObjC().isKnownName("CFBridgingRetain") &&

31 SemaRef.ObjC().isKnownName("CFBridgingRelease");

32 return *EnableCFBridgeFns;

33}

34

35

36

37

38

40 bool AllowOnUnknownClass) {

42 return false;

43

45 if (T.isNull())

46 return false;

47

48

51 AllowOnUnknownClass = true;

52

57 if (!AllowOnUnknownClass && (Class || Class->getName() == "NSObject"))

58 return false;

59 if (!AllowOnUnknownClass && Class->hasDefinition())

60 return false;

61 if (Class && Class->isArcWeakrefUnavailable())

62 return false;

63 }

64

65 return true;

66}

67

69 if (E->getOpcode() != BO_Assign)

70 return false;

71

73}

74

76 if (E)

77 return false;

78 if (const FullExpr *FE = dyn_cast(E))

79 E = FE->getSubExpr();

80

83 if (ME->getMethodFamily() == OMF_retain)

84 return true;

85

88 if (const FunctionDecl *FD = callE->getDirectCallee()) {

89 if (FD->hasAttr())

90 return true;

91

92 if (FD->isGlobal() &&

93 FD->getIdentifier() &&

94 FD->getParent()->isTranslationUnit() &&

95 FD->isExternallyVisible() &&

97 FD->getIdentifier()->getName())) {

98 StringRef fname = FD->getIdentifier()->getName();

99 if (fname.ends_with("Retain") || fname.contains("Create") ||

100 fname.contains("Copy"))

101 return true;

102 }

103 }

104 }

105

107 while (implCE && implCE->getCastKind() == CK_BitCast)

108 implCE = dyn_cast(implCE->getSubExpr());

109

110 return implCE && implCE->getCastKind() == CK_ARCConsumeObject;

111}

112

113

114

115

116

123}

124

125

126

127

128

131 bool IsDecl) {

136 }

138

139

140 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);

141

142

143 bool invalidTemp = false;

144 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);

145 if (invalidTemp)

147

148 const char *tokenBegin = file.data() + locInfo.second;

149

150

151 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),

153 file.begin(), tokenBegin, file.end());

156 if (tok.isNot(tok::semi)) {

157 if (!IsDecl)

159

160

162 }

163

165}

166

169 return false;

170

173 if (!ME)

174 return true;

182 return false;

185 default:

186 break;

187 }

188 break;

189 default:

190 break;

191 }

192

193 return true;

194}

195

198 if (DeclRefExpr *DRE = dyn_cast(E))

199 return DRE->getDecl()->getDeclContext()->isFileContext() &&

200 DRE->getDecl()->isExternallyVisible();

202 return isGlobalVar(condOp->getTrueExpr()) &&

204

205 return false;

206}

207

210}

211

212namespace {

213

216public:

217 ReferenceClear(ExprSet &refs) : Refs(refs) { }

218 bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }

219};

220

221class ReferenceCollector : public RecursiveASTVisitor {

224

225public:

227 : Dcl(D), Refs(refs) { }

228

230 if (E->getDecl() == Dcl)

231 Refs.insert(E);

232 return true;

233 }

234};

235

236class RemovablesCollector : public RecursiveASTVisitor {

238

239public:

240 RemovablesCollector(ExprSet &removables)

241 : Removables(removables) { }

242

243 bool shouldWalkTypesOfTypeLocs() const { return false; }

244

245 bool TraverseStmtExpr(StmtExpr *E) {

248 I = S->body_begin(), E = S->body_end(); I != E; ++I) {

249 if (I != E - 1)

250 mark(*I);

251 TraverseStmt(*I);

252 }

253 return true;

254 }

255

257 for (auto *I : S->body())

258 mark(I);

259 return true;

260 }

261

262 bool VisitIfStmt(IfStmt *S) {

263 mark(S->getThen());

264 mark(S->getElse());

265 return true;

266 }

267

268 bool VisitWhileStmt(WhileStmt *S) {

269 mark(S->getBody());

270 return true;

271 }

272

273 bool VisitDoStmt(DoStmt *S) {

274 mark(S->getBody());

275 return true;

276 }

277

278 bool VisitForStmt(ForStmt *S) {

279 mark(S->getInit());

280 mark(S->getInc());

281 mark(S->getBody());

282 return true;

283 }

284

285private:

286 void mark(Stmt *S) {

287 if (!S) return;

288

289 while (auto *Label = dyn_cast(S))

290 S = Label->getSubStmt();

291 if (auto *E = dyn_cast(S))

293 if (auto *E = dyn_cast(S))

294 Removables.insert(E);

295 }

296};

297

298}

299

301 ReferenceClear(refs).TraverseStmt(S);

302}

303

305 ReferenceCollector(D, refs).TraverseStmt(S);

306}

307

309 RemovablesCollector(exprs).TraverseStmt(S);

310}

311

312

313

314

315

316namespace {

317

321

322public:

323 ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }

324

325 bool shouldWalkTypesOfTypeLocs() const { return false; }

326

332 (*I)->traverseObjCImplementation(ImplCtx);

333

334 return base::TraverseObjCImplementationDecl(D);

335 }

336

337 bool TraverseStmt(Stmt *rootS) {

338 if (!rootS)

339 return true;

340

345 (*I)->traverseBody(BodyCtx);

346

347 return true;

348 }

349};

350

351}

352

356 delete *I;

357}

358

360 while (T.isNull()) {

362 if (AttrT->getAttrKind() == attr::ObjCOwnership)

363 return !AttrT->getModifiedType()->isObjCRetainableType();

364 }

365

372 else

373 break;

374 }

375

376 return false;

377}

378

380 StringRef toAttr,

383 return false;

384

386

387

388 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);

389

390

391 bool invalidTemp = false;

392 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);

393 if (invalidTemp)

394 return false;

395

396 const char *tokenBegin = file.data() + locInfo.second;

397

398

399 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),

401 file.begin(), tokenBegin, file.end());

404 if (tok.isNot(tok::at)) return false;

406 if (tok.isNot(tok::raw_identifier)) return false;

408 return false;

410 if (tok.isNot(tok::l_paren)) return false;

411

412 Token BeforeTok = tok;

416

418 if (tok.is(tok::r_paren))

419 return false;

420

421 while (true) {

422 if (tok.isNot(tok::raw_identifier)) return false;

424 if (!toAttr.empty()) {

426 return true;

427 }

428

430 }

431

432 do {

434 if (AttrLoc.isValid() && AfterTok.is(tok::unknown))

435 AfterTok = tok;

436 } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));

437 if (tok.is(tok::r_paren))

438 break;

440 BeforeTok = tok;

442 }

443

444 if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {

445

446 if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {

449 } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {

451 } else {

453 }

454

455 return true;

456 }

457

458 return false;

459}

460

464 return false;

465

467

468

469 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);

470

471

472 bool invalidTemp = false;

473 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);

474 if (invalidTemp)

475 return false;

476

477 const char *tokenBegin = file.data() + locInfo.second;

478

479

480 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),

482 file.begin(), tokenBegin, file.end());

485 if (tok.isNot(tok::at)) return false;

487 if (tok.isNot(tok::raw_identifier)) return false;

489 return false;

491

492 if (tok.isNot(tok::l_paren)) {

494 return true;

495 }

496

498 if (tok.is(tok::r_paren)) {

500 return true;

501 }

502

503 if (tok.isNot(tok::raw_identifier)) return false;

504

506 return true;

507}

508

512 (*I)->traverseTU(*this);

513

514 ASTTransform(*this).TraverseDecl(TU);

515}

516

523

525 impl_iterator;

526 for (impl_iterator I = impl_iterator(DC->decls_begin()),

527 E = impl_iterator(DC->decls_end()); I != E; ++I) {

528 for (const auto *MD : I->instance_methods()) {

529 if (!MD->hasBody())

530 continue;

531

532 if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {

536 "#if !__has_feature(objc_arc)\n");

541 std::string str = "\n#endif\n";

546

547 break;

548 }

549 }

550 }

551}

552

553

554

555

556

559

563 }

567

569}

570

580}

581

584 bool NoFinalizeRemoval) {

585 std::vector transforms;

586

590

592

593 return transforms;

594}

Defines the clang::ASTContext interface.

Defines the clang::Preprocessor interface.

This file declares semantic analysis for Objective-C.

Defines the SourceManager interface.

static void traverseAST(MigrationPass &pass)

static void independentTransforms(MigrationPass &pass)

static void GCRewriteFinalize(MigrationPass &pass)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

TranslationUnitDecl * getTranslationUnitDecl() const

const LangOptions & getLangOpts() const

SelectorTable & Selectors

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

const TargetInfo & getTargetInfo() const

An attributed type is a type to which a type attribute has been applied.

A builtin binary operation expression such as "x + y" or "x <= y".

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

CastKind getCastKind() const

static CharSourceRange getTokenRange(SourceRange R)

CompoundStmt - This represents a group of statements like { stmt stmt }.

ConditionalOperator - The ?: ternary operator.

specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

decl_iterator decls_end() const

decl_iterator decls_begin() const

A reference to a declared variable, function, enum, etc.

DoStmt - This represents a 'do/while' stmt.

This represents one expression.

Expr * IgnoreParenCasts() LLVM_READONLY

Skip past any parentheses and casts which might surround this expression until reaching a fixed point...

Expr * IgnoreImplicit() LLVM_READONLY

Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.

bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const

HasSideEffects - This routine returns true for all those expressions which have any effect other than...

ForStmt - This represents a 'for (init;cond;inc)' stmt.

FullExpr - Represents a "full-expression" node.

Represents a function declaration or definition.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

IfStmt - This represents an if/then/else.

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.

static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)

Returns a string for the source that the range encompasses.

bool LexFromRawLexer(Token &Result)

LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...

static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)

Returns true if the given MacroID location points at the last token of the macro expansion.

static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)

Computes the source location just past the end of the token at this source location.

ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...

Represents an ObjC class declaration.

An expression that sends a message to the given Objective-C object or class.

Expr * getInstanceReceiver()

Returns the object expression (receiver) for an instance message, or null for a message that is not a...

ObjCMethodFamily getMethodFamily() const

@ SuperInstance

The receiver is the instance of the superclass object.

@ Instance

The receiver is an object instance.

ReceiverKind getReceiverKind() const

Determine the kind of receiver that this message is being sent to.

ObjCMethodDecl - Represents an instance or class method declaration.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

Represents a pointer to an Objective C object.

PointerType - C99 6.7.5.1 - Pointer Declarators.

bool isMacroDefined(StringRef Id)

A (possibly-)qualified type.

A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...

Base for LValueReferenceType and RValueReferenceType.

Selector getNullarySelector(const IdentifierInfo *ID)

Smart pointer class that efficiently represents Objective-C method names.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

This class handles loading and caching of source files into memory.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).

Stmt - This represents one statement.

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

Token - This structure provides full information about a lexed token.

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

bool is(tok::TokenKind K) const

is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....

bool isNot(tok::TokenKind K) const

void startToken()

Reset all flags to cleared.

StringRef getRawIdentifier() const

getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...

The top declaration context.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

const T * getAs() const

Member-template getAs'.

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

WhileStmt - This represents a 'while' stmt.

bool isGCMigration() const

bool CFBridgingFunctionsDefined()

void insertAfterToken(SourceLocation loc, StringRef text)

void insert(SourceLocation loc, StringRef text)

void remove(SourceRange range)

void replaceText(SourceLocation loc, StringRef text, StringRef replacementText)

void traverse(TranslationUnitDecl *TU)

bool addPropertyAttribute(StringRef attr, SourceLocation atLoc)

traverser_iterator traversers_begin()

std::vector< ASTTraverser * >::iterator traverser_iterator

bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, SourceLocation atLoc)

void addTraverser(ASTTraverser *traverser)

bool isGCOwnedNonObjC(QualType T)

traverser_iterator traversers_end()

Defines the clang::TargetInfo interface.

StringRef getNilString(MigrationPass &Pass)

Returns "nil" or "0" if 'nil' macro is not actually defined.

bool hasSideEffects(Expr *E, ASTContext &Ctx)

void removeRetainReleaseDeallocFinalize(MigrationPass &pass)

bool canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass=false)

Determine whether we can add weak to the given type.

void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass)

void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs)

void clearRefsIn(Stmt *S, ExprSet &refs)

llvm::DenseSet< Expr * > ExprSet

void rewriteAutoreleasePool(MigrationPass &pass)

void rewriteUnbridgedCasts(MigrationPass &pass)

void rewriteUnusedInitDelegate(MigrationPass &pass)

bool isPlusOneAssign(const BinaryOperator *E)

void checkAPIUses(MigrationPass &pass)

bool isPlusOne(const Expr *E)

SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)

'Loc' is the end of a statement range.

bool isGlobalVar(Expr *E)

void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass)

SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)

'Loc' is the end of a statement range.

void makeAssignARCSafe(MigrationPass &pass)

void collectRemovables(Stmt *S, ExprSet &exprs)

std::vector< TransformFn > getAllTransformations(LangOptions::GCMode OrigGCMode, bool NoFinalizeRemoval)

const internal::VariadicAllOfMatcher< Attr > attr

Matches attributes.

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())

The JSON file list parser is used to communicate input to InstallAPI.

const FunctionProtoType * T

@ Class

The "class" keyword introduces the elaborated-type-specifier.