forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			257 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- Core/Transform.h - Transform Base Class Def'n -----------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| ///
 | |
| /// \file
 | |
| /// \brief This file provides the declaration for the base Transform class from
 | |
| /// which all transforms must subclass.
 | |
| ///
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef CPP11_MIGRATE_TRANSFORM_H
 | |
| #define CPP11_MIGRATE_TRANSFORM_H
 | |
| 
 | |
| #include "Core/IncludeExcludeInfo.h"
 | |
| #include "clang/Tooling/Refactoring.h"
 | |
| #include "llvm/ADT/OwningPtr.h"
 | |
| #include "llvm/Support/CommandLine.h"
 | |
| #include "llvm/Support/Registry.h"
 | |
| #include "llvm/Support/Timer.h"
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| /// \brief Description of the riskiness of actions that can be taken by
 | |
| /// transforms.
 | |
| enum RiskLevel {
 | |
|   /// Transformations that will not change semantics.
 | |
|   RL_Safe,
 | |
| 
 | |
|   /// Transformations that might change semantics.
 | |
|   RL_Reasonable,
 | |
| 
 | |
|   /// Transformations that are likely to change semantics.
 | |
|   RL_Risky
 | |
| };
 | |
| 
 | |
| // Forward declarations
 | |
| namespace clang {
 | |
| class CompilerInstance;
 | |
| namespace tooling {
 | |
| class CompilationDatabase;
 | |
| class FrontendActionFactory;
 | |
| } // namespace tooling
 | |
| namespace ast_matchers {
 | |
| class MatchFinder;
 | |
| } // namespace ast_matchers
 | |
| } // namespace clang
 | |
| 
 | |
| class FileOverrides;
 | |
| 
 | |
| /// \brief To group transforms' options together when printing the help.
 | |
| extern llvm::cl::OptionCategory TransformsOptionsCategory;
 | |
| 
 | |
| /// \brief Container for global options affecting all transforms.
 | |
| struct TransformOptions {
 | |
|   /// \brief Enable the use of performance timers.
 | |
|   bool EnableTiming;
 | |
| 
 | |
|   /// \brief Allow changes to headers included from the main source file.
 | |
|   /// Transform sub-classes should use ModifiableHeaders to determine which
 | |
|   /// headers are modifiable and which are not.
 | |
|   bool EnableHeaderModifications;
 | |
| 
 | |
|   /// \brief Contains information on which headers are safe to transform and
 | |
|   /// which aren't.
 | |
|   IncludeExcludeInfo ModifiableHeaders;
 | |
| 
 | |
|   /// \brief Maximum allowed level of risk.
 | |
|   RiskLevel MaxRiskLevel;
 | |
| };
 | |
| 
 | |
| /// \brief Abstract base class for all C++11 migration transforms.
 | |
| ///
 | |
| /// Subclasses must call createActionFactory() to create a
 | |
| /// FrontendActionFactory to pass to ClangTool::run(). Subclasses are also
 | |
| /// responsible for calling setOverrides() before calling ClangTool::run().
 | |
| ///
 | |
| /// If timing is enabled (see TransformOptions), per-source performance timing
 | |
| /// is recorded and stored in a TimingVec for later access with timing_begin()
 | |
| /// and timing_end().
 | |
