Reland: "[Frontend][PCH]-Add support for ignoring PCH options (-ignore-pch). (#142409)" (#143614)

Visual Studio has an argument to ignore all PCH related switches.
clang-cl has also support option /Y-. Having the same option in clang
would be helpful. This commit is to add support for ignoring PCH options
(-ignore-pch).

The commit includes:
  1. Implement -ignore-pch as a Driver option.
  2. Add a Driver test and a PCH test.
  3. Add a section of -ignore-pch to user manual.
  4. Add a release note for the new option '-ignore-pch'.

The change since the original landing:
  1. preprocessing-only mode doesn't imply that -include-pch is disabled.

Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
This commit is contained in:
Ying Yi
2025-06-17 10:54:22 +01:00
committed by GitHub
parent 4c8f434409
commit 6f29837659
8 changed files with 167 additions and 2 deletions

View File

@@ -339,6 +339,8 @@ New Compiler Flags
- New option ``-Wnrvo`` added and disabled by default to warn about missed NRVO opportunities.
- New option ``-ignore-pch`` added to disable precompiled headers. It overrides ``-emit-pch`` and ``-include-pch``. (#GH142409, `PCHDocs <https://clang.llvm.org/docs/UsersManual.html#ignoring-a-pch-file>`_).
Deprecated Compiler Flags
-------------------------

View File

@@ -1458,6 +1458,19 @@ will be processed from the PCH file. Otherwise, Clang will report an error.
``test.h`` since ``test.h`` was included directly in the source file and not
specified on the command line using ``-include-pch``.
Ignoring a PCH File
^^^^^^^^^^^^^^^^^^^
To ignore PCH options, a `-ignore-pch` option is passed to ``clang``:
.. code-block:: console
$ clang -x c-header test.h -Xclang -ignore-pch -o test.h.pch
$ clang -include-pch test.h.pch -Xclang -ignore-pch test.c -o test
This option disables precompiled headers, overrides -emit-pch and -include-pch.
test.h.pch is not generated and not used as a prefix header.
Relocatable PCH Files
^^^^^^^^^^^^^^^^^^^^^

View File

@@ -3351,6 +3351,9 @@ defm pch_codegen: OptInCC1FFlag<"pch-codegen", "Generate ", "Do not generate ",
"code for uses of this PCH that assumes an explicit object file will be built for the PCH">;
defm pch_debuginfo: OptInCC1FFlag<"pch-debuginfo", "Generate ", "Do not generate ",
"debug info for types in an object file built from this PCH and do not generate them elsewhere">;
def ignore_pch : Flag<["-"], "ignore-pch">, Group<f_Group>,
Visibility<[ClangOption]>,
HelpText<"Disable precompiled headers, overrides -emit-pch and -include-pch">;
def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CLOption]>,

View File

@@ -4331,6 +4331,14 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
YcArg = YuArg = nullptr;
}
if (Args.hasArg(options::OPT_include_pch) &&
Args.hasArg(options::OPT_ignore_pch)) {
// If -ignore-pch is used, -include-pch is disabled. Since -emit-pch is
// CC1option, it will not be added to command argments if -ignore-pch is
// used.
Args.eraseArg(options::OPT_include_pch);
}
bool LinkOnly = phases::Link == FinalPhase && Inputs.size() > 0;
for (auto &I : Inputs) {
types::ID InputType = I.first;

View File

@@ -5202,7 +5202,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-module-interface");
else if (JA.getType() == types::TY_HeaderUnit)
CmdArgs.push_back("-emit-header-unit");
else
else if (!Args.hasArg(options::OPT_ignore_pch))
CmdArgs.push_back("-emit-pch");
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
@@ -5259,6 +5259,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (JA.getType() == types::TY_PP_Asm) {
CmdArgs.push_back("-S");
} else if (JA.getType() == types::TY_AST) {
if (!Args.hasArg(options::OPT_ignore_pch))
CmdArgs.push_back("-emit-pch");
} else if (JA.getType() == types::TY_ModuleFile) {
CmdArgs.push_back("-module-file-info");

View File

@@ -0,0 +1,19 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// Create PCH without -ignore-pch.
// RUN: %clang -x c++-header %S/Inputs/pchfile.h -### 2>&1 | FileCheck %s -check-prefix=CHECK-EMIT-PCH
// RUN: %clang -x c++-header %S/Inputs/pchfile.h -o %t/pchfile.h.pch
// RUN: %clang %s -include-pch %t/pchfile.h.pch -### 2>&1 | FileCheck %s -check-prefix=CHECK-INCLUDE-PCH
// RUN: %clang %s -emit-ast -include-pch %t/pchfile.h.pch -### 2>&1 | FileCheck %s -check-prefixes=CHECK-EMIT-PCH,CHECK-INCLUDE-PCH
// Create PCH with -ignore-pch.
// RUN: %clang -x c++-header -ignore-pch %S/Inputs/pchfile.h -### 2>&1 | FileCheck %s -check-prefix=CHECK-IGNORE-PCH
// RUN: %clang %s -ignore-pch -include-pch %t/pchfile.h.pch -### 2>&1 | FileCheck %s -check-prefix=CHECK-IGNORE-PCH
// RUN: %clang %s -ignore-pch -emit-ast -include-pch %t/pchfile.h.pch -### 2>&1 | FileCheck %s -check-prefix=CHECK-IGNORE-PCH
// CHECK-EMIT-PCH: -emit-pch
// CHECK-INCLUDE-PCH: -include-pch
// CHECK-IGNORE-PCH-NOT: -emit-pch
// CHECK-IGNORE-PCH-NOT: -include-pch

View File

@@ -0,0 +1,6 @@
#ifndef IGNORED_PCH_H
#define IGNORED_PCH_H
inline int f() {
return 42;
}
#endif // IGNORED_PCH_H

View File

@@ -0,0 +1,113 @@
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -o %t.ll
// RUN: ls %t.pch | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -o %t.pch
// RUN: %clang %s -emit-ast -include-pch %t.pch -o %t.ll
// RUN: ls %t.pch | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Check that -ignore-pch causes -emit-pch and -include-pch options to be ignored.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH-ERROR %s
// RUN: ls %t.ll 2>&1 | FileCheck --check-prefix=CHECK-OBJ %s
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -emit-ast %s -include-pch %t.pch -ignore-pch -o %t.ll
// RUN: not ls %t.ll 2>&1 | FileCheck --check-prefix=CHECK-OBJ-ERROR %s
// Check that -ignore-pch works for multiple PCH related options.
// Test with -building-pch-with-obj.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -Xclang -building-pch-with-obj -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -Xclang -building-pch-with-obj -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH-ERROR %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fallow-pch-with-compiler-errors.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -Xclang -fallow-pch-with-compiler-errors -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -Xclang -fallow-pch-with-compiler-errors -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH-ERROR %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fallow-pch-with-different-modules-cache-path.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -Xclang -fallow-pch-with-different-modules-cache-path -o %t.pch
// RUN: %clang -S -emit-llvm %s -ignore-pch -include-pch %t.pch -Xclang -fallow-pch-with-different-modules-cache-path -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH-ERROR %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fpch-codegen.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -fpch-codegen -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -fpch-codegen -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH-ERROR %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fpch-debuginfo.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -fpch-debuginfo -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -fpch-debuginfo -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fpch-instantiate-templates.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -fpch-instantiate-templates -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -fpch-instantiate-templates -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fno-pch-timestamp.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -Xclang -fno-pch-timestamp -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -Xclang -fno-pch-timestamp -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -fno-validate-pch.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -Xclang -fno-validate-pch -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -Xclang -fno-validate-pch -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -relocatable-pch.
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -relocatable-pch -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -relocatable-pch -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with -pch-through-hdrstop-create/-pch-through-hdrstop-use
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -ignore-pch -Xclang -pch-through-hdrstop-create -o %t.pch
// RUN: %clang -S -emit-llvm %s -include-pch %t.pch -ignore-pch -Xclang -pch-through-hdrstop-use -o %t.ll
// RUN: not ls %t.pch 2>&1 | FileCheck --check-prefix=CHECK-PCH %s
// RUN: ls %t.ll | FileCheck --check-prefix=CHECK-OBJ %s
// Test with AST dump output:
// RUN: rm -rf %t.pch %t.ll
// RUN: %clang -x c-header %S/Inputs/ignored-pch.h -o %t.pch
// RUN: %clang %s -include-pch %t.pch -Xclang -ast-dump-all -c | FileCheck --check-prefix=CHECK-AST-PCH %s
// RUN: %clang %s -include-pch %t.pch -ignore-pch -Xclang -ast-dump-all -c | FileCheck --check-prefix=CHECK-AST %s
// CHECK-PCH: ignored-pch.c.{{.*}}.pch
// CHECK-OBJ: ignored-pch.c.{{.*}}.ll
// CHECK-PCH-ERROR: ignored-pch.c.{{.*}}.pch{{'?}}: No such file or directory
// CHECK-OBJ-ERROR: ignored-pch.c.{{.*}}.ll{{'?}}: No such file or directory
// CHECK-AST-PCH: <undeserialized declarations>
// CHECK-AST-NOT: <undeserialized declarations>
#pragma hdrstop
#include "Inputs/ignored-pch.h"
int main() {
return f();
}