r303741 - Method loadFromCommandLine should be able to report errors

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Wed May 24 04:57:37 PDT 2017


Author: sepavloff
Date: Wed May 24 06:57:37 2017
New Revision: 303741

URL: http://llvm.org/viewvc/llvm-project?rev=303741&view=rev
Log:
Method loadFromCommandLine should be able to report errors

Now FixedCompilationDatabase::loadFromCommandLine has no means to report
which error occurred if it fails to create compilation object. This is
a block for implementing D33013, because after that change driver will
refuse to create compilation if command line contains erroneous options.

This change adds additional argument to loadFromCommandLine, which is
assigned error message text if compilation object was not created. This is
the same way as other methods of CompilationDatabase report failure.

Differential Revision: https://reviews.llvm.org/D33272

Modified:
    cfe/trunk/include/clang/Tooling/CompilationDatabase.h
    cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp
    cfe/trunk/lib/Tooling/CommonOptionsParser.cpp
    cfe/trunk/lib/Tooling/CompilationDatabase.cpp
    cfe/trunk/lib/Tooling/Tooling.cpp
    cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp

Modified: cfe/trunk/include/clang/Tooling/CompilationDatabase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/CompilationDatabase.h?rev=303741&r1=303740&r2=303741&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/CompilationDatabase.h (original)
+++ cfe/trunk/include/clang/Tooling/CompilationDatabase.h Wed May 24 06:57:37 2017
@@ -176,10 +176,11 @@ public:
   /// the number of arguments before "--", if "--" was found in the argument
   /// list.
   /// \param Argv Points to the command line arguments.
+  /// \param ErrorMsg Contains error text if the function returns null pointer.
   /// \param Directory The base directory used in the FixedCompilationDatabase.
-  static FixedCompilationDatabase *loadFromCommandLine(int &Argc,
-                                                       const char *const *Argv,
-                                                       Twine Directory = ".");
+  static std::unique_ptr<FixedCompilationDatabase> loadFromCommandLine(
+      int &Argc, const char *const *Argv, std::string &ErrorMsg,
+      Twine Directory = ".");
 
   /// \brief Constructs a compilation data base from a specified directory
   /// and command line.

Modified: cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp?rev=303741&r1=303740&r2=303741&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp (original)
+++ cfe/trunk/lib/Frontend/CreateInvocationFromCommandLine.cpp Wed May 24 06:57:37 2017
@@ -52,6 +52,8 @@ std::unique_ptr<CompilerInvocation> clan
   TheDriver.setCheckInputsExist(false);
 
   std::unique_ptr<driver::Compilation> C(TheDriver.BuildCompilation(Args));
+  if (!C)
+    return nullptr;
 
   // Just print the cc1 options if -### was present.
   if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {

Modified: cfe/trunk/lib/Tooling/CommonOptionsParser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CommonOptionsParser.cpp?rev=303741&r1=303740&r2=303741&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/CommonOptionsParser.cpp (original)
+++ cfe/trunk/lib/Tooling/CommonOptionsParser.cpp Wed May 24 06:57:37 2017
@@ -116,7 +116,11 @@ CommonOptionsParser::CommonOptionsParser
 
   cl::HideUnrelatedOptions(Category);
 
-  Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc, argv));
+  std::string ErrorMessage;
+  Compilations =
+      FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage);
+  if (!Compilations && !ErrorMessage.empty())
+    llvm::errs() << ErrorMessage;
   cl::ParseCommandLineOptions(argc, argv, Overview);
   cl::PrintOptionValues();
 
