I fixed my code according to the review:
    - Undo clang-format on unrelated code.
    - Add anchor destinations to the main file.

  Now the transforms can be converted to a library system and it should still
  work.

  For example I tried to make the AddOverride a library,
  AddOverride/CMakeLists.txt was:

    set(LLVM_LINK_COMPONENTS support)

    add_clang_library(migrateAddOverrideTransform
      AddOverrideActions.cpp
      AddOverride.cpp
      AddOverrideMatchers.cpp
      )

    target_link_libraries(migrateAddOverrideTransform
      migrateCore
      )

  Then in tool/CMakeLists.txt I used:

    -file(GLOB_RECURSE AddOverrideSources "../AddOverride/*.cpp")
    -list(APPEND Cpp11MigrateSources ${AddOverrideSources})
    +# file(GLOB_RECURSE AddOverrideSources "../AddOverride/*.cpp")
    +# list(APPEND Cpp11MigrateSources ${AddOverrideSources})

    <...>

     target_link_libraries(cpp11-migrate
       migrateCore
    +  migrateAddOverrideTransform
       )


  I linked this library and it worked, displaying the command line option and
  passing the tests. I believe this is a [long-term] goal to have
  "library-transform".

Hi revane, arielbernal, tareqsiraj,

http://llvm-reviews.chandlerc.com/D1196

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1196?vs=2944&id=2969#toc

Files:
  cpp11-migrate/AddOverride/AddOverride.cpp
  cpp11-migrate/Core/Transform.cpp
  cpp11-migrate/Core/Transform.h
  cpp11-migrate/Core/Transforms.cpp
  cpp11-migrate/Core/Transforms.h
  cpp11-migrate/LoopConvert/LoopConvert.cpp
  cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
  cpp11-migrate/UseAuto/UseAuto.cpp
  cpp11-migrate/UseNullptr/UseNullptr.cpp
  cpp11-migrate/tool/Cpp11Migrate.cpp
Index: cpp11-migrate/AddOverride/AddOverride.cpp
===================================================================
--- cpp11-migrate/AddOverride/AddOverride.cpp
+++ cpp11-migrate/AddOverride/AddOverride.cpp
@@ -59,3 +59,17 @@
   Fixer->setPreprocessor(CI.getPreprocessor());
   return Transform::handleBeginSource(CI, Filename);
 }
+
+struct AddOverrideFactory : TransformFactory {
+  Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
+    return new AddOverrideTransform(Opts);
+  }
+};
+
+// Register the factory using this statically initialized variable.
+static TransformFactoryRegistry::Add<AddOverrideFactory>
+X("add-override", "Make use of override specifier where possible");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the factory.
+volatile int AddOverrideTransformAnchorSource = 0;
Index: cpp11-migrate/Core/Transform.cpp
===================================================================
--- cpp11-migrate/Core/Transform.cpp
+++ cpp11-migrate/Core/Transform.cpp
@@ -132,3 +132,5 @@
 Transform::createActionFactory(MatchFinder &Finder) {
   return new ActionFactory(Finder, /*Owner=*/ *this);
 }
+
+TransformFactory::~TransformFactory() {}
Index: cpp11-migrate/Core/Transform.h
===================================================================
--- cpp11-migrate/Core/Transform.h
+++ cpp11-migrate/Core/Transform.h
@@ -20,8 +20,8 @@
 #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>
 
@@ -222,4 +222,35 @@
   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
Index: cpp11-migrate/Core/Transforms.cpp
===================================================================
--- cpp11-migrate/Core/Transforms.cpp
+++ cpp11-migrate/Core/Transforms.cpp
@@ -20,31 +20,34 @@
 static cl::OptionCategory TransformCategory("Transforms");
 
 Transforms::~Transforms() {
-  for (std::vector<Transform*>::iterator I = ChosenTransforms.begin(),
-       E = ChosenTransforms.end(); I != E; ++I) {
+  for (std::vector<Transform *>::iterator I = ChosenTransforms.begin(),
+                                          E = ChosenTransforms.end();
+       I != E; ++I)
     delete *I;
-  }
-  for (OptionVec::iterator I = Options.begin(),
-       E = Options.end(); I != E; ++I) {
-    delete I->first;
-  }
+
+  for (OptionMap::iterator I = Options.begin(), E = Options.end(); I != E; ++I)
+    delete I->getValue();
 }
 
