https://github.com/vvereschaka updated 
https://github.com/llvm/llvm-project/pull/205736

>From f0ca0ad5a4064c520657ba1c2ac88164664f4170 Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <[email protected]>
Date: Wed, 24 Jun 2026 23:30:25 -0700
Subject: [PATCH 1/4] [clang-cl] Omit command line in COFF CV debug info for
 the deterministic builds.

The command line can contain the arguments, such as the pathes or `/pathmap` 
options,
which could break a reproducable output for the object files. Just do not 
include it
into the debug sections in the result .obj file.
---
 clang/lib/Driver/ToolChains/Clang.cpp | 2 ++
 clang/test/Driver/cl-deterministic.c  | 1 +
 2 files changed, 3 insertions(+)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 418d540895681..35f0193726f35 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8948,6 +8948,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID 
InputType,
     // deterministic result, but we force this timestamp to 0, which also
     // produces deterministic result.
     CmdArgs.push_back("-mno-incremental-linker-compatible");
+    // Omit command line in COFF CV debug section.
+    CmdArgs.push_back("-gno-codeview-command-line");
   }
 
   bool HasNoDateTime = Args.hasFlag(options::OPT__SLASH_d1nodatetime,
diff --git a/clang/test/Driver/cl-deterministic.c 
b/clang/test/Driver/cl-deterministic.c
index 34010f24e53c2..61937bed8c114 100644
--- a/clang/test/Driver/cl-deterministic.c
+++ b/clang/test/Driver/cl-deterministic.c
@@ -9,6 +9,7 @@
 // RUN: %clang_cl -E -### /experimental:deterministic -- %s 2>&1 | FileCheck 
%s --check-prefix=WDATETIME
 // WDATETIME: -Wdate-time
 // WDATETIME: -mno-incremental-linker-compatible
+// WDATETIME: -gno-codeview-command-line
 // RUN: %clang_cl -E -### /d1nodatetime -- %s 2>&1 | FileCheck %s 
--check-prefix=MACROREDEF
 // MACROREDEF: -init-datetime-macros=undefined
 

>From 0eb6e44f4bf0ca562132ff0a448403c10eabd551 Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <[email protected]>
Date: Thu, 25 Jun 2026 11:44:07 -0700
Subject: [PATCH 2/4] Update the test.

---
 clang/test/Driver/cl-deterministic.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/Driver/cl-deterministic.c 
b/clang/test/Driver/cl-deterministic.c
index 61937bed8c114..34d310e25f83c 100644
--- a/clang/test/Driver/cl-deterministic.c
+++ b/clang/test/Driver/cl-deterministic.c
@@ -6,10 +6,10 @@
 
 // expected-no-diagnostics
 
-// RUN: %clang_cl -E -### /experimental:deterministic -- %s 2>&1 | FileCheck 
%s --check-prefix=WDATETIME
-// WDATETIME: -Wdate-time
-// WDATETIME: -mno-incremental-linker-compatible
-// WDATETIME: -gno-codeview-command-line
+// RUN: %clang_cl -E -### /experimental:deterministic -- %s 2>&1 | FileCheck 
%s --check-prefix=EXPERIMENTALDETERM
+// EXPERIMENTALDETERM: -Wdate-time
+// EXPERIMENTALDETERM: -mno-incremental-linker-compatible
+// EXPERIMENTALDETERM: -gno-codeview-command-line
 // RUN: %clang_cl -E -### /d1nodatetime -- %s 2>&1 | FileCheck %s 
--check-prefix=MACROREDEF
 // MACROREDEF: -init-datetime-macros=undefined
 

>From fb25bd077db717540bf2e5f7be2671b848db6718 Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <[email protected]>
Date: Thu, 25 Jun 2026 21:30:44 -0700
Subject: [PATCH 3/4] Add `-gcodeview-sanitize-buildinfo` cc1 option to
 sanitize CV debug build info.

The option removes all compiler flags, which could affect reprucible build,
from the build info field of the CodeView debug information sections.

The dropped options are the following (clang/cc1 only):
- macro definition
- all file include options
- contains path/directory or file as argument
- -f*-prefix-map options
---
 clang/include/clang/Basic/DebugOptions.def |  3 +++
 clang/include/clang/Options/Options.td     | 20 +++++++++++---
 clang/lib/Driver/ToolChains/Clang.cpp      |  5 ++--
 clang/lib/Frontend/CompilerInvocation.cpp  | 31 ++++++++++++++++++++--
 clang/test/Driver/cl-deterministic.c       |  2 +-
 5 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/Basic/DebugOptions.def 
b/clang/include/clang/Basic/DebugOptions.def
index c9dd3f726e799..a0ec9dfc60d0c 100644
--- a/clang/include/clang/Basic/DebugOptions.def
+++ b/clang/include/clang/Basic/DebugOptions.def
@@ -122,6 +122,9 @@ DEBUGOPT(CodeViewGHash, 1, 0, Compatible)
 /// Whether to emit the compiler path and command line into the CodeView debug 
information.
 DEBUGOPT(CodeViewCommandLine, 1, 0, Compatible)
 
+/// Wheither to remove non-deterministic build options from the CodeView debug 
information.
+DEBUGOPT(CodeViewSanitizeBuildinfo, 1, 0, Compatible)
+
 /// Whether emit extra debug info for sample pgo profile collection.
 DEBUGOPT(DebugInfoForProfiling, 1, 0, Compatible)
 
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 4fc9f4d4c3472..05e5199c89865 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1527,7 +1527,7 @@ def dependency_dot : Separate<["-"], "dependency-dot">,
   HelpText<"Filename to write DOT-formatted header dependencies to">,
   MarshallingInfoString<DependencyOutputOpts<"DOTOutputFile">>;
 def module_dependency_dir : Separate<["-"], "module-dependency-dir">,
-  Visibility<[ClangOption, CC1Option]>,
+  Visibility<[ClangOption, CC1Option]>, MetaVarName<"<directory>">,
   HelpText<"Directory to dump module dependencies to">,
   MarshallingInfoString<DependencyOutputOpts<"ModuleDependencyOutputDir">>;
 def dsym_dir : JoinedOrSeparate<["-"], "dsym-dir">,
@@ -1590,7 +1590,7 @@ def extract_api_ignores_EQ: CommaJoined<["--"], 
"extract-api-ignores=">,
     HelpText<"Comma separated list of files containing a new line separated 
list of API symbols to ignore when extracting API information.">,
     MarshallingInfoStringVector<FrontendOpts<"ExtractAPIIgnoresFileList">>;
 def symbol_graph_dir_EQ: Joined<["--"], "symbol-graph-dir=">,
-   Visibility<[ClangOption, CC1Option]>,
+   Visibility<[ClangOption, CC1Option]>, MetaVarName<"<directory>">,
    HelpText<"Directory in which to emit symbol graphs.">,
    MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
 def emit_pretty_sgf: Flag<["--"], "pretty-sgf">,
@@ -1813,18 +1813,21 @@ def fno_auto_profile_accurate : Flag<["-"], 
"fno-auto-profile-accurate">,
 def fdebug_compilation_dir_EQ : Joined<["-"], "fdebug-compilation-dir=">,
     Group<f_Group>,
     Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption, DXCOption]>,
+    MetaVarName<"<directory>">,
     HelpText<"The compilation directory to embed in the debug info">,
     MarshallingInfoString<CodeGenOpts<"DebugCompilationDir">>;
 def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
     Group<f_Group>,
     Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption, DXCOption]>,
+    MetaVarName<"<directory>">,
     Alias<fdebug_compilation_dir_EQ>;
 def fcoverage_compilation_dir_EQ : Joined<["-"], "fcoverage-compilation-dir=">,
     Group<f_Group>, Visibility<[ClangOption, CC1Option, CC1AsOption, 
CLOption]>,
+    MetaVarName<"<directory>">,
     HelpText<"The compilation directory to embed in the coverage mapping.">,
     MarshallingInfoString<CodeGenOpts<"CoverageCompilationDir">>;
 def ffile_compilation_dir_EQ : Joined<["-"], "ffile-compilation-dir=">, 
Group<f_Group>,
-    Visibility<[ClangOption, CLOption, DXCOption]>,
+    Visibility<[ClangOption, CLOption, DXCOption]>, MetaVarName<"<directory>">,
     HelpText<"The compilation directory to embed in the debug info and 
coverage mapping.">;
 defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling",
   CodeGenOpts<"DebugInfoForProfiling">, DefaultFalse,
@@ -5045,11 +5048,13 @@ def fcoverage_prefix_map_EQ
     HelpText<"remap file source paths <old> to <new> in coverage mapping. If 
there are multiple options, prefix replacement is applied in reverse order 
starting from the last one">;
 def ffile_prefix_map_EQ
   : Joined<["-"], "ffile-prefix-map=">, Group<f_Group>,
+    MetaVarName<"<old>=<new>">,
     HelpText<"remap file source paths in debug info, coverage mapping, 
predefined preprocessor "
              "macros and __builtin_FILE(). Implies -ffile-reproducible.">;
 def fmacro_prefix_map_EQ
   : Joined<["-"], "fmacro-prefix-map=">, Group<f_Group>,
-  Visibility<[ClangOption, CLOption, CC1Option]>,
+    Visibility<[ClangOption, CLOption, CC1Option]>,
+    MetaVarName<"<old>=<new>">,
     HelpText<"remap file source paths in predefined preprocessor macros and "
              "__builtin_FILE(). Implies -ffile-reproducible.">;
 defm force_dwarf_frame : BoolFOption<"force-dwarf-frame",
@@ -5135,6 +5140,12 @@ defm codeview_command_line : BoolOption<"g", 
"codeview-command-line",
   NegFlag<SetFalse, [], [ClangOption], "Don't emit compiler path and command 
line into CodeView debug information">,
   BothFlags<[], [ClangOption, CLOption, DXCOption, CC1Option]>>,
   Group<g_flags_Group>;
+defm codeview_sanitize_buildinfo : BoolOption<"g", 
"codeview-sanitize-buildinfo",
+  CodeGenOpts<"CodeViewSanitizeBuildinfo">, DefaultFalse,
+  PosFlag<SetTrue, [], [ClangOption], "Sanitize non-deterministic build flags 
and pathes in CodeView debug information">,
+  NegFlag<SetFalse, [], [ClangOption], "Keep non-deterministic build flags and 
pathes in CodeView debug information">,
+  BothFlags<[], [ClangOption, CLOption, DXCOption, CC1Option]>>,
+  Group<g_flags_Group>;
 defm inline_line_tables : BoolGOption<"inline-line-tables",
   CodeGenOpts<"NoInlineLineTables">, DefaultFalse,
   NegFlag<SetTrue, [], [ClangOption, CC1Option],
@@ -8593,6 +8604,7 @@ def foverride_record_layout_EQ : Joined<["-"], 
"foverride-record-layout=">,
   HelpText<"Override record layouts with those in the given file">,
   MarshallingInfoString<FrontendOpts<"OverrideRecordLayoutsFile">>;
 def pch_through_header_EQ : Joined<["-"], "pch-through-header=">,
+  MetaVarName<"<file>">,
   HelpText<"Stop PCH generation after including this file.  When using a PCH, "
            "skip tokens until after this file is included.">,
   MarshallingInfoString<PreprocessorOpts<"PCHThroughHeader">>;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 35f0193726f35..c7dd5801fc599 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8948,8 +8948,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID 
InputType,
     // deterministic result, but we force this timestamp to 0, which also
     // produces deterministic result.
     CmdArgs.push_back("-mno-incremental-linker-compatible");
