- Review fixes, tests improved.
Hi revane, arielbernal, tareqsiraj,
http://llvm-reviews.chandlerc.com/D1202
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1202?vs=2971&id=2990#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
docs/MigratorUsage.rst
test/cpp11-migrate/Combined/compilers.cpp
Index: cpp11-migrate/AddOverride/AddOverride.cpp
===================================================================
--- cpp11-migrate/AddOverride/AddOverride.cpp
+++ cpp11-migrate/AddOverride/AddOverride.cpp
@@ -61,6 +61,18 @@
}
struct AddOverrideFactory : TransformFactory {
+ AddOverrideFactory() {
+ // if detecting macros is enabled, do not impose requirements on the
+ // compiler. It is assumed that the macros use is "C++11-aware", meaning it
+ // won't expand to override if the compiler doesn't support the specifier.
+ if (!DetectMacros) {
+ Since.Clang = Version(3, 0);
+ Since.Gcc = Version(4, 7);
+ Since.Icc = Version(14);
+ Since.Msvc = Version(8);
+ }
+ }
+
Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
return new AddOverrideTransform(Opts);
}
Index: cpp11-migrate/Core/Transform.cpp
===================================================================
--- cpp11-migrate/Core/Transform.cpp
+++ cpp11-migrate/Core/Transform.cpp
@@ -20,6 +20,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
using namespace clang;
@@ -132,4 +133,32 @@
return new ActionFactory(Finder, /*Owner=*/ *this);
}
+Version Version::getFromString(llvm::StringRef VersionStr) {
+ llvm::StringRef MajorStr, MinorStr;
+ Version V;
+
+ llvm::tie(MajorStr, MinorStr) = VersionStr.split('.');
+ if (!MinorStr.empty() && MinorStr.getAsInteger(10, V.Minor))
+ return Version();
+ if (MajorStr.getAsInteger(10, V.Major))
+ return Version();
+ return V;
+}
+
TransformFactory::~TransformFactory() {}
+
+namespace {
+bool versionSupported(Version Required, Version AvailableSince) {
+ // null version, means no requirements, means supported
+ if (Required.isNull())
+ return true;
+ return Required >= AvailableSince;
+}
+} // end anonymous namespace
+
+bool TransformFactory::supportsRequirements(CompilerVersions Required) const {
+ return versionSupported(Required.Clang, Since.Clang) &&
+ versionSupported(Required.Gcc, Since.Gcc) &&
+ versionSupported(Required.Icc, Since.Icc) &&
+ versionSupported(Required.Msvc, Since.Msvc);
+}
Index: cpp11-migrate/Core/Transform.h
===================================================================
--- cpp11-migrate/Core/Transform.h
+++ cpp11-migrate/Core/Transform.h
@@ -71,6 +71,9 @@
/// \brief Maximum allowed level of risk.
RiskLevel MaxRiskLevel;
+
+ /// \brief Whether all transforms should be enabled by default or not.
+ bool EnableAllTransformsByDefault;
};
/// \brief Abstract base class for all C++11 migration transforms.
@@ -222,16 +225,72 @@
unsigned DeferredChanges;
};
+/// \brief Describes a version number of the form major[.minor] (minor being
+/// optional).
+struct Version {
+ explicit Version(unsigned Major = 0, unsigned Minor = 0)
+ : Major(Major), Minor(Minor) {}
+
+ bool operator<(Version RHS) const {
+ if (Major < RHS.Major)
+ return true;
+ if (Major == RHS.Major)
+ return Minor < RHS.Minor;
+ return false;
+ }
+
+ bool operator==(Version RHS) const {
+ return Major == RHS.Major && Minor == RHS.Minor;
+ }
+
+ bool operator!=(Version RHS) const { return !(*this == RHS); }
+ bool operator>(Version RHS) const { return RHS < *this; }
+ bool operator<=(Version RHS) const { return !(*this > RHS); }
+ bool operator>=(Version RHS) const { return !(*this < RHS); }
+
+ bool isNull() const { return Minor == 0 && Major == 0; }
+ unsigned getMajor() const { return Major; }
+ unsigned getMinor() const { return Minor; }
+
+ /// \brief Creates a version from a string of the form \c MAJOR[.MINOR].
+ ///
+ /// \return A null version is returned on error.
+ static Version getFromString(llvm::StringRef VersionStr);
+
+private:
+ unsigned Major;
+ unsigned Minor;
+};
+
+/// \brief Convenience structure to store the version of some compilers.
+struct CompilerVersions {
+ Version Clang, Gcc, Icc, Msvc;
+};
+
/// \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.
+/// method.
+///
+/// Some constraints can informed about the compiler versions supported by the
+/// transform. These constraints should be set in the constructor as show in the
+/// example.
+///
+/// Note that you should use \c TransformFactoryRegistry to register the
+/// transform globally.
///
/// Example:
/// \code
/// class MyTransform : public Transform { ... };
///
/// struct MyFactory : TransformFactory {
+/// MyFactory() {
+/// Since.Clang = Version(3, 0);
+/// Since.Gcc = Version(4, 7);
+/// Since.Icc = Version(12);
+/// Since.Msvc = Version(10);
+/// }
+///
/// Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
/// return new MyTransform(Opts);
/// }
@@ -249,6 +308,17 @@
public:
virtual ~TransformFactory();
virtual Transform *createTransform(const TransformOptions &) = 0;
+
+ /// \brief Whether the transform is supported by the required compilers or
+ /// not.
+ bool supportsRequirements(CompilerVersions Required) const;
+
+protected:
+ /// \brief Since when the C++11 feature introduced by this transform has been
+ /// available.
+ ///
+ /// Can be set by the sub-class in the constructor body.
+ CompilerVersions Since;
};
typedef llvm::Registry<TransformFactory> TransformFactoryRegistry;
Index: cpp11-migrate/Core/Transforms.cpp
===================================================================
--- cpp11-migrate/Core/Transforms.cpp
+++ cpp11-migrate/Core/Transforms.cpp
@@ -38,16 +38,19 @@
}
void
-Transforms::createSelectedTransforms(const TransformOptions &GlobalOptions) {
+Transforms::createSelectedTransforms(const TransformOptions &GlobalOptions,
+ const CompilerVersions &RequiredVersions) {
for (TransformFactoryRegistry::iterator I = TransformFactoryRegistry::begin(),
E = TransformFactoryRegistry::end();
I != E; ++I) {
- bool OptionEnabled = *Options[I->getName()];
+ bool OptionEnabled =
+ GlobalOptions.EnableAllTransformsByDefault || *Options[I->getName()];
if (!OptionEnabled)
continue;
llvm::OwningPtr<TransformFactory> Factory(I->instantiate());
- ChosenTransforms.push_back(Factory->createTransform(GlobalOptions));
+ if (Factory->supportsRequirements(RequiredVersions))
+ ChosenTransforms.push_back(Factory->createTransform(GlobalOptions));
}
}
Index: cpp11-migrate/Core/Transforms.h
===================================================================
--- cpp11-migrate/Core/Transforms.h
+++ cpp11-migrate/Core/Transforms.h
@@ -30,6 +30,7 @@
} // namespace llvm
class Transform;
struct TransformOptions;
+struct CompilerVersions;
typedef Transform *(*TransformCreator)(const TransformOptions &);
template <typename T>
@@ -57,7 +58,8 @@
/// \brief Instantiate all transforms that were selected on the command line.
///
/// Call *after* parsing options.
- void createSelectedTransforms(const TransformOptions &Options);
+ void createSelectedTransforms(const TransformOptions &Options,
+ const CompilerVersions &RequiredVersions);
/// \brief Return an iterator to the start of a container of instantiated
/// transforms.
Index: cpp11-migrate/LoopConvert/LoopConvert.cpp
===================================================================
--- cpp11-migrate/LoopConvert/LoopConvert.cpp
+++ cpp11-migrate/LoopConvert/LoopConvert.cpp
@@ -68,6 +68,13 @@
}
struct LoopConvertFactory : TransformFactory {
+ LoopConvertFactory() {
+ Since.Clang = Version(3, 0);
+ Since.Gcc = Version(4, 6);
+ Since.Icc = Version(13);
+ Since.Msvc = Version(11);
+ }
+
Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
return new LoopConvertTransform(Opts);
}
Index: cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
===================================================================
--- cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
+++ cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
@@ -50,6 +50,13 @@
}
struct ReplaceAutoPtrFactory : TransformFactory {
+ ReplaceAutoPtrFactory() {
+ Since.Clang = Version(3, 0);
+ Since.Gcc = Version(4, 6);
+ Since.Icc = Version(13);
+ Since.Msvc = Version(11);
+ }
+
Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
return new ReplaceAutoPtrTransform(Opts);
}
Index: cpp11-migrate/UseAuto/UseAuto.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAuto.cpp
+++ cpp11-migrate/UseAuto/UseAuto.cpp
@@ -49,6 +49,13 @@
}
struct UseAutoFactory : TransformFactory {
+ UseAutoFactory() {
+ Since.Clang = Version(2, 9);
+ Since.Gcc = Version(4, 4);
+ Since.Icc = Version(12);
+ Since.Msvc = Version(10);
+ }
+
Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
return new UseAutoTransform(Opts);
}
Index: cpp11-migrate/UseNullptr/UseNullptr.cpp
===================================================================
--- cpp11-migrate/UseNullptr/UseNullptr.cpp
+++ cpp11-migrate/UseNullptr/UseNullptr.cpp
@@ -50,6 +50,13 @@
}
struct UseNullptrFactory : TransformFactory {
+ UseNullptrFactory() {
+ Since.Clang = Version(3, 0);
+ Since.Gcc = Version(4, 6);
+ Since.Icc = Version(12, 1);
+ Since.Msvc = Version(10);
+ }
+
Transform *createTransform(const TransformOptions &Opts) LLVM_OVERRIDE {
return new UseNullptrTransform(Opts);
}
Index: cpp11-migrate/tool/Cpp11Migrate.cpp
===================================================================
--- cpp11-migrate/tool/Cpp11Migrate.cpp
+++ cpp11-migrate/tool/Cpp11Migrate.cpp
@@ -24,6 +24,8 @@
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
@@ -113,6 +115,75 @@
cl::location(GlobalOptions.EnableHeaderModifications),
cl::init(false));
+cl::list<std::string> Supports(
+ "supports", cl::value_desc("platform"), cl::ZeroOrMore,
+ cl::desc("Add a platform to be supported by the migration.\n"
+ "All transforms supported by all of the given platforms"
+ " will be used for the migration.\n"
+ "Currently supports:\n"
+ "\tc++11 (turn on all transforms), clang-VERSION, gcc-VERSION, "
+ "icc-VERSION and msvc-VERSION\n"));
+
+/// \brief Extract the minimum compiler versions as requested on the command
+/// line by the switch \c -supports.
+///
+/// \param ProgName The name of the program, \c argv[0], used to print errors.
+/// \param Error If an error occur while parsing the versions this parameter is
+/// set to \c true, otherwise it will be left untouched.
+static CompilerVersions handleSupportsCommand(const char *ProgName,
+ bool &Error) {
+ CompilerVersions RequiredVersions;
+
+ GlobalOptions.EnableAllTransformsByDefault = false;
+ for (std::vector<std::string>::iterator I = Supports.begin(),
+ E = Supports.end();
+ I != E; ++I) {
+ llvm::StringRef Platform = *I;
+
+ // If c++11 is specified or if a compiler version is required, enable all
+ // transforms by default.
+ GlobalOptions.EnableAllTransformsByDefault = true;
+
+ // check for c++11
+ if (Platform == "c++11")
+ continue;
+
+ // otherwise assume "plaform-version" format
+ llvm::StringRef VersionStr;
+ llvm::tie(Platform, VersionStr) = Platform.split('-');
+
+ Version *V = llvm::StringSwitch<Version *>(Platform)
+ .Case("clang", &RequiredVersions.Clang)
+ .Case("gcc", &RequiredVersions.Gcc).Case("icc", &RequiredVersions.Icc)
+ .Case("msvc", &RequiredVersions.Msvc).Default(NULL);
+
+ if (V == NULL) {
+ llvm::errs() << ProgName << ": " << Platform
+ << ": unsupported platform\n";
+ Error = true;
+ continue;
+ }
+ if (VersionStr.empty()) {
+ llvm::errs() << ProgName << ": " << *I
+ << ": missing version number in platform\n";
+ Error = true;
+ continue;
+ }
+
+ Version Version = Version::getFromString(VersionStr);
+ if (Version.isNull()) {
+ llvm::errs() << ProgName << ": " << Platform << ": invalid version "
+ << VersionStr << "\n";
+ Error = true;
+ continue;
+ }
+ // support the lowest version given
+ if (V->isNull() || Version < *V)
+ *V = Version;
+ }
+ return RequiredVersions;
+}
+
/// \brief Creates the Reformatter if the format style option is provided,
/// return a null pointer otherwise.
///
@@ -161,10 +232,13 @@
GlobalOptions.EnableTiming = (TimingDirectoryName != NoTiming);
// Check the reformatting style option
- bool BadStyle = false;
+ bool CmdSwitchError = false;
llvm::OwningPtr<Reformatter> ChangesReformatter(
- handleFormatStyle(argv[0], BadStyle));
- if (BadStyle)
+ handleFormatStyle(argv[0], CmdSwitchError));
+
+ CompilerVersions RequiredVersions =
+ handleSupportsCommand(argv[0], CmdSwitchError);
+ if (CmdSwitchError)
return 1;
// Populate the ModifiableHeaders structure if header modifications are
@@ -176,10 +250,13 @@
.readListFromFile(IncludeFromFile, ExcludeFromFile);
}
- TransformManager.createSelectedTransforms(GlobalOptions);
+ TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions);
if (TransformManager.begin() == TransformManager.end()) {
- llvm::errs() << argv[0] << ": No selected transforms\n";
+ if (Supports.empty())
+ llvm::errs() << argv[0] << ": No selected transforms\n";
+ else
+ llvm::errs() << argv[0] << ": No transforms supported\n";
return 1;
}
Index: docs/MigratorUsage.rst
===================================================================
--- docs/MigratorUsage.rst
+++ docs/MigratorUsage.rst
@@ -113,6 +113,58 @@
with other accepted changes. Re-applying the transform will resolve deferred
changes.
+.. option:: -supports <platform>
+
+ Select the platforms to support. Transforms will be selected automatically to
+ work on all selected platforms.
+
+ There is a special platform **c++11** that enables all transforms.
+
+ ``cpp11-migrate -supports c++11 <args..>``
+
+
+ Four compilers are supported. The transforms are enabled according to this
+ table:
+
+ =============== ===== === ==== ====
+ Transforms clang gcc icc mscv
+ =============== ===== === ==== ====
+ AddOverride (1) 3.0 4.7 14 8
+ LoopConvert 3.0 4.6 13 11
+ ReplaceAutoPtr 3.0 4.6 13 11
+ UseAuto 2.9 4.4 12 10
+ UseNullptr 3.0 4.6 12.1 10
+ =============== ===== === ==== ====
+
+ (1): if *-override-macros* is provided it's assumed that the macros are C++11
+ aware and the transform is enabled without regard to the supported compilers.
+
+ The structure of the argument to the `-supports` option is **<compiler>-<major
+ ver>[.<minor ver>]** where **<compiler>** is one of the compilers from the
+ above table.
+
+ Some examples:
+
+ 1. To support `Clang >= 3`, `GCC >= 4.6` and `MSVC >= 11`:
+
+ ``cpp11-migrate -supports clang-3.0 -supports gcc-4.6 -supports msvc-11
+ <args..>``
+
+ Enables LoopConvert, ReplaceAutoPtr, UseAuto, UseNullptr.
+
+ 2. To support `icc >= 12` while using a C++11-aware macro for the `override`
+ virtual specifier:
+
+ ``cpp11-migrate -supports icc-12 -override-macros <args..>``
+
+ Enables AddOverride and UseAuto.
+
+ .. warning::
+
+ If your version of Clang depends on the GCC headers (e.g: when `libc++` is
+ not used), then you probably want to add the GCC version to the targeted
+ platforms as well.
+
.. option:: -perf[=<directory>]
Turns on performance measurement and output functionality. The time it takes to
Index: test/cpp11-migrate/Combined/compilers.cpp
===================================================================
--- /dev/null
+++ test/cpp11-migrate/Combined/compilers.cpp
@@ -0,0 +1,66 @@
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports c++11 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=CPP11 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports clang-2.9 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=CLANG-29 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports clang-2.9 -override-macros %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=CLANG-29-OV-MACROS -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports clang-3.0 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=CLANG-30 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports gcc-4.6 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=GCC-46 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports gcc-4.7 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=GCC-47 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports icc-13 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=ICC-13 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports icc-14 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=ICC-14 -input-file=%t.cpp %s
+//
+// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -supports msvc-8 %t.cpp -- -std=c++11
+// RUN: FileCheck -check-prefix=MSVC-8 -input-file=%t.cpp %s
+//
+// Test unknown platform
+// RUN: not cpp11-migrate -supports foo-10 %t.cpp -- -std=c++11
+//
+// Test invalid or unsupported version schemes
+// RUN: not cpp11-migrate -supports clang-3.4.0 %t.cpp -- -std=c++11
+// RUN: not cpp11-migrate -supports clang-3.4a %t.cpp -- -std=c++11
+//
+// Test when no transforms can be selected because the compiler lacks support of
+// the needed C++11 features
+// RUN: not cpp11-migrate -supports clang-2.0 %t.cpp -- -std=c++11
+
+// Test add overrides
+struct A {
+ virtual A *clone() = 0;
+};
+
+#define LLVM_OVERRIDE override
+
+struct B : A {
+ virtual B *clone();
+ // CPP11: virtual B *clone() override;
+ // CLANG-29-OV-MACROS: virtual B *clone() LLVM_OVERRIDE;
+ // CLANG-29: virtual B *clone();
+ // CLANG-30: virtual B *clone() override;
+ // GCC-46: virtual B *clone();
+ // GCC-47: virtual B *clone() override;
+ // ICC-13: virtual B *clone();
+ // ICC-14: virtual B *clone() override;
+ // MSVC-8: virtual B *clone() override;
+};
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits