[clang] [clang] Canonicalizing `-include-pch` input in the Frontend (PR #180065)
Qiongsi Wu via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 5 15:51:51 PST 2026
https://github.com/qiongsiwu updated https://github.com/llvm/llvm-project/pull/180065
>From b8ba91c9cf72a34cb88d39de744fefe8711eeeac Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Thu, 5 Feb 2026 15:08:06 -0800
Subject: [PATCH 1/2] Canonicalizing -include-pch input in the frontend.
---
clang/lib/Frontend/FrontendAction.cpp | 17 +++++++++---
clang/test/PCH/debug-info-pch-path.c | 2 ++
clang/test/PCH/pch-input-path-independent.c | 29 +++++++++++++++++++++
3 files changed, 44 insertions(+), 4 deletions(-)
create mode 100644 clang/test/PCH/pch-input-path-independent.c
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 7810f0999f7d6..c5c17334da295 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -1018,13 +1018,22 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
return true;
}
- // If the implicit PCH include is actually a directory, rather than
- // a single file, search for a suitable PCH file in that directory.
if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
FileManager &FileMgr = CI.getFileManager();
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+
+ // Canonicalize ImplicitPCHInclude. This way, all the downstream code,
+ // including the ASTWriter, will receive the absolute path to the included
+ // PCH. This way we can avoid reasoning about absolute path or relative
+ // paths later on during serialization.
+ SmallString<128> PCHIncludePath(PPOpts.ImplicitPCHInclude);
+ FileMgr.makeAbsolutePath(PCHIncludePath);
+ llvm::sys::path::remove_dots(PCHIncludePath, true);
+ PPOpts.ImplicitPCHInclude = PCHIncludePath.str();
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
- std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();
+
+ // If the implicit PCH include is actually a directory, rather than
+ // a single file, search for a suitable PCH file in that directory.
if (auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude)) {
std::error_code EC;
SmallString<128> DirNative;
@@ -1040,7 +1049,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.getPCHContainerReader(), CI.getLangOpts(),
CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getPreprocessorOpts(), CI.getHeaderSearchOpts(),
- SpecificModuleCachePath,
+ CI.getSpecificModuleCachePath(),
/*RequireStrictOptionMatches=*/true)) {
PPOpts.ImplicitPCHInclude = std::string(Dir->path());
Found = true;
diff --git a/clang/test/PCH/debug-info-pch-path.c b/clang/test/PCH/debug-info-pch-path.c
index 22b367f344204..0a4e9d8146f00 100644
--- a/clang/test/PCH/debug-info-pch-path.c
+++ b/clang/test/PCH/debug-info-pch-path.c
@@ -17,6 +17,7 @@
// RUN: %clang_cc1 -debug-info-kind=standalone \
// RUN: -dwarf-ext-refs -fmodule-format=obj \
// RUN: -triple %itanium_abi_triple \
+// RUN: -fdebug-compilation-dir=%t \
// RUN: -include-pch prefix.pch %s -emit-llvm -o %t.nodir.ll %s
// RUN: cat %t.nodir.ll | FileCheck %s --check-prefix=CHECK-REL-NODIR
//
@@ -42,6 +43,7 @@
// RUN: %clang_cc1 -debug-info-kind=standalone \
// RUN: -dwarf-ext-refs -fmodule-format=obj \
// RUN: -triple %itanium_abi_triple \
+// RUN: -fdebug-compilation-dir=%t \
// RUN: -include-pch pchdir/prefix.pch %s -emit-llvm -o %t.rel.ll %s
// RUN: cat %t.rel.ll | FileCheck %s --check-prefix=CHECK-REL
diff --git a/clang/test/PCH/pch-input-path-independent.c b/clang/test/PCH/pch-input-path-independent.c
new file mode 100644
index 0000000000000..56a697b9d300f
--- /dev/null
+++ b/clang/test/PCH/pch-input-path-independent.c
@@ -0,0 +1,29 @@
+// Testing `-include-pch` canoniclaization.
+// When PCHs are chained, the dependent PCHs produced are identical
+// whether the included PCH is specified through a relative path or an absolute
+// path (bridging1.h.pch vs bridging2.h.pch).
+// The dependent PCHs are also identical regardless of the working
+// directory where clang is invoked (bridging1.h.pch vs bridging3.h.pch).
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+// RUN: %clang_cc1 -triple x86_64-apple-macos11 -emit-pch h1.h -o %t/h1.h.pch
+// RUN: %clang_cc1 -triple x86_64-apple-macos11 -emit-pch %t/bridging.h \
+// RUN: -o %t/bridging1.h.pch -include-pch %t/h1.h.pch
+// RUN: %clang_cc1 -triple x86_64-apple-macos11 -emit-pch %t/bridging.h \
+// RUN: -o %t/bridging2.h.pch -include-pch ./h1.h.pch
+// RUN: mkdir %t/wd/
+// RUN: cd %t/wd/
+// RUN: %clang_cc1 -triple x86_64-apple-macos11 -emit-pch %t/bridging.h \
+// RUN: -o %t/bridging3.h.pch -include-pch ../h1.h.pch
+
+// RUN: diff %t/bridging1.h.pch %t/bridging2.h.pch
+// RUN: diff %t/bridging1.h.pch %t/bridging3.h.pch
+
+//--- h1.h
+int bar1() { return 42; }
+
+//--- bridging.h
+int bar() { return bar1(); }
+
>From 60271a3d0fbf22e28757da727828e6c2de2d1d74 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Thu, 5 Feb 2026 15:51:35 -0800
Subject: [PATCH 2/2] Fixing tests on Windows.
---
clang/test/Modules/validate-file-content.m | 2 +-
clang/test/PCH/modified-module-dependency.m | 2 +-
clang/test/PCH/validate-file-content.m | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/Modules/validate-file-content.m b/clang/test/Modules/validate-file-content.m
index cff89884552b7..1eae7748165c1 100644
--- a/clang/test/Modules/validate-file-content.m
+++ b/clang/test/Modules/validate-file-content.m
@@ -24,7 +24,7 @@
// RUN: not %clang_cc1 -fsyntax-only -fmodules-cache-path=%t/cache -fmodules -fimplicit-module-maps -I %t -include-pch %t/a.pch %s -fvalidate-ast-input-files-content 2> %t/stderr
// RUN: FileCheck %s < %t/stderr
//
-// CHECK: file '[[M_H:.*[/\\]m\.h]]' has been modified since the precompiled header '[[A_PCH:.*/a\.pch]]' was built: content changed
+// CHECK: file '[[M_H:.*[/\\]m\.h]]' has been modified since the precompiled header '[[A_PCH:.*[/\\]a\.pch]]' was built: content changed
// CHECK: '[[M_H]]' required by '[[M_PCM:.*[/\\]m.*\.pcm]]'
// CHECK: '[[M_PCM]]' required by '[[A_PCH]]'
// CHECK: please rebuild precompiled file '[[A_PCH]]'
diff --git a/clang/test/PCH/modified-module-dependency.m b/clang/test/PCH/modified-module-dependency.m
index a4710dea51169..bf93b53e2c152 100644
--- a/clang/test/PCH/modified-module-dependency.m
+++ b/clang/test/PCH/modified-module-dependency.m
@@ -14,7 +14,7 @@
// RUN: not %clang_cc1 -x objective-c -I %t-dir -include-pch %t-dir/prefix.pch -fmodules -fimplicit-module-maps -fmodules-cache-path=%t-dir/cache -fdisable-module-hash -fsyntax-only %s 2> %t-dir/log
// RUN: FileCheck %s < %t-dir/log
-// CHECK: file '[[TEST_H:.*[/\\]test\.h]]' has been modified since the precompiled header '[[PREFIX_PCH:.*/prefix\.pch]]' was built
+// CHECK: file '[[TEST_H:.*[/\\]test\.h]]' has been modified since the precompiled header '[[PREFIX_PCH:.*[/\\]prefix\.pch]]' was built
// CHECK: '[[TEST_H]]' required by '[[TEST_PCM:.*[/\\]test\.pcm]]'
// CHECK: '[[TEST_PCM]]' required by '[[PREFIX_PCH]]'
// CHECK: please rebuild precompiled file '[[PREFIX_PCH]]'
diff --git a/clang/test/PCH/validate-file-content.m b/clang/test/PCH/validate-file-content.m
index 8863b7abea3af..289dbff1a8c20 100644
--- a/clang/test/PCH/validate-file-content.m
+++ b/clang/test/PCH/validate-file-content.m
@@ -22,6 +22,6 @@
// RUN: not %clang_cc1 -fsyntax-only -I %t -include-pch %t/a.pch %s -fvalidate-ast-input-files-content 2> %t/stderr
// RUN: FileCheck %s < %t/stderr
//
-// CHECK: file '[[M_H:.*[/\\]m\.h]]' has been modified since the precompiled header '[[A_PCH:.*/a\.pch]]' was built: content changed
+// CHECK: file '[[M_H:.*[/\\]m\.h]]' has been modified since the precompiled header '[[A_PCH:.*[/\\]a\.pch]]' was built: content changed
// CHECK: please rebuild precompiled file '[[A_PCH]]'
// expected-no-diagnostics
More information about the cfe-commits
mailing list