From e6f854353eca5e8d0fb1506126b15428edf99ff5 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Tue, 24 Oct 2017 13:10:58 +0000 Subject: [PATCH] [Tooling] Add a factory method for CommonOptionsParser Summary: This returns error instead of exiting the program in case of error. Reviewers: klimek, hokein Reviewed By: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D39042 llvm-svn: 316433 --- clang/include/clang/Tooling/CommonOptionsParser.h | 17 ++++++++- clang/lib/Tooling/CommonOptionsParser.cpp | 45 ++++++++++++++++++++--- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/Tooling/CommonOptionsParser.h b/clang/include/clang/Tooling/CommonOptionsParser.h index 70f5e80..e89b59c 100644 --- a/clang/include/clang/Tooling/CommonOptionsParser.h +++ b/clang/include/clang/Tooling/CommonOptionsParser.h @@ -30,6 +30,7 @@ #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" namespace clang { namespace tooling { @@ -86,13 +87,18 @@ public: /// All options not belonging to \p Category become hidden. /// /// It also allows calls to set the required number of positional parameters. - /// - /// This constructor exits program in case of error. CommonOptionsParser(int &argc, const char **argv, llvm::cl::OptionCategory &Category, llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview = nullptr); + /// \brief A factory method that is similar to the above constructor, except + /// this returns an error instead exiting the program on error. + static llvm::Expected + create(int &argc, const char **argv, llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, + const char *Overview = nullptr); + /// Returns a reference to the loaded compilations database. CompilationDatabase &getCompilations() { return *Compilations; @@ -106,6 +112,13 @@ public: static const char *const HelpMessage; private: + CommonOptionsParser() = default; + + llvm::Error init(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, + const char *Overview); + std::unique_ptr Compilations; std::vector SourcePathList; }; diff --git a/clang/lib/Tooling/CommonOptionsParser.cpp b/clang/lib/Tooling/CommonOptionsParser.cpp index edcb7df5..9ad15cc 100644 --- a/clang/lib/Tooling/CommonOptionsParser.cpp +++ b/clang/lib/Tooling/CommonOptionsParser.cpp @@ -24,9 +24,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/CommandLine.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Tooling.h" +#include "llvm/Support/CommandLine.h" using namespace clang::tooling; using namespace llvm; @@ -81,7 +81,7 @@ std::vector ArgumentsAdjustingCompilations::adjustCommands( return Commands; } -CommonOptionsParser::CommonOptionsParser( +llvm::Error CommonOptionsParser::init( int &argc, const char **argv, cl::OptionCategory &Category, llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) { static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden, @@ -105,20 +105,30 @@ CommonOptionsParser::CommonOptionsParser( cl::desc("Additional argument to prepend to the compiler command line"), cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::ResetAllOptionOccurrences(); + cl::HideUnrelatedOptions(Category); std::string ErrorMessage; Compilations = FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage); - if (!Compilations && !ErrorMessage.empty()) - llvm::errs() << ErrorMessage; - cl::ParseCommandLineOptions(argc, argv, Overview); + if (!ErrorMessage.empty()) + ErrorMessage.append("\n"); + llvm::raw_string_ostream OS(ErrorMessage); + // Stop initializing if command-line option parsing failed. + if (!cl::ParseCommandLineOptions(argc, argv, Overview, &OS)) { + OS.flush(); + return llvm::make_error("[CommonOptionsParser]: " + + ErrorMessage, + llvm::inconvertibleErrorCode()); + } + cl::PrintOptionValues(); SourcePathList = SourcePaths; if ((OccurrencesFlag == cl::ZeroOrMore || OccurrencesFlag == cl::Optional) && SourcePathList.empty()) - return; + return llvm::Error::success(); if (!Compilations) { if (!BuildPath.empty()) { Compilations = @@ -142,4 +152,27 @@ CommonOptionsParser::CommonOptionsParser( AdjustingCompilations->appendArgumentsAdjuster( getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END)); Compilations = std::move(AdjustingCompilations); + return llvm::Error::success(); +} + +llvm::Expected CommonOptionsParser::create( + int &argc, const char **argv, llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) { + CommonOptionsParser Parser; + llvm::Error Err = + Parser.init(argc, argv, Category, OccurrencesFlag, Overview); + if (Err) + return std::move(Err); + return std::move(Parser); +} + +CommonOptionsParser::CommonOptionsParser( + int &argc, const char **argv, cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) { + llvm::Error Err = init(argc, argv, Category, OccurrencesFlag, Overview); + if (Err) { + llvm::report_fatal_error( + "CommonOptionsParser: failed to parse command-line arguments. " + + llvm::toString(std::move(Err))); + } } -- 2.7.4