| class Transform {
 | |
| public:
 | |
|   /// \brief Constructor
 | |
|   /// \param Name Name of the transform for human-readable purposes (e.g. -help
 | |
|   /// text)
 | |
|   /// \param Options Global options that affect all Transforms.
 | |
|   Transform(llvm::StringRef Name, const TransformOptions &Options);
 | |
| 
 | |
|   virtual ~Transform();
 | |
| 
 | |
|   /// \brief Apply a transform to all files listed in \p SourcePaths.
 | |
|   ///
 | |
|   /// \p Database must contain information for how to compile all files in \p
 | |
|   /// SourcePaths. \p InputStates contains the file contents of files in \p
 | |
|   /// SourcePaths and should take precedence over content of files on disk.
 | |
|   /// Upon return, \p ResultStates shall contain the result of performing this
 | |
|   /// transform on the files listed in \p SourcePaths.
 | |
|   virtual int apply(FileOverrides &InputStates,
 | |
|                     const clang::tooling::CompilationDatabase &Database,
 | |
|                     const std::vector<std::string> &SourcePaths) = 0;
 | |
| 
 | |
|   /// \brief Query if changes were made during the last call to apply().
 | |
|   bool getChangesMade() const { return AcceptedChanges > 0; }
 | |
| 
 | |
|   /// \brief Query if changes were not made due to conflicts with other changes
 | |
|   /// made during the last call to apply() or if changes were too risky for the
 | |
|   /// requested risk level.
 | |
|   bool getChangesNotMade() const {
 | |
|     return RejectedChanges > 0 || DeferredChanges > 0;
 | |
|   }
 | |
| 
 | |
|   /// \brief Query the number of accepted changes.
 | |
|   unsigned getAcceptedChanges() const { return AcceptedChanges; }
 | |
|   /// \brief Query the number of changes considered too risky.
 | |
|   unsigned getRejectedChanges() const { return RejectedChanges; }
 | |
|   /// \brief Query the number of changes not made because they conflicted with
 | |
|   /// early changes.
 | |
|   unsigned getDeferredChanges() const { return DeferredChanges; }
 | |
| 
 | |
|   /// \brief Query transform name.
 | |
|   llvm::StringRef getName() const { return Name; }
 | |
| 
 | |
|   /// \brief Reset internal state of the transform.
 | |
|   ///
 | |
|   /// Useful if calling apply() several times with one instantiation of a
 | |
|   /// transform.
 | |
|   void Reset() {
 | |
|     AcceptedChanges = 0;
 | |
|     RejectedChanges = 0;
 | |
|     DeferredChanges = 0;
 | |
|   }
 | |
| 
 | |
|   /// \brief Tests if the file containing \a Loc is allowed to be modified by
 | |
|   /// the Migrator.
 | |
|   bool isFileModifiable(const clang::SourceManager &SM,
 | |
|                         const clang::SourceLocation &Loc) const;
 | |
| 
 | |
|   /// \brief Called before parsing a translation unit for a FrontendAction.
 | |
|   ///
 | |
|   /// Transform uses this function to apply file overrides and start
 | |
|   /// performance timers. Subclasses overriding this function must call it
 | |
|   /// before returning.
 | |
|   virtual bool handleBeginSource(clang::CompilerInstance &CI,
 | |
|                                  llvm::StringRef Filename);
 | |
| 
 | |
|   /// \brief Called after FrontendAction has been run over a translation unit.
 | |
|   ///
 | |
|   /// Transform uses this function to stop performance timers. Subclasses
 | |
|   /// overriding this function must call it before returning. A call to
 | |
|   /// handleEndSource() for a given translation unit is expected to be called
 | |
|   /// immediately after the corresponding handleBeginSource() call.
 | |
|   virtual void handleEndSource();
 | |
| 
 | |
|   /// \brief Performance timing data is stored as a vector of pairs. Pairs are
 | |
|   /// formed of:
 | |
|   /// \li Name of source file.
 | |
|   /// \li Elapsed time.
 | |
|   typedef std::vector<std::pair<std::string, llvm::TimeRecord> > TimingVec;
 | |
| 
 | |
|   /// \brief Return an iterator to the start of collected timing data.
 | |
|   TimingVec::const_iterator timing_begin() const { return Timings.begin(); }
 | |
|   /// \brief Return an iterator to the start of collected timing data.
 | |
|   TimingVec::const_iterator timing_end() const { return Timings.end(); }
 | |
| 
 | |
| protected:
 | |
| 
 | |
|   void setAcceptedChanges(unsigned Changes) {
 | |
|     AcceptedChanges = Changes;
 | |
|   }
 | |
|   void setRejectedChanges(unsigned Changes) {
 | |
|     RejectedChanges = Changes;
 | |
|   }
 | |
|   void setDeferredChanges(unsigned Changes) {
 | |
|     DeferredChanges = Changes;
 | |
|   }
 | |
| 
 | |
|   /// \brief Allows subclasses to manually add performance timer data.
 | |
|   ///
 | |
|   /// \p Label should probably include the source file name somehow as the
 | |
|   /// duration info is simply added to the vector of timing data which holds
 | |
|   /// data for all sources processed by this transform.
 | |
|   void addTiming(llvm::StringRef Label, llvm::TimeRecord Duration);
 | |
| 
 | |
|   /// \brief Provide access for subclasses to the TransformOptions they were
 | |
|   /// created with.
 | |
|   const TransformOptions &Options() { return GlobalOptions; }
 | |
| 
 | |
|   /// \brief Provide access for subclasses for the container to store
 | |
|   /// translation unit replacements.
 | |
|   clang::tooling::Replacements &getReplacements() { return Replace; }
 | |
| 
 | |
|   /// \brief Affords a subclass to provide file contents overrides before
 | |
|   /// applying frontend actions.
 | |
|   ///
 | |
|   /// It is an error not to call this function before calling ClangTool::run()
 | |
|   /// with the factory provided by createActionFactory().
 | |
|   void setOverrides(FileOverrides &Overrides) {
 | |
|     this->Overrides = &Overrides;
 | |
|   }
 | |
| 
 | |
|   /// \brief Subclasses must call this function to create a
 | |
|   /// FrontendActionFactory to pass to ClangTool.
 | |
|   ///
 | |
|   /// The factory returned by this function is responsible for calling back to
 | |
|   /// Transform to call handleBeginSource() and handleEndSource().
 | |
|   clang::tooling::FrontendActionFactory *
 | |
|       createActionFactory(clang::ast_matchers::MatchFinder &Finder);
 | |
| 
 | |
| private:
 | |
|   const std::string Name;
 | |
|   const TransformOptions &GlobalOptions;
 | |
|   FileOverrides *Overrides;
 | |
|   clang::tooling::Replacements Replace;
 | |
|   std::string CurrentSource;
 | |
|   TimingVec Timings;
 | |
|   unsigned AcceptedChanges;
 | |
|   unsigned RejectedChanges;
 | |
|   unsigned DeferredChanges;
 | |
| };
 | |
| 
 | |
| /// \brief A factory that can instantiate a specific transform.
 | |
| ///
 | |
| /// Each transform should subclass it and implement the \c createTransform()
 | |
| /// methods. Use \c TransformFactoryRegistry to register the transform globally.
 | |
| ///
 | |
| /// Example:
 | |
| /// \code
 | |
| /// class MyTransform : public Transform { ... };
 | |
| ///
 | |
| /// struct MyFactory : TransformFactory {
 | |
| ///   Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
 | |
| ///     return new MyTransform(Opts);
 | |
| ///   }
 | |
| /// };
 | |
| ///
 | |
| /// // Register the factory using this statically initialized variable.
 | |
| /// static TransformFactoryRegistry::Add<MyFactory>
 | |
| /// X("my-transform", "<Short description of my transform>");
 | |
| ///
 | |
| /// // This anchor is used to force the linker to link in the generated object
 | |
| /// // file and thus register the factory.
 | |
| /// volatile int MyTransformAnchorSource = 0;
 | |
| /// \endcode
 | |
| class TransformFactory {
 | |
| public:
 | |
|   virtual ~TransformFactory();
 | |
|   virtual Transform *createTransform(const TransformOptions &) = 0;
 | |
| };
 | |
| 
 | |
| typedef llvm::Registry<TransformFactory> TransformFactoryRegistry;
 | |
| 
 | |
| #endif // CPP11_MIGRATE_TRANSFORM_H
 |