Index: include/clang/Tooling/CompilationDatabase.h =================================================================== --- include/clang/Tooling/CompilationDatabase.h +++ include/clang/Tooling/CompilationDatabase.h @@ -186,11 +186,20 @@ /// 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, + std::string &ErrorMsg, Twine Directory = "."); + static FixedCompilationDatabase *loadFromCommandLine(int &Argc, + const char *const *Argv, + Twine Directory = ".") { + std::string ErrorMsg; + return loadFromCommandLine(Argc, Argv, ErrorMsg, Directory); + } + /// \brief Constructs a compilation data base from a specified directory /// and command line. FixedCompilationDatabase(Twine Directory, ArrayRef CommandLine); Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -598,6 +598,8 @@ bool CCCPrintPhases; InputArgList Args = ParseArgStrings(ArgList.slice(1)); + if (Diags.hasErrorOccurred()) + return nullptr; // Silence driver warnings if requested Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w)); Index: lib/Frontend/CreateInvocationFromCommandLine.cpp =================================================================== --- lib/Frontend/CreateInvocationFromCommandLine.cpp +++ lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -52,6 +52,8 @@ TheDriver.setCheckInputsExist(false); std::unique_ptr 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)) { Index: lib/Tooling/CommonOptionsParser.cpp =================================================================== --- lib/Tooling/CommonOptionsParser.cpp +++ lib/Tooling/CommonOptionsParser.cpp @@ -116,7 +116,12 @@ cl::HideUnrelatedOptions(Category); - Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc, argv)); + std::string ErrorMessage; + Compilations.reset( + FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage)); + if (!Compilations) { + llvm::errs() << ErrorMessage; + } cl::ParseCommandLineOptions(argc, argv, Overview); cl::PrintOptionValues(); @@ -125,7 +130,6 @@ SourcePathList.empty()) return; if (!Compilations) { - std::string ErrorMessage; if (!BuildPath.empty()) { Compilations = CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage); Index: lib/Tooling/CompilationDatabase.cpp =================================================================== --- lib/Tooling/CompilationDatabase.cpp +++ lib/Tooling/CompilationDatabase.cpp @@ -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 #include using namespace clang; @@ -150,23 +151,21 @@ // 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)); - } - if (Other) - Other->HandleDiagnostic(DiagLevel, Info); + + // If driver failed to create compilation object, show the diagnostics + // to user. + } else if (DiagLevel >= DiagnosticsEngine::Error) + Other.HandleDiagnostic(DiagLevel, Info); } - DiagnosticConsumer *Other; + DiagnosticConsumer &Other; SmallVector UnusedInputs; }; @@ -205,9 +204,12 @@ /// \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 Args, - std::vector &Result) { + std::vector &Result, + std::string &ErrorMsg) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - UnusedInputDiagConsumer DiagClient; + llvm::raw_string_ostream Output(ErrorMsg); + TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts); + UnusedInputDiagConsumer DiagClient(DiagnosticPrinter); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr(new DiagnosticIDs()), &*DiagOpts, &DiagClient, false); @@ -245,6 +247,8 @@ const std::unique_ptr Compilation( NewDriver->BuildCompilation(Args)); + if (!Compilation) + return false; const driver::JobList &Jobs = Compilation->getJobs(); @@ -258,8 +262,7 @@ } if (CompileAnalyzer.Inputs.empty()) { - // No compile jobs found. - // FIXME: Emit a warning of some kind? + ErrorMsg = "error: no compile jobs found\n"; return false; } @@ -281,15 +284,22 @@ } FixedCompilationDatabase *FixedCompilationDatabase::loadFromCommandLine( - int &Argc, const char *const *Argv, Twine Directory) { + int &Argc, const char *const *Argv, std::string &ErrorMsg, + Twine Directory) { + if (Argc == 0) { + ErrorMsg = "error: no arguments specified\n"; + return nullptr; + } const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); - if (DoubleDash == Argv + Argc) + if (DoubleDash == Argv + Argc) { + ErrorMsg = "error: double dash not found\n"; return nullptr; + } std::vector CommandLine(DoubleDash + 1, Argv + Argc); Argc = DoubleDash - Argv; std::vector StrippedArgs; - if (!stripPositionalArgs(CommandLine, StrippedArgs)) + if (!stripPositionalArgs(CommandLine, StrippedArgs, ErrorMsg)) return nullptr; return new FixedCompilationDatabase(Directory, StrippedArgs); } Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -260,6 +260,8 @@ Driver->setCheckInputsExist(false); const std::unique_ptr Compilation( Driver->BuildCompilation(llvm::makeArrayRef(Argv))); + if (!Compilation) + return false; const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments( &Diagnostics, Compilation.get()); if (!CC1Args) { Index: test/Driver/aarch64-cpus.c =================================================================== --- test/Driver/aarch64-cpus.c +++ test/Driver/aarch64-cpus.c @@ -11,7 +11,7 @@ // RUN: %clang -target arm64 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s // RUN: %clang -target arm64 -mcpu=generic -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s // RUN: %clang -target arm64 -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s -// RUN: %clang -target arm64 -mlittle-endian -mcpu-generic -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s +// RUN: %clang -target arm64 -mlittle-endian -mcpu=generic -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-GENERIC %s // ARM64-GENERIC: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic" Index: test/Driver/amdgpu-features.c =================================================================== --- test/Driver/amdgpu-features.c +++ test/Driver/amdgpu-features.c @@ -1,7 +1,7 @@ -// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri -mamdgpu-debugger-abi=0.0 %s -o 2>&1 \ +// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri -mamdgpu-debugger-abi=0.0 %s -o - 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MAMDGPU-DEBUGGER-ABI-0-0 %s // CHECK-MAMDGPU-DEBUGGER-ABI-0-0: the clang compiler does not support '-mamdgpu-debugger-abi=0.0' -// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri -mamdgpu-debugger-abi=1.0 %s -o 2>&1 \ +// RUN: %clang -### -target amdgcn -x cl -S -emit-llvm -mcpu=kaveri -mamdgpu-debugger-abi=1.0 %s -o - 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MAMDGPU-DEBUGGER-ABI-1-0 %s // CHECK-MAMDGPU-DEBUGGER-ABI-1-0: "-target-feature" "+amdgpu-debugger-insert-nops" "-target-feature" "+amdgpu-debugger-reserve-regs" "-target-feature" "+amdgpu-debugger-emit-prologue" Index: test/Driver/arm-darwin-builtin.c =================================================================== --- test/Driver/arm-darwin-builtin.c +++ /dev/null @@ -1,14 +0,0 @@ -// FIXME: Disable pending PR4941. -// RUX: clang -target x86_64-apple-darwin9 -arch arm -### -fsyntax-only %s 2> %t && -// RUX: grep -- "-fno-builtin-strcat" %t && -// RUX: grep -- "-fno-builtin-strcpy" %t && - -// FIXME: Disable pending PR4941. -// RUX: clang -target x86_64-apple-darwin9 -arch arm -### -fsyntax-only %s -fbuiltin-strcat -fbuiltin-strcpy 2> %t && -// RUX: not grep -- "-fno-builtin-strcat" %t && -// RUX: not grep -- "-fno-builtin-strcpy" %t && - -// RUN: %clang -target x86_64-apple-darwin9 -arch arm -### -fsyntax-only %s -fbuiltin-strcat -fbuiltin-strcpy 2> %t -// RUN: not grep -- "-fno-builtin-strcat" %t -// RUN: not grep -- "-fno-builtin-strcpy" %t - Index: test/Driver/arm-default-build-attributes.s =================================================================== --- test/Driver/arm-default-build-attributes.s +++ test/Driver/arm-default-build-attributes.s @@ -10,9 +10,9 @@ // Option ignored C/C++ (since we always emit hardware and ABI build attributes // during codegen). -// RUN: %clang -target armv7--none-eabi -### -x c %s -mdefault-build-attributes -verify 2>&1 \ +// RUN: %clang -target armv7--none-eabi -### -x c %s -mdefault-build-attributes 2>&1 \ // RUN: | FileCheck %s -check-prefix CHECK-DISABLED -// RUN: %clang -target armv7--none-eabi -### -x c++ %s -mdefault-build-attributes -verify 2>&1 \ +// RUN: %clang -target armv7--none-eabi -### -x c++ %s -mdefault-build-attributes 2>&1 \ // RUN: | FileCheck %s -check-prefix CHECK-DISABLED // CHECK-DISABLED-NOT: "-arm-add-build-attributes" Index: test/Driver/cl-outputs.c =================================================================== --- test/Driver/cl-outputs.c +++ test/Driver/cl-outputs.c @@ -73,7 +73,7 @@ // RUN: %clang_cl /c /o .. -### -- %s 2>&1 | FileCheck -check-prefix=oCRAZY2 %s // oCRAZY2: "-o" "..obj" -// RUN: %clang_cl /c %s -### /o 2>&1 | FileCheck -check-prefix=oMISSINGARG %s +// RUN: not %clang_cl /c %s -### /o 2>&1 | FileCheck -check-prefix=oMISSINGARG %s // oMISSINGARG: error: argument to '/o' is missing (expected 1 value) // RUN: %clang_cl /c /omydir/ -### -- %s %s 2>&1 | FileCheck -check-prefix=CHECK-oMULTIPLESOURCEOK1 %s @@ -208,7 +208,7 @@ // FeoDIRNAMEEXTDLL: "-out:foo.dir{{[/\\]+}}a.ext" // FeoDIRNAMEEXTDLL: "-implib:foo.dir{{[/\\]+}}a.lib" -// RUN: %clang_cl -### /o 2>&1 | FileCheck -check-prefix=FeoMISSINGARG %s +// RUN: not %clang_cl -### /o 2>&1 | FileCheck -check-prefix=FeoMISSINGARG %s // FeoMISSINGARG: error: argument to '/o' is missing (expected 1 value) // RUN: %clang_cl /ofoo /o bar -### -- %s 2>&1 | FileCheck -check-prefix=FeoOVERRIDE %s Index: test/Driver/clang_f_opts.c =================================================================== --- test/Driver/clang_f_opts.c +++ test/Driver/clang_f_opts.c @@ -186,7 +186,7 @@ // CHECK-NO-SLP-VECTORIZE-AGG-NOT: "-vectorize-slp-aggressive" // RUN: %clang -### -S -fextended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-EXTENDED-IDENTIFIERS %s -// RUN: %clang -### -S -fno-extended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-NO-EXTENDED-IDENTIFIERS %s +// RUN: not %clang -### -S -fno-extended-identifiers %s 2>&1 | FileCheck -check-prefix=CHECK-NO-EXTENDED-IDENTIFIERS %s // CHECK-EXTENDED-IDENTIFIERS: "-cc1" // CHECK-EXTENDED-IDENTIFIERS-NOT: "-fextended-identifiers" // CHECK-NO-EXTENDED-IDENTIFIERS: error: unsupported option '-fno-extended-identifiers' Index: test/Driver/cuda-external-tools.cu =================================================================== --- test/Driver/cuda-external-tools.cu +++ test/Driver/cuda-external-tools.cu @@ -24,8 +24,8 @@ // RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix DBG %s // --no-cuda-noopt-device-debug overrides --cuda-noopt-device-debug. -// RUN: %clang -### -target x86_64-linux-gnu --cuda-noopt-debug \ -// RUN: --no-cuda-noopt-debug -O2 -c %s 2>&1 \ +// RUN: %clang -### -target x86_64-linux-gnu --cuda-noopt-device-debug \ +// RUN: --no-cuda-noopt-device-debug -O2 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix ARCH64 -check-prefix SM20 -check-prefix OPT2 %s // Regular compile without -O. This should result in us passing -O0 to ptxas. Index: test/Driver/debug-options.c =================================================================== --- test/Driver/debug-options.c +++ test/Driver/debug-options.c @@ -80,7 +80,7 @@ // RUN: %clang -### -c -gdwarf-2 %s 2>&1 \ // RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s // -// RUN: %clang -### -c -gfoo %s 2>&1 | FileCheck -check-prefix=G_NO %s +// RUN: not %clang -### -c -gfoo %s 2>&1 | FileCheck -check-prefix=G_ERR %s // RUN: %clang -### -c -g -g0 %s 2>&1 | FileCheck -check-prefix=G_NO %s // RUN: %clang -### -c -ggdb0 %s 2>&1 | FileCheck -check-prefix=G_NO %s // RUN: %clang -### -c -glldb -g0 %s 2>&1 | FileCheck -check-prefix=G_NO %s @@ -171,6 +171,8 @@ // G_PS4: "-dwarf-version= // G_PS4: "-generate-arange-section" // +// G_ERR: error: unknown argument: +// // G_NO: "-cc1" // G_NO-NOT: -debug-info-kind= // Index: test/Driver/gfortran.f90 =================================================================== --- test/Driver/gfortran.f90 +++ test/Driver/gfortran.f90 @@ -106,7 +106,6 @@ ! RUN: -fsyntax-only \ ! RUN: -funderscoring \ ! RUN: -fwhole-file \ -! RUN: -fworking-directory \ ! RUN: -imultilib \ ! RUN: -iprefix \ ! RUN: -iquote \ @@ -226,7 +225,6 @@ ! CHECK: "-fstack-arrays" ! CHECK: "-funderscoring" ! CHECK: "-fwhole-file" -! CHECK: "-fworking-directory" ! CHECK: "-imultilib" ! CHECK: "-iprefix" ! CHECK: "-iquote" Index: test/Driver/split-debug.h =================================================================== --- test/Driver/split-debug.h +++ test/Driver/split-debug.h @@ -3,13 +3,4 @@ // RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -fmodules -### %s 2> %t // RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s // -// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -fmodules -emit-module -fmodules-embed-all-files -fno-implicit-modules -fno-implicit-module-maps -### %s 2> %t -// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s -// -// FIXME: This should fail using clang, except that the type of the output for -// an object output with modules is given as clang::driver::types::TY_PCH -// rather than TY_Object. -// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -fmodules -fmodule-format=obj -### %s 2> %t -// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s -// // CHECK-NO-ACTIONS-NOT: objcopy Index: test/Driver/unknown-arg.c =================================================================== --- test/Driver/unknown-arg.c +++ test/Driver/unknown-arg.c @@ -1,8 +1,8 @@ -// RUN: %clang %s -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### 2>&1 | \ +// RUN: not %clang %s -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### 2>&1 | \ // RUN: FileCheck %s // RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### -c -- %s 2>&1 | \ // RUN: FileCheck %s --check-prefix=CL -// RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Werror=unknown-argument -### -- %s 2>&1 | \ +// RUN: not %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Werror=unknown-argument -### -- %s 2>&1 | \ // RUN: FileCheck %s --check-prefix=CL-ERROR // RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Wno-unknown-argument -### -- %s 2>&1 | \ // RUN: FileCheck %s --check-prefix=SILENT Index: test/Index/index-attrs.c =================================================================== --- test/Index/index-attrs.c +++ test/Index/index-attrs.c @@ -1,16 +1,16 @@ -// RUN: c-index-test -index-file -check-prefix CHECK %s -target armv7-windows-gnu -fdeclspec +// RUN: c-index-test -index-file %s -target armv7-windows-gnu -fdeclspec 2>&1 | FileCheck %s void __declspec(dllexport) export_function(void) {} -// CHECK: [indexDeclaraton]: kind: function | name: export_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: export_function | {{.*}} | lang: C // CHECK: : attribute(dllexport) void __attribute__((dllexport)) export_gnu_attribute(void) {} -// CHECK: [indexDeclaration] kind: function | name: export_gnu_attribute | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: export_gnu_attribute | {{.*}} | lang: C // CHECK: : attribute(dllexport) void __declspec(dllimport) import_function(void); -// CHECK: [indexDeclaration] kind: function | name: import_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: import_function | {{.*}} | lang: C // CHECK: : attribute(dllimport) void __attribute__((dllimport)) import_gnu_attribute(void); -// CHECK: [indexDeclaration] kind: function | name: import_gnu_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: import_gnu_attribute | {{.*}} | lang: C // CHECK: : attribute(dllimport) Index: test/Index/index-attrs.cpp =================================================================== --- test/Index/index-attrs.cpp +++ test/Index/index-attrs.cpp @@ -1,4 +1,4 @@ -// RUN: c-index-test -index-file -check-prefix CHECK %s -target armv7-windows-gnu -fdeclspec +// RUN: c-index-test -index-file %s -target armv7-windows-gnu -fdeclspec | FileCheck %s struct __declspec(dllexport) export_s { void m(); @@ -19,7 +19,7 @@ class __attribute__((dllexport)) export_gnu_s { void m(); }; -// CHECK: [indexDeclaration]: kind: struct | name: export_gnu_s | {{.*}} | lang: C++ +// CHECK: [indexDeclaration]: kind: c++-class | name: export_gnu_s | {{.*}} | lang: C++ // CHECK: : attribute(dllexport) // CHECK: [indexDeclaration]: kind: c++-instance-method | name: m | {{.*}} | lang: C++ // CHECK: : attribute(dllexport) @@ -27,24 +27,24 @@ class __attribute__((dllimport)) import_gnu_s { void m(); }; -// CHECK: [indexDeclaration]: kind: struct | name: import_gnu_s | {{.*}} | lang: C++ +// CHECK: [indexDeclaration]: kind: c++-class | name: import_gnu_s | {{.*}} | lang: C++ // CHECK: : attribute(dllimport) // CHECK: [indexDeclaration]: kind: c++-instance-method | name: m | {{.*}} | lang: C++ // CHECK: : attribute(dllimport) extern "C" void __declspec(dllexport) export_function(void) {} -// CHECK: [indexDeclaraton]: kind: function | name: export_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: export_function | {{.*}} | lang: C // CHECK: : attribute(dllexport) extern "C" void __attribute__((dllexport)) export_gnu_function(void) {} -// CHECK: [indexDeclaraton]: kind: function | name: export_gnu_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: export_gnu_function | {{.*}} | lang: C // CHECK: : attribute(dllexport) extern "C" { void __declspec(dllimport) import_function(void); -// CHECK: [indexDeclaration] kind: function | name: import_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: import_function | {{.*}} | lang: C // CHECK: : attribute(dllimport) void __attribute__((dllimport)) import_gnu_function(void); -// CHECK: [indexDeclaration] kind: function | name: import_gnu_function | {{.*}} | lang: C +// CHECK: [indexDeclaration]: kind: function | name: import_gnu_function | {{.*}} | lang: C // CHECK: : attribute(dllimport) } Index: tools/driver/driver.cpp =================================================================== --- tools/driver/driver.cpp +++ tools/driver/driver.cpp @@ -454,40 +454,41 @@ SetBackdoorDriverOutputsFromEnvVars(TheDriver); std::unique_ptr C(TheDriver.BuildCompilation(argv)); - int Res = 0; - SmallVector, 4> FailingCommands; - if (C.get()) + int Res = 1; + if (C.get()) { + SmallVector, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); - // Force a crash to test the diagnostics. - if (TheDriver.GenReproducer) { - Diags.Report(diag::err_drv_force_crash) + // Force a crash to test the diagnostics. + if (TheDriver.GenReproducer) { + Diags.Report(diag::err_drv_force_crash) << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"); - // Pretend that every command failed. - FailingCommands.clear(); - for (const auto &J : C->getJobs()) - if (const Command *C = dyn_cast(&J)) - FailingCommands.push_back(std::make_pair(-1, C)); - } + // Pretend that every command failed. + FailingCommands.clear(); + for (const auto &J : C->getJobs()) + if (const Command *C = dyn_cast(&J)) + FailingCommands.push_back(std::make_pair(-1, C)); + } - for (const auto &P : FailingCommands) { - int CommandRes = P.first; - const Command *FailingCommand = P.second; - if (!Res) - Res = CommandRes; - - // If result status is < 0, then the driver command signalled an error. - // If result status is 70, then the driver command reported a fatal error. - // On Windows, abort will return an exit code of 3. In these cases, - // generate additional diagnostic information if possible. - bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70; + for (const auto &P : FailingCommands) { + int CommandRes = P.first; + const Command *FailingCommand = P.second; + if (!Res) + Res = CommandRes; + + // If result status is < 0, then the driver command signalled an error. + // If result status is 70, then the driver command reported a fatal error. + // On Windows, abort will return an exit code of 3. In these cases, + // generate additional diagnostic information if possible. + bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70; #ifdef LLVM_ON_WIN32 - DiagnoseCrash |= CommandRes == 3; + DiagnoseCrash |= CommandRes == 3; #endif - if (DiagnoseCrash) { - TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); - break; + if (DiagnoseCrash) { + TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); + break; + } } } Index: unittests/Driver/ToolChainTest.cpp =================================================================== --- unittests/Driver/ToolChainTest.cpp +++ unittests/Driver/ToolChainTest.cpp @@ -60,6 +60,7 @@ std::unique_ptr C(TheDriver.BuildCompilation( {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"})); + EXPECT_TRUE(C); std::string S; { @@ -99,6 +100,7 @@ std::unique_ptr C(TheDriver.BuildCompilation( {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"})); + EXPECT_TRUE(C); std::string S; { @@ -128,15 +130,24 @@ Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, InMemoryFileSystem); + CCDriver.setCheckInputsExist(false); Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags, InMemoryFileSystem); + CXXDriver.setCheckInputsExist(false); Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags, InMemoryFileSystem); - - std::unique_ptr CC(CCDriver.BuildCompilation({"foo.cpp"})); - std::unique_ptr CXX(CXXDriver.BuildCompilation({"foo.cpp"})); - std::unique_ptr CL(CLDriver.BuildCompilation({"foo.cpp"})); - + CLDriver.setCheckInputsExist(false); + + std::unique_ptr CC(CCDriver.BuildCompilation( + { "/home/test/bin/clang", "foo.cpp"})); + std::unique_ptr CXX(CXXDriver.BuildCompilation( + { "/home/test/bin/clang++", "foo.cpp"})); + std::unique_ptr CL(CLDriver.BuildCompilation( + { "/home/test/bin/clang-cl", "foo.cpp"})); + + EXPECT_TRUE(CC); + EXPECT_TRUE(CXX); + EXPECT_TRUE(CL); EXPECT_TRUE(CCDriver.CCCIsCC()); EXPECT_TRUE(CXXDriver.CCCIsCXX()); EXPECT_TRUE(CLDriver.IsCLMode()); Index: unittests/Tooling/CompilationDatabaseTest.cpp =================================================================== --- unittests/Tooling/CompilationDatabaseTest.cpp +++ unittests/Tooling/CompilationDatabaseTest.cpp @@ -504,18 +504,22 @@ TEST(ParseFixedCompilationDatabase, ReturnsNullOnEmptyArgumentList) { int Argc = 0; + std::string ErrorMsg; std::unique_ptr Database( - FixedCompilationDatabase::loadFromCommandLine(Argc, nullptr)); + FixedCompilationDatabase::loadFromCommandLine(Argc, nullptr, ErrorMsg)); EXPECT_FALSE(Database); + EXPECT_EQ(ErrorMsg, "error: no arguments specified\n"); EXPECT_EQ(0, Argc); } TEST(ParseFixedCompilationDatabase, ReturnsNullWithoutDoubleDash) { int Argc = 2; const char *Argv[] = { "1", "2" }; + std::string ErrorMsg; std::unique_ptr Database( - FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); + FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg)); EXPECT_FALSE(Database); + EXPECT_EQ(ErrorMsg, "error: double dash not found\n"); EXPECT_EQ(2, Argc); } @@ -524,9 +528,11 @@ const char *Argv[] = { "1", "2", "--\0no-constant-folding", "-DDEF3", "-DDEF4" }; + std::string ErrorMsg; std::unique_ptr Database( - FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); + FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg)); ASSERT_TRUE((bool)Database); + ASSERT_TRUE(ErrorMsg.empty()); std::vector Result = Database->getCompileCommands("source"); ASSERT_EQ(1ul, Result.size()); @@ -543,9 +549,11 @@ TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) { int Argc = 3; const char *Argv[] = { "1", "2", "--\0no-constant-folding" }; + std::string ErrorMsg; std::unique_ptr Database( FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); ASSERT_TRUE((bool)Database); + ASSERT_TRUE(ErrorMsg.empty()); std::vector Result = Database->getCompileCommands("source"); ASSERT_EQ(1ul, Result.size()); @@ -560,9 +568,11 @@ TEST(ParseFixedCompilationDatabase, HandlesPositionalArgs) { const char *Argv[] = {"1", "2", "--", "-c", "somefile.cpp", "-DDEF3"}; int Argc = sizeof(Argv) / sizeof(char*); + std::string ErrorMsg; std::unique_ptr Database( FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); ASSERT_TRUE((bool)Database); + ASSERT_TRUE(ErrorMsg.empty()); std::vector Result = Database->getCompileCommands("source"); ASSERT_EQ(1ul, Result.size()); @@ -579,9 +589,11 @@ TEST(ParseFixedCompilationDatabase, HandlesArgv0) { const char *Argv[] = {"1", "2", "--", "mytool", "somefile.cpp"}; int Argc = sizeof(Argv) / sizeof(char*); + std::string ErrorMsg; std::unique_ptr Database( FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); ASSERT_TRUE((bool)Database); + ASSERT_TRUE(ErrorMsg.empty()); std::vector Result = Database->getCompileCommands("source"); ASSERT_EQ(1ul, Result.size());