@@ -125,7 +129,6 @@ CommonOptionsParser::CommonOptionsParser
       SourcePathList.empty())
     return;
   if (!Compilations) {
-    std::string ErrorMessage;
     if (!BuildPath.empty()) {
       Compilations =
           CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);

Modified: cfe/trunk/lib/Tooling/CompilationDatabase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CompilationDatabase.cpp?rev=303741&r1=303740&r2=303741&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/CompilationDatabase.cpp (original)
+++ cfe/trunk/lib/Tooling/CompilationDatabase.cpp Wed May 24 06:57:37 2017
@@ -27,6 +27,7 @@
 #include "llvm/Option/Arg.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
 #include <sstream>
 #include <system_error>
 using namespace clang;
@@ -150,23 +151,21 @@ private:
 // options.
 class UnusedInputDiagConsumer : public DiagnosticConsumer {
 public:
-  UnusedInputDiagConsumer() : Other(nullptr) {}
-
-  // Useful for debugging, chain diagnostics to another consumer after
-  // recording for our own purposes.
-  UnusedInputDiagConsumer(DiagnosticConsumer *Other) : Other(Other) {}
+  UnusedInputDiagConsumer(DiagnosticConsumer &Other) : Other(Other) {}
 
   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                         const Diagnostic &Info) override {
     if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
       // Arg 1 for this diagnostic is the option that didn't get used.
       UnusedInputs.push_back(Info.getArgStdStr(0));
+    } else if (DiagLevel >= DiagnosticsEngine::Error) {
+      // If driver failed to create compilation object, show the diagnostics
+      // to user.
+      Other.HandleDiagnostic(DiagLevel, Info);
     }
-    if (Other)
-      Other->HandleDiagnostic(DiagLevel, Info);
   }
 
-  DiagnosticConsumer *Other;
+  DiagnosticConsumer &Other;
   SmallVector<std::string, 2> UnusedInputs;
 };
 
@@ -205,9 +204,12 @@ private:
 ///          \li false if \c Args cannot be used for compilation jobs (e.g.
 ///          contains an option like -E or -version).
 static bool stripPositionalArgs(std::vector<const char *> Args,
-                                std::vector<std::string> &Result) {
+                                std::vector<std::string> &Result,
+                                std::string &ErrorMsg) {
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
-  UnusedInputDiagConsumer DiagClient;
+  llvm::raw_string_ostream Output(ErrorMsg);
+  TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts);
+  UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
   DiagnosticsEngine Diagnostics(
       IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
       &*DiagOpts, &DiagClient, false);
