diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e131e4f127803..881dcb78b6638 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -46,6 +46,11 @@ sections with improvements to Clang's support for those languages. Major New Features ------------------ +- clang used to run the actual compilation in a subprocess ("clang -cc1"). + Now compilations are done in-process by default. ``-fno-integrated-cc1`` + restores the former behavior. The ``-v`` and ``-###`` flags will print + "(in-process)" when compilations are done in-process. + - ... Improvements to Clang's diagnostics diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1218172fd5b69..abfa767afea8f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2855,6 +2855,14 @@ def fintegrated_as : Flag<["-"], "fintegrated-as">, Flags<[DriverOption]>, def fno_integrated_as : Flag<["-"], "fno-integrated-as">, Flags<[CC1Option, DriverOption]>, Group, HelpText<"Disable the integrated assembler">; + +def fintegrated_cc1 : Flag<["-"], "fintegrated-cc1">, + Flags<[CoreOption, DriverOption]>, Group, + HelpText<"Run cc1 in-process">; +def fno_integrated_cc1 : Flag<["-"], "fno-integrated-cc1">, + Flags<[CoreOption, DriverOption]>, Group, + HelpText<"Spawn a separate process for each cc1">; + def : Flag<["-"], "integrated-as">, Alias, Flags<[DriverOption]>; def : Flag<["-"], "no-integrated-as">, Alias, Flags<[CC1Option, DriverOption]>; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e718b8366df0e..7ee3caaa0bce0 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1035,6 +1035,10 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { // -no-canonical-prefixes is used very early in main. Args.ClaimAllArgs(options::OPT_no_canonical_prefixes); + // f(no-)integated-cc1 is also used very early in main. + Args.ClaimAllArgs(options::OPT_fintegrated_cc1); + Args.ClaimAllArgs(options::OPT_fno_integrated_cc1); + // Ignore -pipe. Args.ClaimAllArgs(options::OPT_pipe); diff --git a/clang/test/Driver/cc1-spawnprocess.c b/clang/test/Driver/cc1-spawnprocess.c index c5c16ce8513fc..624593895961e 100644 --- a/clang/test/Driver/cc1-spawnprocess.c +++ b/clang/test/Driver/cc1-spawnprocess.c @@ -1,4 +1,22 @@ -// RUN: env CLANG_SPAWN_CC1= %clang -S %s -o /dev/null -// RUN: env CLANG_SPAWN_CC1=0 %clang -S %s -o /dev/null -// RUN: env CLANG_SPAWN_CC1=1 %clang -S %s -o /dev/null -// RUN: env CLANG_SPAWN_CC1=test not %clang -S %s -o /dev/null +// RUN: %clang -fintegrated-cc1 -### %s 2>&1 | FileCheck %s --check-prefix=YES +// RUN: %clang -fno-integrated-cc1 -### %s 2>&1 | FileCheck %s --check-prefix=NO + +// RUN: %clang -fintegrated-cc1 -fno-integrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NO +// RUN: %clang -fno-integrated-cc1 -fintegrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=YES + +// RUN: %clang_cl -fintegrated-cc1 -### -- %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=YES +// RUN: %clang_cl -fno-integrated-cc1 -### -- %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NO + +// RUN: env CCC_OVERRIDE_OPTIONS=+-fintegrated-cc1 \ +// RUN: %clang -fintegrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=YES +// RUN: env CCC_OVERRIDE_OPTIONS=+-fno-integrated-cc1 \ +// RUN: %clang -fintegrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NO + +// YES: (in-process) +// NO-NOT: (in-process) diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 4cdf8015b1bfc..39f6c7f62be41 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -258,27 +258,6 @@ static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); if (TheDriver.CCLogDiagnostics) TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE"); - - // Whether the cc1 tool should be called inside the current process, or if we - // should spawn a new clang process (old behavior). - // Not having an additional process saves some execution time of Windows, - // and makes debugging easier. - bool UseNewCC1Process = CLANG_SPAWN_CC1; - - StringRef SpawnCC1Str = ::getenv("CLANG_SPAWN_CC1"); - if (!SpawnCC1Str.empty()) { - if (SpawnCC1Str != "0" && SpawnCC1Str != "1") { - llvm::errs() << "error: the value of the environment variable " - "CLANG_SPAWN_CC1 must be either 0 or 1.\n"; - ::exit(1); - } - UseNewCC1Process = SpawnCC1Str[0] - '0'; - } - if (!UseNewCC1Process) { - TheDriver.CC1Main = &ExecuteCC1Tool; - // Ensure the CC1Command actually catches cc1 crashes - llvm::CrashRecoveryContext::Enable(); - } } static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, @@ -294,7 +273,7 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, // This lets us create the DiagnosticsEngine with a properly-filled-out // DiagnosticOptions instance. static DiagnosticOptions * -CreateAndPopulateDiagOpts(ArrayRef argv) { +CreateAndPopulateDiagOpts(ArrayRef argv, bool &UseNewCC1Process) { auto *DiagOpts = new DiagnosticOptions; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = getDriverOptTable().ParseArgs( @@ -303,6 +282,12 @@ CreateAndPopulateDiagOpts(ArrayRef argv) { // Any errors that would be diagnosed here will also be diagnosed later, // when the DiagnosticsEngine actually exists. (void)ParseDiagnosticArgs(*DiagOpts, Args); + + UseNewCC1Process = + Args.hasFlag(clang::driver::options::OPT_fno_integrated_cc1, + clang::driver::options::OPT_fintegrated_cc1, + /*Default=*/CLANG_SPAWN_CC1); + return DiagOpts; } @@ -330,7 +315,7 @@ static void SetInstallDir(SmallVectorImpl &argv, static int ExecuteCC1Tool(ArrayRef argv) { // If we call the cc1 tool from the clangDriver library (through - // Driver::CC1Main), we need to cleanup the options usage count. The options + // Driver::CC1Main), we need to clean up the options usage count. The options // are currently global, and they might have been used previously by the // driver. llvm::cl::ResetAllOptionOccurrences(); @@ -413,6 +398,8 @@ int main(int argc_, const char **argv_) { return ExecuteCC1Tool(argv); } + // Handle options that need handling before the real command line parsing in + // Driver::BuildCompilation() bool CanonicalPrefixes = true; for (int i = 1, size = argv.size(); i < size; ++i) { // Skip end-of-line response file markers @@ -457,8 +444,14 @@ int main(int argc_, const char **argv_) { std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes); + // Whether the cc1 tool should be called inside the current process, or if we + // should spawn a new clang subprocess (old behavior). + // Not having an additional process saves some execution time of Windows, + // and makes debugging and profiling easier. + bool UseNewCC1Process; + IntrusiveRefCntPtr DiagOpts = - CreateAndPopulateDiagOpts(argv); + CreateAndPopulateDiagOpts(argv, UseNewCC1Process); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); @@ -486,6 +479,12 @@ int main(int argc_, const char **argv_) { SetBackdoorDriverOutputsFromEnvVars(TheDriver); + if (!UseNewCC1Process) { + TheDriver.CC1Main = &ExecuteCC1Tool; + // Ensure the CC1Command actually catches cc1 crashes + llvm::CrashRecoveryContext::Enable(); + } + std::unique_ptr C(TheDriver.BuildCompilation(argv)); int Res = 1; if (C && !C->containsError()) {