forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			226 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			226 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#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;
 | 
						|
    /// \brief 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;
 | 
						|
 | 
						|
  /// \brief 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.
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
/// \brief 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);
 | 
						|
 | 
						|
/// \brief '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);
 | 
						|
 | 
						|
/// \brief '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);
 | 
						|
/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
 | 
						|
StringRef getNilString(ASTContext &Ctx);
 | 
						|
 | 
						|
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
 |