@@ -245,6 +247,8 @@ static bool stripPositionalArgs(std::vec
 
   const std::unique_ptr<driver::Compilation> Compilation(
       NewDriver->BuildCompilation(Args));
+  if (!Compilation)
+    return false;
 
   const driver::JobList &Jobs = Compilation->getJobs();
 
@@ -258,8 +262,7 @@ static bool stripPositionalArgs(std::vec
   }
 
   if (CompileAnalyzer.Inputs.empty()) {
-    // No compile jobs found.
-    // FIXME: Emit a warning of some kind?
+    ErrorMsg = "warning: no compile jobs found\n";
     return false;
   }
 
@@ -280,8 +283,14 @@ static bool stripPositionalArgs(std::vec
   return true;
 }
 
-FixedCompilationDatabase *FixedCompilationDatabase::loadFromCommandLine(
-    int &Argc, const char *const *Argv, Twine Directory) {
+std::unique_ptr<FixedCompilationDatabase>
+FixedCompilationDatabase::loadFromCommandLine(int &Argc,
+                                              const char *const *Argv,
+                                              std::string &ErrorMsg,
+                                              Twine Directory) {
+  ErrorMsg.clear();
+  if (Argc == 0)
+    return nullptr;
   const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
   if (DoubleDash == Argv + Argc)
     return nullptr;
@@ -289,9 +298,10 @@ FixedCompilationDatabase *FixedCompilati
   Argc = DoubleDash - Argv;
 
   std::vector<std::string> StrippedArgs;
-  if (!stripPositionalArgs(CommandLine, StrippedArgs))
+  if (!stripPositionalArgs(CommandLine, StrippedArgs, ErrorMsg))
     return nullptr;
-  return new FixedCompilationDatabase(Directory, StrippedArgs);
+  return std::unique_ptr<FixedCompilationDatabase>(
+      new FixedCompilationDatabase(Directory, StrippedArgs));
 }
 
 FixedCompilationDatabase::

Modified: cfe/trunk/lib/Tooling/Tooling.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=303741&r1=303740&r2=303741&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Tooling.cpp (original)
+++ cfe/trunk/lib/Tooling/Tooling.cpp Wed May 24 06:57:37 2017
@@ -260,6 +260,8 @@ bool ToolInvocation::run() {
   Driver->setCheckInputsExist(false);
   const std::unique_ptr<clang::driver::Compilation> Compilation(
       Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
+  if (!Compilation)
+    return false;
   const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
       &Diagnostics, Compilation.get());
   if (!CC1Args) {

Modified: cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp?rev=303741&r1=303740&r2=303741&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp Wed May 24 06:57:37 2017
@@ -504,18 +504,22 @@ TEST(FixedCompilationDatabase, GetAllCom
 
 TEST(ParseFixedCompilationDatabase, ReturnsNullOnEmptyArgumentList) {
   int Argc = 0;
-  std::unique_ptr<FixedCompilationDatabase> Database(
-      FixedCompilationDatabase::loadFromCommandLine(Argc, nullptr));
+  std::string ErrorMsg;
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, nullptr, ErrorMsg);
   EXPECT_FALSE(Database);
+  EXPECT_TRUE(ErrorMsg.empty());
   EXPECT_EQ(0, Argc);
 }
 
 TEST(ParseFixedCompilationDatabase, ReturnsNullWithoutDoubleDash) {
   int Argc = 2;
   const char *Argv[] = { "1", "2" };
+  std::string ErrorMsg;
   std::unique_ptr<FixedCompilationDatabase> Database(
-      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg));
   EXPECT_FALSE(Database);
+  EXPECT_TRUE(ErrorMsg.empty());
   EXPECT_EQ(2, Argc);
 }
 
@@ -524,9 +528,11 @@ TEST(ParseFixedCompilationDatabase, Retu
   const char *Argv[] = {
     "1", "2", "--\0no-constant-folding", "-DDEF3", "-DDEF4"
   };
+  std::string ErrorMsg;
   std::unique_ptr<FixedCompilationDatabase> Database(
-      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg));
   ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
   std::vector<CompileCommand> Result =
     Database->getCompileCommands("source");
   ASSERT_EQ(1ul, Result.size());
@@ -543,9 +549,11 @@ TEST(ParseFixedCompilationDatabase, Retu
 TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) {
   int Argc = 3;
   const char *Argv[] = { "1", "2", "--\0no-constant-folding" };
-  std::unique_ptr<FixedCompilationDatabase> Database(
-      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+  std::string ErrorMsg;
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
   ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
   std::vector<CompileCommand> Result =
     Database->getCompileCommands("source");
   ASSERT_EQ(1ul, Result.size());
@@ -560,9 +568,11 @@ TEST(ParseFixedCompilationDatabase, Retu
 TEST(ParseFixedCompilationDatabase, HandlesPositionalArgs) {
   const char *Argv[] = {"1", "2", "--", "-c", "somefile.cpp", "-DDEF3"};
   int Argc = sizeof(Argv) / sizeof(char*);
-  std::unique_ptr<FixedCompilationDatabase> Database(
-      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+  std::string ErrorMsg;
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
   ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
   std::vector<CompileCommand> Result =
     Database->getCompileCommands("source");
   ASSERT_EQ(1ul, Result.size());
@@ -579,9 +589,11 @@ TEST(ParseFixedCompilationDatabase, Hand
 TEST(ParseFixedCompilationDatabase, HandlesArgv0) {
   const char *Argv[] = {"1", "2", "--", "mytool", "somefile.cpp"};
   int Argc = sizeof(Argv) / sizeof(char*);
-  std::unique_ptr<FixedCompilationDatabase> Database(
-      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+  std::string ErrorMsg;
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
   ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
   std::vector<CompileCommand> Result =
     Database->getCompileCommands("source");
   ASSERT_EQ(1ul, Result.size());




More information about the cfe-commits mailing list