-    // Omit command line in COFF CV debug section.
-    CmdArgs.push_back("-gno-codeview-command-line");
+    // Sanitize the command line options that could affect the reproducible
+    // builds for CodeView build info attribute.
+    CmdArgs.push_back("-gcodeview-sanitize-buildinfo");
   }
 
   bool HasNoDateTime = Args.hasFlag(options::OPT__SLASH_d1nodatetime,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index dfde7b756dbff..81a25750f31e0 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -5178,8 +5178,35 @@ bool CompilerInvocation::CreateFromArgsImpl(
 
   // Store the command-line for using in the CodeView backend.
   if (Res.getCodeGenOpts().CodeViewCommandLine) {
-    Res.getCodeGenOpts().Argv0 = Argv0;
-    append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
+    // Remove all options that could affect reproducible build
+    // from the CoveView build info attributes.
+    if (Res.getCodeGenOpts().CodeViewSanitizeBuildinfo) {
+      Res.getCodeGenOpts().Argv0 = nullptr;
+
+      for (const auto *A : Args) {
+        const StringRef ArgName = A->getOption().getName();
+        const StringRef ArgMetaVar = A->getOption().getMetaVar();
+        const unsigned int ArgID = A->getOption().getID();
+
+        // Use MetaVar name to filter out most of the options.
+        if (ArgName == "<input>" || A->getOption().matches(OPT_resource_dir) ||
+            A->getOption().matches(OPT_working_directory) || ArgID == OPT_D ||
+            ArgID == OPT_fmodule_file || ArgID == OPT_ccc_install_dir ||
+            ArgID == OPT_gcc_install_dir_EQ ||
+            ArgID == OPT_config_system_dir_EQ ||
+            ArgID == OPT_config_user_dir_EQ || ArgID == OPT_fprofile_dir ||
+            ArgMetaVar == "<directory>" || ArgMetaVar == "<dir>" ||
+            ArgMetaVar == "<gcc-path>" || ArgMetaVar == "<pathname>" ||
+            ArgMetaVar == "<path>" || ArgMetaVar == "<file>" ||
+            ArgMetaVar == "<script>" || ArgMetaVar == "<old>=<new>")
+          continue;
+
+        Res.getCodeGenOpts().CommandLineArgs.push_back(A->getAsString(Args));
+      }
+    } else {
+      Res.getCodeGenOpts().Argv0 = Argv0;
+      append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
+    }
   }
 
   if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty() &&
diff --git a/clang/test/Driver/cl-deterministic.c 
b/clang/test/Driver/cl-deterministic.c
index 34d310e25f83c..9a121312170e6 100644
--- a/clang/test/Driver/cl-deterministic.c
+++ b/clang/test/Driver/cl-deterministic.c
@@ -9,7 +9,7 @@
 // RUN: %clang_cl -E -### /experimental:deterministic -- %s 2>&1 | FileCheck 
%s --check-prefix=EXPERIMENTALDETERM
 // EXPERIMENTALDETERM: -Wdate-time
 // EXPERIMENTALDETERM: -mno-incremental-linker-compatible
-// EXPERIMENTALDETERM: -gno-codeview-command-line
+// EXPERIMENTALDETERM: -gcodeview-sanitize-buildinfo
 // RUN: %clang_cl -E -### /d1nodatetime -- %s 2>&1 | FileCheck %s 
--check-prefix=MACROREDEF
 // MACROREDEF: -init-datetime-macros=undefined
 

>From 392371d62eeea8f3cc9583142236c60c0e0d5780 Mon Sep 17 00:00:00 2001
From: Vladimir Vereschaka <[email protected]>
Date: Fri, 26 Jun 2026 17:46:02 -0700
Subject: [PATCH 4/4] Added test

---
 clang/test/DebugInfo/Generic/codeview-buildinfo.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/clang/test/DebugInfo/Generic/codeview-buildinfo.c 
b/clang/test/DebugInfo/Generic/codeview-buildinfo.c
index b930e3cc642c4..aa3489d832cf9 100644
--- a/clang/test/DebugInfo/Generic/codeview-buildinfo.c
+++ b/clang/test/DebugInfo/Generic/codeview-buildinfo.c
@@ -24,6 +24,12 @@
 // RUN: cd %t.relpath && %clang_cl --target=i686-windows-msvc /c /Z7 
/Fo:hello.obj -- hello.cpp
 // RUN: llvm-pdbutil dump --types %t.relpath/hello.obj | FileCheck %s 
--check-prefix RELPATH
 
+// The non-deterministic build options must be removed from the command line
+// if `/experimental:deterministic` has been specified.
+// RUN: %clang_cl --target=i686-windows-msvc /c /Z7 /Fo%t.obj \
+// RUN:   /pathmap:%t.pathmap=x:/path-to /experimental:deterministic -- %s
+// RUN: llvm-pdbutil dump --types %t.obj | FileCheck %s --check-prefix 
SANITIZED-CMDLINE
+
 int main(void) { return 42; }
 
 // CHECK:                       Types (.debug$T)
@@ -78,3 +84,6 @@ int main(void) { return 42; }
 // RELPATH-NEXT:           0x{{.*}}: `
 // RELPATH-NOT:   {{hello\.cpp}}
 // RELPATH-SAME:  `
+
+// SANITIZED-CMDLINE-NOT: -fdebug-prefix-map= 
+// SANITIZED-CMDLINE-NOT: -fdebug-compilation-dir=

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to