https://github.com/bjosv updated https://github.com/llvm/llvm-project/pull/201803
From f45ee969f011915705771298f185c45e6dd29d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Mon, 23 Mar 2026 09:59:57 +0100 Subject: [PATCH 1/3] [Clang] Add -fsanitize-compilation-dir= for reproducible sanitizer builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add -fsanitize-compilation-dir=<dir> to set the compilation directory for sanitizer metadata. Absolute source paths that start with the given directory are made relative to it, affecting ASan module names and UBSan diagnostic source locations. This enables reproducible builds when using AddressSanitizer or UndefinedBehaviorSanitizer from different build directories. The flag follows the established -f*-compilation-dir pattern used by -fdebug-compilation-dir and -fcoverage-compilation-dir. It is also implied by -ffile-compilation-dir=, which sets the compilation directory for debug info, coverage, and now sanitizer metadata in a single flag. This addresses the issue where ASan and UBSan embed absolute source file paths in binary metadata (.rodata), causing non-reproducible builds when compiling from different directories. Signed-off-by: Björn Svensson <[email protected]> --- clang/docs/AddressSanitizer.rst | 29 +++++++++++++++++ clang/docs/ReleaseNotes.rst | 5 +++ clang/docs/UndefinedBehaviorSanitizer.rst | 6 ++++ clang/docs/UsersManual.rst | 8 +++++ clang/include/clang/Basic/CodeGenOptions.h | 3 ++ clang/include/clang/Options/Options.td | 6 +++- clang/lib/CodeGen/BackendUtil.cpp | 1 + clang/lib/CodeGen/CGExpr.cpp | 17 ++++++++++ .../DependencyScanning/ModuleDepCollector.cpp | 2 ++ clang/lib/Driver/SanitizerArgs.cpp | 7 ++++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + .../CodeGen/asan-sanitize-compilation-dir.c | 20 ++++++++++++ .../ubsan-sanitize-compilation-dir.cpp | 27 ++++++++++++++++ clang/test/Driver/fsanitize-compilation-dir.c | 13 ++++++++ .../Instrumentation/AddressSanitizer.h | 2 ++ .../Instrumentation/AddressSanitizer.cpp | 32 ++++++++++++++++--- 16 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGen/asan-sanitize-compilation-dir.c create mode 100644 clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp create mode 100644 clang/test/Driver/fsanitize-compilation-dir.c diff --git a/clang/docs/AddressSanitizer.rst b/clang/docs/AddressSanitizer.rst index 80b1cdd95d77a..80144206b2494 100644 --- a/clang/docs/AddressSanitizer.rst +++ b/clang/docs/AddressSanitizer.rst @@ -47,6 +47,11 @@ in error messages add ``-fno-omit-frame-pointer``. To get perfect stack traces you may need to disable inlining (just use ``-O1``) and tail call elimination (``-fno-optimize-sibling-calls``). +To produce reproducible builds, use ``-fsanitize-compilation-dir=<dir>`` (or +``-ffile-compilation-dir=<dir>`` which also sets it for debug info and +coverage) to make absolute paths in ASan metadata relative to the given +directory. See `Remapping source paths`_ for details. + .. code-block:: console % cat example_UseAfterFree.cc @@ -408,6 +413,30 @@ run-time performance, which leads to increased binary size. Using the flag forces all code instrumentation to be outlined, which reduces the size of the generated code, but also reduces the run-time performance. +Remapping source paths +---------------------- + +AddressSanitizer embeds the source file path in global metadata. For +reproducible builds, the option ``-fsanitize-compilation-dir=<dir>`` can be +used to set the compilation directory. Absolute source paths that start with +``<dir>`` are made relative to it. + +The option ``-ffile-compilation-dir=<dir>`` can also be used, which +additionally sets the compilation directory for debug info and coverage +mapping. When both ``-ffile-compilation-dir`` and ``-fsanitize-compilation-dir`` +are specified, the last one on the command line wins for sanitizer metadata. + +Example +^^^^^^^ + +.. code-block:: console + + # Make absolute paths relative to the build directory + $ clang -fsanitize=address -fsanitize-compilation-dir=/build/dir source.c + + # Using -ffile-compilation-dir to also cover debug info and coverage + $ clang -fsanitize=address -ffile-compilation-dir=/home/user/project source.c + Limitations =========== diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9e4a47a5b18fc..b6395c6c9058a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -929,6 +929,11 @@ Sanitizers ---------- - UndefinedBehaviorSanitizer now supports ``__ubsan_default_suppressions``. +- Added ``-fsanitize-compilation-dir=`` to set the compilation directory for + sanitizer metadata (UBSan diagnostics and ASan module names), making + absolute paths relative for reproducible builds. Also implied by + ``-ffile-compilation-dir=``. + Python Binding Changes ---------------------- - Add deprecation warnings to ``CompletionChunk.isKind...`` methods. diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 3ff1a77e33a6c..4d5b760365a7d 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -522,6 +522,10 @@ information. If ``N`` is positive, file information emitted by UndefinedBehaviorSanitizer will drop the first ``N`` components from the file path. If ``N`` is negative, the last ``N`` components will be kept. +Alternatively, ``-fsanitize-compilation-dir=<dir>`` (or +``-ffile-compilation-dir=<dir>``) can be used to set the compilation directory, +making absolute paths relative to it. This is useful for reproducible builds. + Example ------- @@ -532,6 +536,8 @@ For a file called ``/code/library/file.cpp``, here is what would be emitted: * ``-fsanitize-undefined-strip-path-components=2``: ``library/file.cpp`` * ``-fsanitize-undefined-strip-path-components=-1``: ``file.cpp`` * ``-fsanitize-undefined-strip-path-components=-2``: ``library/file.cpp`` +* ``-fsanitize-compilation-dir=/code``: ``library/file.cpp`` +* ``-fsanitize-compilation-dir=/code/library``: ``file.cpp`` More Information ================ diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 3392a210f0bb0..c6f25a34c06d7 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2277,6 +2277,14 @@ are listed below. See :doc: `AddressSanitizer` for more details. +.. option:: -fsanitize-compilation-dir=<dir> + + Set the compilation directory for sanitizer metadata. Absolute source paths + that start with the given directory are made relative to it, affecting + UBSan diagnostic source locations and ASan module names. This can be used + to achieve reproducible builds regardless of the build directory. Also + implied by ``-ffile-compilation-dir=``. + .. option:: -f[no-]sanitize-type-outline-instrumentation Controls how type sanitizer code is generated. If enabled will always use diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index e43112b4bb98b..aaacca4c5190c 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -260,6 +260,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The string to embed in coverage mapping as the current working directory. std::string CoverageCompilationDir; + /// The compilation directory to use for sanitizer metadata. + std::string SanitizeCompilationDir; + /// The string to embed in the debug information for the compile unit, if /// non-empty. std::string DwarfDebugFlags; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 8451a3698ef17..989a86f84728a 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -1811,9 +1811,13 @@ def fcoverage_compilation_dir_EQ : Joined<["-"], "fcoverage-compilation-dir=">, Group<f_Group>, Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption]>, HelpText<"The compilation directory to embed in the coverage mapping.">, MarshallingInfoString<CodeGenOpts<"CoverageCompilationDir">>; +def fsanitize_compilation_dir_EQ : Joined<["-"], "fsanitize-compilation-dir=">, + Group<f_Group>, Visibility<[ClangOption, CC1Option]>, + HelpText<"The compilation directory to use for sanitizer metadata.">, + MarshallingInfoString<CodeGenOpts<"SanitizeCompilationDir">>; def ffile_compilation_dir_EQ : Joined<["-"], "ffile-compilation-dir=">, Group<f_Group>, Visibility<[ClangOption, CLOption, DXCOption]>, - HelpText<"The compilation directory to embed in the debug info and coverage mapping.">; + HelpText<"The compilation directory to embed in the debug info, coverage mapping, and sanitizer metadata.">; defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling", CodeGenOpts<"DebugInfoForProfiling">, DefaultFalse, PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index a46a25c4492f2..bb8218af31e92 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -750,6 +750,7 @@ static void addSanitizers(const Triple &TargetTriple, Opts.Recover = CodeGenOpts.SanitizeRecover.has(Mask); Opts.UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope; Opts.UseAfterReturn = CodeGenOpts.getSanitizeAddressUseAfterReturn(); + Opts.CompilationDir = CodeGenOpts.SanitizeCompilationDir; MPM.addPass(AddressSanitizerPass(Opts, UseGlobalGC, UseOdrIndicator, DestructorKind)); } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 325902f2127bc..c3bea476732d7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -49,6 +49,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/xxhash.h" @@ -4050,6 +4051,22 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) { if (PLoc.isValid()) { StringRef FilenameString = PLoc.getFilename(); + // If a sanitize compilation dir is set, make absolute paths relative to it. + llvm::SmallString<256> FileBuf(FilenameString); + if (!CGM.getCodeGenOpts().SanitizeCompilationDir.empty() && + llvm::sys::path::is_absolute(FilenameString)) { + llvm::SmallString<256> CompDir( + CGM.getCodeGenOpts().SanitizeCompilationDir); + if (!llvm::sys::path::is_absolute(CompDir)) + llvm::sys::fs::make_absolute(CompDir); + llvm::sys::path::remove_dots(CompDir, /*remove_dot_dot=*/true); + // Ensure trailing separator so "/foo" doesn't match "/foobar/x.c". + if (!CompDir.empty() && !llvm::sys::path::is_separator(CompDir.back())) + CompDir += llvm::sys::path::get_separator(); + if (llvm::sys::path::replace_path_prefix(FileBuf, CompDir, "")) + FilenameString = FileBuf; + } + int PathComponentsToStrip = CGM.getCodeGenOpts().EmitCheckPathComponentsToStrip; if (PathComponentsToStrip < 0) { diff --git a/clang/lib/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/DependencyScanning/ModuleDepCollector.cpp index f9fe50564a5ae..24ce027a8004f 100644 --- a/clang/lib/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/DependencyScanning/ModuleDepCollector.cpp @@ -136,6 +136,7 @@ static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) { BuildInvocation.getMutFileSystemOpts().WorkingDir.clear(); BuildInvocation.getMutCodeGenOpts().DebugCompilationDir.clear(); BuildInvocation.getMutCodeGenOpts().CoverageCompilationDir.clear(); + BuildInvocation.getMutCodeGenOpts().SanitizeCompilationDir.clear(); } static std::vector<std::string> splitString(std::string S, char Separator) { @@ -185,6 +186,7 @@ void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction, (ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) { CGOpts.DebugCompilationDir.clear(); CGOpts.CoverageCompilationDir.clear(); + CGOpts.SanitizeCompilationDir.clear(); CGOpts.CoverageDataFile.clear(); CGOpts.CoverageNotesFile.clear(); CGOpts.ProfileInstrumentUsePath.clear(); diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 31660dd29407c..b80f90b2909a0 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1697,6 +1697,13 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, if (Sanitizers.has(SanitizerKind::MemtagStack) && !hasTargetFeatureMTE(CmdArgs)) TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature); + + // Add sanitize compilation dir. + if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, + options::OPT_fsanitize_compilation_dir_EQ)) { + CmdArgs.push_back(Args.MakeArgString("-fsanitize-compilation-dir=" + + Twine(A->getValue()))); + } } SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 9fc695a74a3c7..384dc6482ae5c 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -5396,6 +5396,7 @@ void CompilerInvocationBase::visitPathsImpl( auto &CodeGenOpts = *this->CodeGenOpts; RETURN_IF(CodeGenOpts.DebugCompilationDir); RETURN_IF(CodeGenOpts.CoverageCompilationDir); + RETURN_IF(CodeGenOpts.SanitizeCompilationDir); // Sanitizer options. RETURN_IF_MANY(LangOpts->NoSanitizeFiles); diff --git a/clang/test/CodeGen/asan-sanitize-compilation-dir.c b/clang/test/CodeGen/asan-sanitize-compilation-dir.c new file mode 100644 index 0000000000000..c173c74640fae --- /dev/null +++ b/clang/test/CodeGen/asan-sanitize-compilation-dir.c @@ -0,0 +1,20 @@ +// Verify that -fsanitize-compilation-dir makes absolute filenames relative +// in the ASan module name embedded in instrumented code. + +// RUN: mkdir -p %t.dir/sub +// RUN: cp %s %t.dir/sub/test.c +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-DEFAULT %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=%t.dir/ %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=%t.dir %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s +// RUN: cd %t.dir && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s +// RUN: cd %t.dir/sub && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=.. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s + +// Verify that a partial prefix match does not strip (e.g. /tmp/dir vs /tmp/directory). +// RUN: mkdir -p %t.directory +// RUN: cp %s %t.directory/test.c +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=%t.dir %t.directory/test.c -o - | FileCheck -check-prefix=CHECK-NO-FALSE-MATCH %s + +// CHECK-DEFAULT: @___asan_gen_module = private constant [{{.*}} x i8] c"{{.+}}test.c\00" +// CHECK-STRIPPED: @___asan_gen_module = private constant [{{.*}} x i8] c"sub{{.}}test.c\00" +// CHECK-NO-FALSE-MATCH: @___asan_gen_module = private constant [{{.*}} x i8] c"{{.+}}directory{{.}}test.c\00" +int x; diff --git a/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp b/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp new file mode 100644 index 0000000000000..0dcd65a8664aa --- /dev/null +++ b/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp @@ -0,0 +1,27 @@ +// Verify that -fsanitize-compilation-dir makes absolute filenames relative +// in UBSan check metadata. +// +// We use -fsanitize=unreachable (one of the checks under -fsanitize=undefined) +// rather than -fsanitize=undefined because the latter is a driver-level umbrella +// flag not accepted by cc1. Any individual sanitizer check exercises the same +// EmitCheckSourceLocation path. + +// RUN: mkdir -p %t.dir/sub +// RUN: cp %s %t.dir/sub/test.c +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-DEFAULT %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=%t.dir/ %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=%t.dir %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s +// RUN: cd %t.dir && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s +// RUN: cd %t.dir/sub && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=.. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s + +// Verify that a partial prefix match does not strip. +// RUN: mkdir -p %t.directory +// RUN: cp %s %t.directory/test.c +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=%t.dir %t.directory/test.c -o - | FileCheck -check-prefix=CHECK-NO-FALSE-MATCH %s + +// CHECK-DEFAULT: @{{.*}} = private unnamed_addr constant [{{.*}} x i8] c"{{.+}}test.c\00" +// CHECK-STRIPPED: @{{.*}} = private unnamed_addr constant [{{.*}} x i8] c"sub{{.}}test.c\00" +// CHECK-NO-FALSE-MATCH: @{{.*}} = private unnamed_addr constant [{{.*}} x i8] c"{{.+}}directory{{.}}test.c\00" +void f(void) { + __builtin_unreachable(); +} diff --git a/clang/test/Driver/fsanitize-compilation-dir.c b/clang/test/Driver/fsanitize-compilation-dir.c new file mode 100644 index 0000000000000..6037f55e58d2f --- /dev/null +++ b/clang/test/Driver/fsanitize-compilation-dir.c @@ -0,0 +1,13 @@ +// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=SANITIZE +// RUN: %clang -### -fsanitize=undefined -fsanitize-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=SANITIZE +// RUN: %clang -### -fsanitize=address -ffile-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=FILE +// RUN: %clang -### -fsanitize=undefined -ffile-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=FILE + +// Verify that -fsanitize-compilation-dir wins over -ffile-compilation-dir when it comes last. +// RUN: %clang -### -fsanitize=address -ffile-compilation-dir=/bar -fsanitize-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=OVERRIDE +// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=/foo -ffile-compilation-dir=/bar %s 2>&1 | FileCheck %s --check-prefix=OVERRIDE-FILE + +// SANITIZE: "-fsanitize-compilation-dir=/foo" +// FILE: "-fsanitize-compilation-dir=/foo" +// OVERRIDE: "-fsanitize-compilation-dir=/foo" +// OVERRIDE-FILE: "-fsanitize-compilation-dir=/bar" diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h index 781b88175f562..aa75976a4c06f 100644 --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h @@ -16,6 +16,7 @@ #include "llvm/IR/PassManager.h" #include "llvm/Support/Compiler.h" #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" +#include <string> namespace llvm { class Module; @@ -30,6 +31,7 @@ struct AddressSanitizerOptions { int InstrumentationWithCallsThreshold = 7000; uint32_t MaxInlinePoisoningSize = 64; bool InsertVersionCheck = true; + std::string CompilationDir; }; /// Public interface to the address sanitizer module pass for instrumenting code diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index e75b5ccdf612c..6a985f8923074 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -70,8 +70,10 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ModRef.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h" @@ -961,7 +963,8 @@ class ModuleAddressSanitizer { bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true, bool UseOdrIndicator = true, AsanDtorKind DestructorKind = AsanDtorKind::Global, - AsanCtorKind ConstructorKind = AsanCtorKind::Global) + AsanCtorKind ConstructorKind = AsanCtorKind::Global, + StringRef CompilationDir = "") : M(M), Inserter(M), CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan : CompileKernel), @@ -988,7 +991,8 @@ class ModuleAddressSanitizer { DestructorKind(DestructorKind), ConstructorKind(ClConstructorKind.getNumOccurrences() > 0 ? ClConstructorKind - : ConstructorKind) { + : ConstructorKind), + CompilationDir(CompilationDir) { C = &(M.getContext()); int LongSize = M.getDataLayout().getPointerSizeInBits(); IntptrTy = Type::getIntNTy(*C, LongSize); @@ -1069,6 +1073,7 @@ class ModuleAddressSanitizer { Function *AsanCtorFunction = nullptr; Function *AsanDtorFunction = nullptr; GlobalVariable *ModuleName = nullptr; + std::string CompilationDir; }; // Stack poisoning does not play well with exception handling. @@ -1339,7 +1344,8 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M, ModuleAddressSanitizer ModuleSanitizer( M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover, - UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind); + UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind, + Options.CompilationDir); bool Modified = false; auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); const StackSafetyGlobalInfo *const SSGI = @@ -2831,8 +2837,26 @@ GlobalVariable *ModuleAddressSanitizer::getOrCreateModuleName() { if (!ModuleName) { // We shouldn't merge same module names, as this string serves as unique // module ID in runtime. + std::string ModuleNameStr = M.getModuleIdentifier(); + + // If a compilation dir is set, make absolute paths relative to it. + if (!CompilationDir.empty()) { + SmallString<256> Path(ModuleNameStr); + if (sys::path::is_absolute(Path)) { + SmallString<256> CompDir(CompilationDir); + if (!sys::path::is_absolute(CompDir)) + sys::fs::make_absolute(CompDir); + sys::path::remove_dots(CompDir, /*remove_dot_dot=*/true); + // Ensure trailing separator so "/foo" doesn't match "/foobar/x.c". + if (!CompDir.empty() && !sys::path::is_separator(CompDir.back())) + CompDir += sys::path::get_separator(); + if (sys::path::replace_path_prefix(Path, CompDir, "")) + ModuleNameStr = std::string(Path); + } + } + ModuleName = - createPrivateGlobalForString(M, M.getModuleIdentifier(), + createPrivateGlobalForString(M, ModuleNameStr, /*AllowMerging*/ false, genName("module")); } return ModuleName; From 231577450c51f914b0ed1b84cf1054baea439ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Fri, 12 Jun 2026 14:38:33 +0200 Subject: [PATCH 2/3] review fixup: store SanitizeCompilationDir as an absolute path in Driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Svensson <[email protected]> --- clang/lib/CodeGen/CGExpr.cpp | 6 +----- clang/lib/Driver/SanitizerArgs.cpp | 9 +++++++-- clang/test/CodeGen/asan-sanitize-compilation-dir.c | 2 -- clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp | 2 -- .../test/Driver/fsanitize-compilation-dir-canonicalize.c | 9 +++++++++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | 6 +----- 6 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 clang/test/Driver/fsanitize-compilation-dir-canonicalize.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index c3bea476732d7..bf55a1e4918d1 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -49,7 +49,6 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/xxhash.h" @@ -4057,11 +4056,8 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) { llvm::sys::path::is_absolute(FilenameString)) { llvm::SmallString<256> CompDir( CGM.getCodeGenOpts().SanitizeCompilationDir); - if (!llvm::sys::path::is_absolute(CompDir)) - llvm::sys::fs::make_absolute(CompDir); - llvm::sys::path::remove_dots(CompDir, /*remove_dot_dot=*/true); // Ensure trailing separator so "/foo" doesn't match "/foobar/x.c". - if (!CompDir.empty() && !llvm::sys::path::is_separator(CompDir.back())) + if (!llvm::sys::path::is_separator(CompDir.back())) CompDir += llvm::sys::path::get_separator(); if (llvm::sys::path::replace_path_prefix(FileBuf, CompDir, "")) FilenameString = FileBuf; diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index b80f90b2909a0..e037f7352ee91 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1701,8 +1701,13 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, // Add sanitize compilation dir. if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, options::OPT_fsanitize_compilation_dir_EQ)) { - CmdArgs.push_back(Args.MakeArgString("-fsanitize-compilation-dir=" + - Twine(A->getValue()))); + SmallString<256> Dir(A->getValue()); + if (!llvm::sys::path::is_absolute(Dir)) + if (auto CWD = TC.getDriver().getVFS().getCurrentWorkingDirectory()) + llvm::sys::path::make_absolute(*CWD, Dir); + llvm::sys::path::remove_dots(Dir, /*remove_dot_dot=*/true); + CmdArgs.push_back( + Args.MakeArgString("-fsanitize-compilation-dir=" + Twine(Dir))); } } diff --git a/clang/test/CodeGen/asan-sanitize-compilation-dir.c b/clang/test/CodeGen/asan-sanitize-compilation-dir.c index c173c74640fae..6166f0a969b34 100644 --- a/clang/test/CodeGen/asan-sanitize-compilation-dir.c +++ b/clang/test/CodeGen/asan-sanitize-compilation-dir.c @@ -6,8 +6,6 @@ // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-DEFAULT %s // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=%t.dir/ %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=%t.dir %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s -// RUN: cd %t.dir && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s -// RUN: cd %t.dir/sub && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=address -fsanitize-compilation-dir=.. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s // Verify that a partial prefix match does not strip (e.g. /tmp/dir vs /tmp/directory). // RUN: mkdir -p %t.directory diff --git a/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp b/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp index 0dcd65a8664aa..4b636db5217c4 100644 --- a/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp +++ b/clang/test/CodeGen/ubsan-sanitize-compilation-dir.cpp @@ -11,8 +11,6 @@ // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-DEFAULT %s // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=%t.dir/ %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=%t.dir %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s -// RUN: cd %t.dir && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s -// RUN: cd %t.dir/sub && %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -fsanitize=unreachable -fsanitize-compilation-dir=.. %t.dir/sub/test.c -o - | FileCheck -check-prefix=CHECK-STRIPPED %s // Verify that a partial prefix match does not strip. // RUN: mkdir -p %t.directory diff --git a/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c b/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c new file mode 100644 index 0000000000000..6cfca911fa9c9 --- /dev/null +++ b/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c @@ -0,0 +1,9 @@ +// UNSUPPORTED: system-windows +// Test uses Unix absolute paths. +// Verify that relative paths are made absolute and dots are removed. +// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=. %s 2>&1 | FileCheck %s --check-prefix=RELATIVE +// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=/foo/bar/.. %s 2>&1 | FileCheck %s --check-prefix=DOTS + +// RELATIVE-NOT: "-fsanitize-compilation-dir=." +// RELATIVE: "-fsanitize-compilation-dir={{/[^"]+}}" +// DOTS: "-fsanitize-compilation-dir=/foo" diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 6a985f8923074..d46a3d003cde9 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -70,7 +70,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ModRef.h" #include "llvm/Support/Path.h" @@ -2844,11 +2843,8 @@ GlobalVariable *ModuleAddressSanitizer::getOrCreateModuleName() { SmallString<256> Path(ModuleNameStr); if (sys::path::is_absolute(Path)) { SmallString<256> CompDir(CompilationDir); - if (!sys::path::is_absolute(CompDir)) - sys::fs::make_absolute(CompDir); - sys::path::remove_dots(CompDir, /*remove_dot_dot=*/true); // Ensure trailing separator so "/foo" doesn't match "/foobar/x.c". - if (!CompDir.empty() && !sys::path::is_separator(CompDir.back())) + if (!sys::path::is_separator(CompDir.back())) CompDir += sys::path::get_separator(); if (sys::path::replace_path_prefix(Path, CompDir, "")) ModuleNameStr = std::string(Path); From fb2c022b5644e8558267afaf81a1262453f0c0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Wed, 24 Jun 2026 00:00:11 +0200 Subject: [PATCH 3/3] fixup: Only use -ffile-compilation-dir= and drop user-facing -fsanitize-compilation-dir= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Svensson <[email protected]> --- clang/docs/AddressSanitizer.rst | 20 ++++++------------- clang/docs/ReleaseNotes.rst | 7 +++---- clang/docs/UndefinedBehaviorSanitizer.rst | 10 +++++----- clang/docs/UsersManual.rst | 8 -------- clang/include/clang/Options/Options.td | 2 +- clang/lib/Driver/SanitizerArgs.cpp | 12 ----------- clang/lib/Driver/ToolChains/Clang.cpp | 11 ++++++++++ .../fsanitize-compilation-dir-canonicalize.c | 4 ++-- clang/test/Driver/fsanitize-compilation-dir.c | 10 +--------- 9 files changed, 29 insertions(+), 55 deletions(-) diff --git a/clang/docs/AddressSanitizer.rst b/clang/docs/AddressSanitizer.rst index 80144206b2494..99d34c5899a25 100644 --- a/clang/docs/AddressSanitizer.rst +++ b/clang/docs/AddressSanitizer.rst @@ -47,10 +47,9 @@ in error messages add ``-fno-omit-frame-pointer``. To get perfect stack traces you may need to disable inlining (just use ``-O1``) and tail call elimination (``-fno-optimize-sibling-calls``). -To produce reproducible builds, use ``-fsanitize-compilation-dir=<dir>`` (or -``-ffile-compilation-dir=<dir>`` which also sets it for debug info and -coverage) to make absolute paths in ASan metadata relative to the given -directory. See `Remapping source paths`_ for details. +To produce reproducible builds, use ``-ffile-compilation-dir=<dir>`` to make +absolute paths in ASan metadata relative to the given directory (this also +covers debug info and coverage). See `Remapping source paths`_ for details. .. code-block:: console @@ -417,14 +416,10 @@ Remapping source paths ---------------------- AddressSanitizer embeds the source file path in global metadata. For -reproducible builds, the option ``-fsanitize-compilation-dir=<dir>`` can be +reproducible builds, the option ``-ffile-compilation-dir=<dir>`` can be used to set the compilation directory. Absolute source paths that start with -``<dir>`` are made relative to it. - -The option ``-ffile-compilation-dir=<dir>`` can also be used, which -additionally sets the compilation directory for debug info and coverage -mapping. When both ``-ffile-compilation-dir`` and ``-fsanitize-compilation-dir`` -are specified, the last one on the command line wins for sanitizer metadata. +``<dir>`` are made relative to it. This option also sets the compilation +directory for debug info and coverage mapping. Example ^^^^^^^ @@ -432,9 +427,6 @@ Example .. code-block:: console # Make absolute paths relative to the build directory - $ clang -fsanitize=address -fsanitize-compilation-dir=/build/dir source.c - - # Using -ffile-compilation-dir to also cover debug info and coverage $ clang -fsanitize=address -ffile-compilation-dir=/home/user/project source.c Limitations diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b6395c6c9058a..4d7d8c0996110 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -929,10 +929,9 @@ Sanitizers ---------- - UndefinedBehaviorSanitizer now supports ``__ubsan_default_suppressions``. -- Added ``-fsanitize-compilation-dir=`` to set the compilation directory for - sanitizer metadata (UBSan diagnostics and ASan module names), making - absolute paths relative for reproducible builds. Also implied by - ``-ffile-compilation-dir=``. +- ``-ffile-compilation-dir=`` now also makes absolute paths relative in + sanitizer metadata (UBSan diagnostics and ASan module names) for + reproducible builds. Python Binding Changes ---------------------- diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 4d5b760365a7d..cb68ff49eb993 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -522,9 +522,9 @@ information. If ``N`` is positive, file information emitted by UndefinedBehaviorSanitizer will drop the first ``N`` components from the file path. If ``N`` is negative, the last ``N`` components will be kept. -Alternatively, ``-fsanitize-compilation-dir=<dir>`` (or -``-ffile-compilation-dir=<dir>``) can be used to set the compilation directory, -making absolute paths relative to it. This is useful for reproducible builds. +Alternatively, ``-ffile-compilation-dir=<dir>`` can be used to set the +compilation directory, making absolute paths relative to it. This is useful +for reproducible builds. Example ------- @@ -536,8 +536,8 @@ For a file called ``/code/library/file.cpp``, here is what would be emitted: * ``-fsanitize-undefined-strip-path-components=2``: ``library/file.cpp`` * ``-fsanitize-undefined-strip-path-components=-1``: ``file.cpp`` * ``-fsanitize-undefined-strip-path-components=-2``: ``library/file.cpp`` -* ``-fsanitize-compilation-dir=/code``: ``library/file.cpp`` -* ``-fsanitize-compilation-dir=/code/library``: ``file.cpp`` +* ``-ffile-compilation-dir=/code``: ``library/file.cpp`` +* ``-ffile-compilation-dir=/code/library``: ``file.cpp`` More Information ================ diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index c6f25a34c06d7..3392a210f0bb0 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2277,14 +2277,6 @@ are listed below. See :doc: `AddressSanitizer` for more details. -.. option:: -fsanitize-compilation-dir=<dir> - - Set the compilation directory for sanitizer metadata. Absolute source paths - that start with the given directory are made relative to it, affecting - UBSan diagnostic source locations and ASan module names. This can be used - to achieve reproducible builds regardless of the build directory. Also - implied by ``-ffile-compilation-dir=``. - .. option:: -f[no-]sanitize-type-outline-instrumentation Controls how type sanitizer code is generated. If enabled will always use diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 989a86f84728a..a5e225887b50d 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -1812,7 +1812,7 @@ def fcoverage_compilation_dir_EQ : Joined<["-"], "fcoverage-compilation-dir=">, HelpText<"The compilation directory to embed in the coverage mapping.">, MarshallingInfoString<CodeGenOpts<"CoverageCompilationDir">>; def fsanitize_compilation_dir_EQ : Joined<["-"], "fsanitize-compilation-dir=">, - Group<f_Group>, Visibility<[ClangOption, CC1Option]>, + Group<f_Group>, Visibility<[CC1Option]>, HelpText<"The compilation directory to use for sanitizer metadata.">, MarshallingInfoString<CodeGenOpts<"SanitizeCompilationDir">>; def ffile_compilation_dir_EQ : Joined<["-"], "ffile-compilation-dir=">, Group<f_Group>, diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index e037f7352ee91..31660dd29407c 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1697,18 +1697,6 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, if (Sanitizers.has(SanitizerKind::MemtagStack) && !hasTargetFeatureMTE(CmdArgs)) TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature); - - // Add sanitize compilation dir. - if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fsanitize_compilation_dir_EQ)) { - SmallString<256> Dir(A->getValue()); - if (!llvm::sys::path::is_absolute(Dir)) - if (auto CWD = TC.getDriver().getVFS().getCurrentWorkingDirectory()) - llvm::sys::path::make_absolute(*CWD, Dir); - llvm::sys::path::remove_dots(Dir, /*remove_dot_dot=*/true); - CmdArgs.push_back( - Args.MakeArgString("-fsanitize-compilation-dir=" + Twine(Dir))); - } } SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 42a09372f5597..e5c9018ac168d 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8035,6 +8035,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // features enabled through -Xclang -target-feature flags. SanitizeArgs.addArgs(TC, Args, CmdArgs, InputType); + // Add -fsanitize-compilation-dir, implied by -ffile-compilation-dir. + if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ)) { + SmallString<256> Dir(A->getValue()); + if (!llvm::sys::path::is_absolute(Dir)) + if (auto CWD = D.getVFS().getCurrentWorkingDirectory()) + llvm::sys::path::make_absolute(*CWD, Dir); + llvm::sys::path::remove_dots(Dir, /*remove_dot_dot=*/true); + CmdArgs.push_back( + Args.MakeArgString("-fsanitize-compilation-dir=" + Twine(Dir))); + } + Args.AddLastArg(CmdArgs, options::OPT_falloc_token_max_EQ); #if CLANG_ENABLE_CIR diff --git a/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c b/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c index 6cfca911fa9c9..3e7285560effa 100644 --- a/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c +++ b/clang/test/Driver/fsanitize-compilation-dir-canonicalize.c @@ -1,8 +1,8 @@ // UNSUPPORTED: system-windows // Test uses Unix absolute paths. // Verify that relative paths are made absolute and dots are removed. -// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=. %s 2>&1 | FileCheck %s --check-prefix=RELATIVE -// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=/foo/bar/.. %s 2>&1 | FileCheck %s --check-prefix=DOTS +// RUN: %clang -### -fsanitize=address -ffile-compilation-dir=. %s 2>&1 | FileCheck %s --check-prefix=RELATIVE +// RUN: %clang -### -fsanitize=address -ffile-compilation-dir=/foo/bar/.. %s 2>&1 | FileCheck %s --check-prefix=DOTS // RELATIVE-NOT: "-fsanitize-compilation-dir=." // RELATIVE: "-fsanitize-compilation-dir={{/[^"]+}}" diff --git a/clang/test/Driver/fsanitize-compilation-dir.c b/clang/test/Driver/fsanitize-compilation-dir.c index 6037f55e58d2f..5434d0d8a097a 100644 --- a/clang/test/Driver/fsanitize-compilation-dir.c +++ b/clang/test/Driver/fsanitize-compilation-dir.c @@ -1,13 +1,5 @@ -// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=SANITIZE -// RUN: %clang -### -fsanitize=undefined -fsanitize-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=SANITIZE +// Verify that -ffile-compilation-dir= emits -fsanitize-compilation-dir= to cc1. // RUN: %clang -### -fsanitize=address -ffile-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=FILE // RUN: %clang -### -fsanitize=undefined -ffile-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=FILE -// Verify that -fsanitize-compilation-dir wins over -ffile-compilation-dir when it comes last. -// RUN: %clang -### -fsanitize=address -ffile-compilation-dir=/bar -fsanitize-compilation-dir=/foo %s 2>&1 | FileCheck %s --check-prefix=OVERRIDE -// RUN: %clang -### -fsanitize=address -fsanitize-compilation-dir=/foo -ffile-compilation-dir=/bar %s 2>&1 | FileCheck %s --check-prefix=OVERRIDE-FILE - -// SANITIZE: "-fsanitize-compilation-dir=/foo" // FILE: "-fsanitize-compilation-dir=/foo" -// OVERRIDE: "-fsanitize-compilation-dir=/foo" -// OVERRIDE-FILE: "-fsanitize-compilation-dir=/bar" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
