ioeric created this revision.

This returns error instead of exiting the program in case of error.


https://reviews.llvm.org/D39042

Files:
  include/clang/Tooling/CommonOptionsParser.h
  lib/Tooling/CommonOptionsParser.cpp

Index: lib/Tooling/CommonOptionsParser.cpp
===================================================================
--- lib/Tooling/CommonOptionsParser.cpp
+++ 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,9 +81,11 @@
   return Commands;
 }
 
-CommonOptionsParser::CommonOptionsParser(
-    int &argc, const char **argv, cl::OptionCategory &Category,
-    llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
+llvm::Error
+CommonOptionsParser::init(int &argc, const char **argv,
+                          cl::OptionCategory &Category,
+                          llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+                          const char *Overview, CommonOptionsParser *Parser) {
   static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden,
                             cl::sub(*cl::AllSubCommands));
 
@@ -105,41 +107,76 @@
       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 =
+  Parser->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<llvm::StringError>("[CommonOptionsParser]: " +
+                                                   ErrorMessage,
+                                               llvm::inconvertibleErrorCode());
+  }
+
   cl::PrintOptionValues();
 
-  SourcePathList = SourcePaths;
+  Parser->SourcePathList = SourcePaths;
   if ((OccurrencesFlag == cl::ZeroOrMore || OccurrencesFlag == cl::Optional) &&
-      SourcePathList.empty())
-    return;
-  if (!Compilations) {
+      Parser->SourcePathList.empty())
+    return llvm::Error::success();
+  if (!Parser->Compilations) {
     if (!BuildPath.empty()) {
-      Compilations =
+      Parser->Compilations =
           CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);
     } else {
-      Compilations = CompilationDatabase::autoDetectFromSource(SourcePaths[0],
-                                                               ErrorMessage);
+      Parser->Compilations = CompilationDatabase::autoDetectFromSource(
+          SourcePaths[0], ErrorMessage);
     }
-    if (!Compilations) {
+    if (!Parser->Compilations) {
       llvm::errs() << "Error while trying to load a compilation database:\n"
                    << ErrorMessage << "Running without flags.\n";
-      Compilations.reset(
+      Parser->Compilations.reset(
           new FixedCompilationDatabase(".", std::vector<std::string>()));
     }
   }
   auto AdjustingCompilations =
       llvm::make_unique<ArgumentsAdjustingCompilations>(
-          std::move(Compilations));
+          std::move(Parser->Compilations));
   AdjustingCompilations->appendArgumentsAdjuster(
       getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN));
   AdjustingCompilations->appendArgumentsAdjuster(
       getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END));
-  Compilations = std::move(AdjustingCompilations);
+  Parser->Compilations = std::move(AdjustingCompilations);
+  return llvm::Error::success();
+}
+
+llvm::Expected<std::unique_ptr<CommonOptionsParser>>
+CommonOptionsParser::create(int &argc, const char **argv,
+                            llvm::cl::OptionCategory &Category,
+                            llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+                            const char *Overview) {
+  std::unique_ptr<CommonOptionsParser> Parser(new CommonOptionsParser);
+  llvm::Error Err =
+      init(argc, argv, Category, OccurrencesFlag, Overview, Parser.get());
+  if (Err)
+    return std::move(Err);
+  return 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, this);
+  if (Err) {
+    llvm::report_fatal_error(
+        "CommonOptionsParser: failed to parse command-line arguments. " +
+        llvm::toString(std::move(Err)));
+  }
 }
Index: include/clang/Tooling/CommonOptionsParser.h
===================================================================
--- include/clang/Tooling/CommonOptionsParser.h
+++ 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,16 @@
   /// 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);
 
+  static llvm::Expected<std::unique_ptr<CommonOptionsParser>>
+  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 +110,13 @@
   static const char *const HelpMessage;
 
 private:
+  CommonOptionsParser() = default;
+
+  static llvm::Error init(int &argc, const char **argv,
+                          llvm::cl::OptionCategory &Category,
+                          llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+                          const char *Overview, CommonOptionsParser *Parser);
+
   std::unique_ptr<CompilationDatabase> Compilations;
   std::vector<std::string> SourcePathList;
 };
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to