Chandler Carruth 2946cd7010 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

225 lines
6.7 KiB
C++

//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/SaveAndRestore.h"
namespace clang {
class Decl;
class Stmt;
class BlockDecl;
class ObjCMethodDecl;
class FunctionDecl;
namespace arcmt {
class MigrationPass;
namespace trans {
class MigrationContext;
//===----------------------------------------------------------------------===//
// Transformations.
//===----------------------------------------------------------------------===//
void rewriteAutoreleasePool(MigrationPass &pass);
void rewriteUnbridgedCasts(MigrationPass &pass);
void makeAssignARCSafe(MigrationPass &pass);
void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
void rewriteUnusedInitDelegate(MigrationPass &pass);
void checkAPIUses(MigrationPass &pass);
void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
class BodyContext {
MigrationContext &MigrateCtx;
ParentMap PMap;
Stmt *TopStmt;
public:
BodyContext(MigrationContext &MigrateCtx, Stmt *S)
: MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
MigrationContext &getMigrationContext() { return MigrateCtx; }
ParentMap &getParentMap() { return PMap; }
Stmt *getTopStmt() { return TopStmt; }
};
class ObjCImplementationContext {
MigrationContext &MigrateCtx;
ObjCImplementationDecl *ImpD;
public:
ObjCImplementationContext(MigrationContext &MigrateCtx,
ObjCImplementationDecl *D)
: MigrateCtx(MigrateCtx), ImpD(D) {}
MigrationContext &getMigrationContext() { return MigrateCtx; }
ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
};
class ASTTraverser {
public:
virtual ~ASTTraverser();
virtual void traverseTU(MigrationContext &MigrateCtx) { }
virtual void traverseBody(BodyContext &BodyCtx) { }
virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
};
class MigrationContext {
std::vector<ASTTraverser *> Traversers;
public:
MigrationPass &Pass;
struct GCAttrOccurrence {
enum AttrKind { Weak, Strong } Kind;
SourceLocation Loc;
QualType ModifiedType;
Decl *Dcl;
/// true if the attribute is owned, e.g. it is in a body and not just
/// in an interface.
bool FullyMigratable;
};
std::vector<GCAttrOccurrence> GCAttrs;
llvm::DenseSet<unsigned> AttrSet;
llvm::DenseSet<unsigned> RemovedAttrSet;
/// Set of raw '@' locations for 'assign' properties group that contain
/// GC __weak.
llvm::DenseSet<unsigned> AtPropsWeak;
explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
~MigrationContext();
typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
traverser_iterator traversers_begin() { return Traversers.begin(); }
traverser_iterator traversers_end() { return Traversers.end(); }
void addTraverser(ASTTraverser *traverser) {
Traversers.push_back(traverser);
}
bool isGCOwnedNonObjC(QualType T);
bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
}
bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
SourceLocation atLoc);
bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
void traverse(TranslationUnitDecl *TU);
void dumpGCAttrs();
};
class PropertyRewriteTraverser : public ASTTraverser {
public:
void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override;
};
class BlockObjCVariableTraverser : public ASTTraverser {
public:
void traverseBody(BodyContext &BodyCtx) override;
};
class ProtectedScopeTraverser : public ASTTraverser {
public:
void traverseBody(BodyContext &BodyCtx) override;
};
// GC transformations
class GCAttrsTraverser : public ASTTraverser {
public:
void traverseTU(MigrationContext &MigrateCtx) override;
};
class GCCollectableCallsTraverser : public ASTTraverser {
public:
void traverseBody(BodyContext &BodyCtx) override;
};
//===----------------------------------------------------------------------===//
// Helpers.
//===----------------------------------------------------------------------===//
/// Determine whether we can add weak to the given type.
bool canApplyWeak(ASTContext &Ctx, QualType type,
bool AllowOnUnknownClass = false);
bool isPlusOneAssign(const BinaryOperator *E);
bool isPlusOne(const Expr *E);
/// 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,
bool IsDecl = false);
/// 'Loc' is the end of a statement range. This returns the location
/// of the semicolon following the statement.
/// If no semicolon is found or the location is inside a macro, the returned
/// source location will be invalid.
SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,
bool IsDecl = false);
bool hasSideEffects(Expr *E, ASTContext &Ctx);
bool isGlobalVar(Expr *E);
/// Returns "nil" or "0" if 'nil' macro is not actually defined.
StringRef getNilString(MigrationPass &Pass);
template <typename BODY_TRANS>
class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
MigrationPass &Pass;
Decl *ParentD;
typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
public:
BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
bool TraverseStmt(Stmt *rootS) {
if (rootS)
BODY_TRANS(Pass).transformBody(rootS, ParentD);
return true;
}
bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
SaveAndRestore<Decl *> SetParent(ParentD, D);
return base::TraverseObjCMethodDecl(D);
}
};
typedef llvm::DenseSet<Expr *> ExprSet;
void clearRefsIn(Stmt *S, ExprSet &refs);
template <typename iterator>
void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
for (; begin != end; ++begin)
clearRefsIn(*begin, refs);
}
void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
void collectRemovables(Stmt *S, ExprSet &exprs);
} // end namespace trans
} // end namespace arcmt
} // end namespace clang
#endif