2012-12-12 22:30:57 +08:00
|
|
|
//===-- cpp11-migrate/Cpp11Migrate.cpp - Main file C++11 migration tool ---===//
|
|
|
|
//
|
|
|
|
// 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 implements the C++11 feature migration tool main function
|
|
|
|
/// and transformation framework.
|
|
|
|
///
|
2013-03-09 03:12:12 +08:00
|
|
|
/// See user documentation for usage instructions.
|
2012-12-12 22:30:57 +08:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-04-05 04:19:58 +08:00
|
|
|
#include "Core/Transforms.h"
|
|
|
|
#include "Core/Transform.h"
|
2013-04-06 03:18:13 +08:00
|
|
|
#include "LoopConvert/LoopConvert.h"
|
|
|
|
#include "UseNullptr/UseNullptr.h"
|
|
|
|
#include "UseAuto/UseAuto.h"
|
2013-04-10 04:49:49 +08:00
|
|
|
#include "AddOverride/AddOverride.h"
|
2012-12-12 22:30:57 +08:00
|
|
|
#include "clang/Frontend/FrontendActions.h"
|
2013-01-02 18:29:31 +08:00
|
|
|
#include "clang/Tooling/CommonOptionsParser.h"
|
2012-12-12 22:30:57 +08:00
|
|
|
#include "clang/Tooling/Tooling.h"
|
2013-01-18 22:31:00 +08:00
|
|
|
#include "llvm/Support/Signals.h"
|
2012-12-12 22:30:57 +08:00
|
|
|
|
|
|
|
namespace cl = llvm::cl;
|
|
|
|
using namespace clang::tooling;
|
|
|
|
|
2013-01-17 05:11:50 +08:00
|
|
|
static cl::opt<RiskLevel> MaxRiskLevel(
|
|
|
|
"risk", cl::desc("Select a maximum risk level:"),
|
|
|
|
cl::values(clEnumValN(RL_Safe, "safe", "Only safe transformations"),
|
|
|
|
clEnumValN(RL_Reasonable, "reasonable",
|
|
|
|
"Enable transformations that might change "
|
|
|
|
"semantics (default)"),
|
|
|
|
clEnumValN(RL_Risky, "risky",
|
|
|
|
"Enable transformations that are likely to "
|
|
|
|
"change semantics"),
|
2013-01-05 02:25:18 +08:00
|
|
|
clEnumValEnd),
|
2013-01-17 05:11:50 +08:00
|
|
|
cl::init(RL_Reasonable));
|
2012-12-12 22:30:57 +08:00
|
|
|
|
2013-03-02 04:53:43 +08:00
|
|
|
static cl::opt<bool> FinalSyntaxCheck(
|
|
|
|
"final-syntax-check",
|
|
|
|
cl::desc("Check for correct syntax after applying transformations"),
|
|
|
|
cl::init(false));
|
|
|
|
|
2013-03-05 08:12:33 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
SummaryMode("summary", cl::desc("Print transform summary"),
|
|
|
|
cl::init(false));
|
|
|
|
|
2013-01-23 02:31:49 +08:00
|
|
|
class EndSyntaxArgumentsAdjuster : public ArgumentsAdjuster {
|
|
|
|
CommandLineArguments Adjust(const CommandLineArguments &Args) {
|
|
|
|
CommandLineArguments AdjustedArgs = Args;
|
|
|
|
AdjustedArgs.push_back("-fsyntax-only");
|
|
|
|
AdjustedArgs.push_back("-std=c++11");
|
|
|
|
return AdjustedArgs;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-12-12 22:30:57 +08:00
|
|
|
int main(int argc, const char **argv) {
|
2013-01-18 22:31:00 +08:00
|
|
|
llvm::sys::PrintStackTraceOnErrorSignal();
|
2013-01-05 02:25:18 +08:00
|
|
|
Transforms TransformManager;
|
|
|
|
|
2013-04-06 03:18:13 +08:00
|
|
|
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>);
|
2013-04-10 04:49:49 +08:00
|
|
|
TransformManager.registerTransform(
|
|
|
|
"add-override", "Make use of override specifier where possible",
|
|
|
|
&ConstructTransform<AddOverrideTransform>);
|
2013-04-06 03:18:13 +08:00
|
|
|
// Add more transform options here.
|
2013-01-05 02:25:18 +08:00
|
|
|
|
|
|
|
// This causes options to be parsed.
|
2012-12-12 22:30:57 +08:00
|
|
|
CommonOptionsParser OptionsParser(argc, argv);
|
|
|
|
|
2013-01-05 02:25:18 +08:00
|
|
|
TransformManager.createSelectedTransforms();
|
|
|
|
|
|
|
|
if (TransformManager.begin() == TransformManager.end()) {
|
|
|
|
llvm::errs() << "No selected transforms\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-01-17 05:11:50 +08:00
|
|
|
FileContentsByPath FileStates1, FileStates2,
|
|
|
|
*InputFileStates = &FileStates1, *OutputFileStates = &FileStates2;
|
|
|
|
|
2013-01-05 02:25:18 +08:00
|
|
|
// Apply transforms.
|
|
|
|
for (Transforms::const_iterator I = TransformManager.begin(),
|
2013-01-17 05:11:50 +08:00
|
|
|
E = TransformManager.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if ((*I)->apply(*InputFileStates, MaxRiskLevel,
|
|
|
|
OptionsParser.getCompilations(),
|
|
|
|
OptionsParser.getSourcePathList(), *OutputFileStates) !=
|
|
|
|
0) {
|
|
|
|
// FIXME: Improve ClangTool to not abort if just one file fails.
|
2013-01-05 02:25:18 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2013-03-05 08:12:33 +08:00
|
|
|
if (SummaryMode) {
|
|
|
|
llvm::outs() << "Transform: " << (*I)->getName()
|
|
|
|
<< " - Accepted: "
|
|
|
|
<< (*I)->getAcceptedChanges();
|
|
|
|
if ((*I)->getChangesNotMade()) {
|
|
|
|
llvm::outs() << " - Rejected: "
|
|
|
|
<< (*I)->getRejectedChanges()
|
|
|
|
<< " - Deferred: "
|
|
|
|
<< (*I)->getDeferredChanges();
|
|
|
|
}
|
|
|
|
llvm::outs() << "\n";
|
|
|
|
}
|
2013-01-17 05:11:50 +08:00
|
|
|
std::swap(InputFileStates, OutputFileStates);
|
|
|
|
OutputFileStates->clear();
|
2013-01-05 02:25:18 +08:00
|
|
|
}
|
|
|
|
|
2013-01-17 05:11:50 +08:00
|
|
|
// Final state of files is pointed at by InputFileStates.
|
|
|
|
|
2013-03-02 04:53:43 +08:00
|
|
|
if (FinalSyntaxCheck) {
|
|
|
|
ClangTool EndSyntaxTool(OptionsParser.getCompilations(),
|
|
|
|
OptionsParser.getSourcePathList());
|
2013-01-23 02:31:49 +08:00
|
|
|
|
2013-03-02 04:53:43 +08:00
|
|
|
// Add c++11 support to clang.
|
|
|
|
EndSyntaxTool.setArgumentsAdjuster(new EndSyntaxArgumentsAdjuster);
|
2013-01-23 02:31:49 +08:00
|
|
|
|
2013-03-02 04:53:43 +08:00
|
|
|
for (FileContentsByPath::const_iterator I = InputFileStates->begin(),
|
|
|
|
E = InputFileStates->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
EndSyntaxTool.mapVirtualFile(I->first, I->second);
|
|
|
|
}
|
2013-01-17 05:11:50 +08:00
|
|
|
|
2013-03-02 04:53:43 +08:00
|
|
|
if (EndSyntaxTool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>())
|
|
|
|
!= 0) {
|
|
|
|
return 1;
|
|
|
|
}
|
2013-01-05 02:25:18 +08:00
|
|
|
}
|
2012-12-12 22:30:57 +08:00
|
|
|
|
2013-03-02 04:53:43 +08:00
|
|
|
// Write results to file.
|
2013-01-17 05:11:50 +08:00
|
|
|
for (FileContentsByPath::const_iterator I = InputFileStates->begin(),
|
|
|
|
E = InputFileStates->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
std::string ErrorInfo;
|
|
|
|
llvm::raw_fd_ostream FileStream(I->first.c_str(), ErrorInfo,
|
|
|
|
llvm::raw_fd_ostream::F_Binary);
|
|
|
|
FileStream << I->second;
|
|
|
|
}
|
|
|
|
|
2012-12-12 22:30:57 +08:00
|
|
|
return 0;
|
|
|
|
}
|