-void Transforms::registerTransform(llvm::StringRef OptName,
-                                   llvm::StringRef Description,
-                                   TransformCreator Creator) {
-  Options.push_back(OptionVec::value_type(
-      new cl::opt<bool>(OptName.data(), cl::desc(Description.data()),
-                        cl::cat(TransformCategory)),
-      Creator));
+void Transforms::registerTransforms() {
+  for (TransformFactoryRegistry::iterator I = TransformFactoryRegistry::begin(),
+                                          E = TransformFactoryRegistry::end();
+       I != E; ++I)
+    Options[I->getName()] = new cl::opt<bool>(
+        I->getName(), cl::desc(I->getDesc()), cl::cat(TransformCategory));
 }
 
 void
 Transforms::createSelectedTransforms(const TransformOptions &GlobalOptions) {
-  for (OptionVec::iterator I = Options.begin(),
-       E = Options.end(); I != E; ++I) {
-    if (*I->first) {
-      ChosenTransforms.push_back(I->second(GlobalOptions));
-    }
+  for (TransformFactoryRegistry::iterator I = TransformFactoryRegistry::begin(),
+                                          E = TransformFactoryRegistry::end();
+       I != E; ++I) {
+    bool OptionEnabled = *Options[I->getName()];
+
+    if (!OptionEnabled)
+      continue;
+
+    llvm::OwningPtr<TransformFactory> Factory(I->instantiate());
+    ChosenTransforms.push_back(Factory->createTransform(GlobalOptions));
   }
 }
Index: cpp11-migrate/Core/Transforms.h
===================================================================
--- cpp11-migrate/Core/Transforms.h
+++ cpp11-migrate/Core/Transforms.h
@@ -48,12 +48,11 @@
 
   ~Transforms();
 
-  /// \brief Registers a transform causing the transform to be made available
-  /// on the command line.
+  /// \brief Registers all available transforms causing them to be made
+  /// available on the command line.
   ///
   /// Be sure to register all transforms *before* parsing command line options.
-  void registerTransform(llvm::StringRef OptName, llvm::StringRef Description,
-                         TransformCreator Creator);
+  void registerTransforms();
 
   /// \brief Instantiate all transforms that were selected on the command line.
   ///
@@ -69,12 +68,11 @@
   const_iterator end() const { return ChosenTransforms.end(); }
 
 private:
-  typedef std::vector<std::pair<llvm::cl::opt<bool>*, TransformCreator> >
-    OptionVec;
+  typedef llvm::StringMap<llvm::cl::opt<bool> *> OptionMap;
 
 private:
   TransformVec ChosenTransforms;
-  OptionVec Options;
+  OptionMap Options;
 };
 
 #endif // CPP11_MIGRATE_TRANSFORMS_H
Index: cpp11-migrate/LoopConvert/LoopConvert.cpp
===================================================================
--- cpp11-migrate/LoopConvert/LoopConvert.cpp
+++ cpp11-migrate/LoopConvert/LoopConvert.cpp
@@ -66,3 +66,17 @@
 
   return 0;
 }
+
+struct LoopConvertFactory : TransformFactory {
+  Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
+    return new LoopConvertTransform(Opts);
+  }
+};
+
+// Register the factory using this statically initialized variable.
+static TransformFactoryRegistry::Add<LoopConvertFactory>
+X("loop-convert", "Make use of range-based for loops where possible");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the factory.
+volatile int LoopConvertTransformAnchorSource = 0;
Index: cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
===================================================================
--- cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
+++ cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
@@ -48,3 +48,18 @@
 
   return 0;
 }
+
+struct ReplaceAutoPtrFactory : TransformFactory {
+  Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
+    return new ReplaceAutoPtrTransform(Opts);
+  }
+};
+
+// Register the factory using this statically initialized variable.
+static TransformFactoryRegistry::Add<ReplaceAutoPtrFactory>
+X("replace-auto_ptr", "Replace std::auto_ptr (deprecated) by std::unique_ptr"
+                      " (EXPERIMENTAL)");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the factory.
+volatile int ReplaceAutoPtrTransformAnchorSource = 0;
Index: cpp11-migrate/UseAuto/UseAuto.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAuto.cpp
+++ cpp11-migrate/UseAuto/UseAuto.cpp
@@ -47,3 +47,17 @@
 
   return 0;
 }
+
+struct UseAutoFactory : TransformFactory {
+  Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
+    return new UseAutoTransform(Opts);
+  }
+};
+
+// Register the factory using this statically initialized variable.
+static TransformFactoryRegistry::Add<UseAutoFactory>
+X("use-auto", "Use of 'auto' type specifier");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the factory.
+volatile int UseAutoTransformAnchorSource = 0;
Index: cpp11-migrate/UseNullptr/UseNullptr.cpp
===================================================================
--- cpp11-migrate/UseNullptr/UseNullptr.cpp
+++ cpp11-migrate/UseNullptr/UseNullptr.cpp
@@ -48,3 +48,17 @@
 
   return 0;
 }
+
+struct UseNullptrFactory : TransformFactory {
+  Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
+    return new UseNullptrTransform(Opts);
+  }
+};
+
+// Register the factory using this statically initialized variable.
+static TransformFactoryRegistry::Add<UseNullptrFactory>
+X("use-nullptr", "Make use of nullptr keyword where possible");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the factory.
+volatile int UseNullptrTransformAnchorSource = 0;
Index: cpp11-migrate/tool/Cpp11Migrate.cpp
===================================================================
--- cpp11-migrate/tool/Cpp11Migrate.cpp
+++ cpp11-migrate/tool/Cpp11Migrate.cpp
@@ -21,11 +21,6 @@
 #include "Core/Transform.h"
 #include "Core/Transforms.h"
 #include "Core/Reformatting.h"
-#include "LoopConvert/LoopConvert.h"
-#include "UseNullptr/UseNullptr.h"
-#include "UseAuto/UseAuto.h"
-#include "AddOverride/AddOverride.h"
-#include "ReplaceAutoPtr/ReplaceAutoPtr.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Tooling.h"
@@ -156,23 +151,7 @@
   llvm::sys::PrintStackTraceOnErrorSignal();
   Transforms TransformManager;
 
-  TransformManager.registerTransform(
-      "loop-convert", "Make use of range-based for loops where possible",
-      &ConstructTransform<LoopConvertTransform>);
-  TransformManager.registerTransform(
-      "use-nullptr", "Make use of nullptr keyword where possible",
-      &ConstructTransform<UseNullptrTransform>);
-  TransformManager.registerTransform(
-      "use-auto", "Use of 'auto' type specifier",
-      &ConstructTransform<UseAutoTransform>);
-  TransformManager.registerTransform(
-      "add-override", "Make use of override specifier where possible",
-      &ConstructTransform<AddOverrideTransform>);
-  TransformManager.registerTransform(
-      "replace-auto_ptr", "Replace auto_ptr (deprecated) by unique_ptr"
-                          " (EXPERIMENTAL)",
-      &ConstructTransform<ReplaceAutoPtrTransform>);
-  // Add more transform options here.
+  TransformManager.registerTransforms();
 
   // This causes options to be parsed.
   CommonOptionsParser OptionsParser(argc, argv);
@@ -293,3 +272,18 @@
 
   return 0;
 }
+
+// These anchors are used to force the linker to link the transforms
+extern volatile int AddOverrideTransformAnchorSource;
+extern volatile int LoopConvertTransformAnchorSource;
+extern volatile int ReplaceAutoPtrTransformAnchorSource;
+extern volatile int UseAutoTransformAnchorSource;
+extern volatile int UseNullptrTransformAnchorSource;
+
+static int TransformsAnchorsDestination[] = {
+  AddOverrideTransformAnchorSource,
+  LoopConvertTransformAnchorSource,
+  ReplaceAutoPtrTransformAnchorSource,
+  UseAutoTransformAnchorSource,
+  UseNullptrTransformAnchorSource
+};
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to