From 2b68ec15d8a555196220dc29bd9cc31368241147 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 22 Jul 2025 14:17:16 -0700 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6 --- clang/lib/CodeGen/CGDebugInfo.cpp | 14 ++----- clang/lib/CodeGen/CGDebugInfo.h | 1 - clang/lib/CodeGen/CoverageMappingGen.cpp | 7 +--- clang/lib/Driver/ToolChains/Clang.cpp | 37 ++++++++++--------- .../DependencyScanning/ModuleDepCollector.cpp | 26 +------------ clang/test/ClangScanDeps/modules-debug-dir.c | 10 +++-- clang/test/CodeGen/debug-info-abspath.c | 13 +------ .../test/CodeGen/debug-info-compilation-dir.c | 7 ++++ clang/test/CodeGen/debug-prefix-map.c | 5 ++- .../debug-info-function-context.cpp | 2 +- clang/test/CodeGenCXX/difile_entry.cpp | 2 +- clang/test/PCH/debug-info-pch-path.c | 3 +- clang/test/Profile/coverage-prefix-map.c | 2 +- .../unittests/Frontend/CodeGenActionTest.cpp | 36 ------------------ 14 files changed, 51 insertions(+), 114 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index a371b6755f74d..fcad19218502a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -643,16 +643,7 @@ unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) { } StringRef CGDebugInfo::getCurrentDirname() { - if (!CGM.getCodeGenOpts().DebugCompilationDir.empty()) - return CGM.getCodeGenOpts().DebugCompilationDir; - - if (!CWDName.empty()) - return CWDName; - llvm::ErrorOr CWD = - CGM.getFileSystem()->getCurrentWorkingDirectory(); - if (!CWD) - return StringRef(); - return CWDName = internString(*CWD); + return CGM.getCodeGenOpts().DebugCompilationDir; } void CGDebugInfo::CreateCompileUnit() { @@ -3246,6 +3237,9 @@ llvm::DIModule *CGDebugInfo::getOrCreateModuleRef(ASTSourceDescriptor Mod, std::string Remapped = remapDIPath(Path); StringRef Relative(Remapped); StringRef CompDir = TheCU->getDirectory(); + if (CompDir.empty()) + return Remapped; + if (Relative.consume_front(CompDir)) Relative.consume_front(llvm::sys::path::get_separator()); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 411b2e718da30..497d3a6ab17b1 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -158,7 +158,6 @@ class CGDebugInfo { /// This is a storage for names that are constructed on demand. For /// example, C++ destructors, C++ operators etc.. llvm::BumpPtrAllocator DebugInfoNames; - StringRef CWDName; llvm::DenseMap DIFileCache; llvm::DenseMap SPCache; diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 4aafac349e3e9..38aaceb6c462d 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -2449,12 +2449,7 @@ CoverageMappingModuleGen::CoverageMappingModuleGen( : CGM(CGM), SourceInfo(SourceInfo) {} std::string CoverageMappingModuleGen::getCurrentDirname() { - if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty()) - return CGM.getCodeGenOpts().CoverageCompilationDir; - - SmallString<256> CWD; - llvm::sys::fs::current_path(CWD); - return CWD.str().str(); + return CGM.getCodeGenOpts().CoverageCompilationDir; } std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1fc7002a3a186..afeea6da5fa89 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -242,17 +242,18 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC, static const char *addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs, const llvm::vfs::FileSystem &VFS) { + std::string DebugCompDir; if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fdebug_compilation_dir_EQ)) { - if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) - CmdArgs.push_back(Args.MakeArgString(Twine("-fdebug-compilation-dir=") + - A->getValue())); + options::OPT_fdebug_compilation_dir_EQ)) + DebugCompDir = A->getValue(); + + if (DebugCompDir.empty()) { + if (llvm::ErrorOr CWD = VFS.getCurrentWorkingDirectory()) + DebugCompDir = std::move(*CWD); else - A->render(Args, CmdArgs); - } else if (llvm::ErrorOr CWD = - VFS.getCurrentWorkingDirectory()) { - CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD)); + return nullptr; } + CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + DebugCompDir)); StringRef Path(CmdArgs.back()); return Path.substr(Path.find('=') + 1).data(); } @@ -541,17 +542,17 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, CmdArgs.push_back("-fcoverage-mcdc"); } + StringRef CoverageCompDir; if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fcoverage_compilation_dir_EQ)) { - if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("-fcoverage-compilation-dir=") + A->getValue())); - else - A->render(Args, CmdArgs); - } else if (llvm::ErrorOr CWD = - D.getVFS().getCurrentWorkingDirectory()) { - CmdArgs.push_back(Args.MakeArgString("-fcoverage-compilation-dir=" + *CWD)); - } + options::OPT_fcoverage_compilation_dir_EQ)) + CoverageCompDir = A->getValue(); + if (CoverageCompDir.empty()) { + if (auto CWD = D.getVFS().getCurrentWorkingDirectory()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + *CWD)); + } else + CmdArgs.push_back(Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + + CoverageCompDir)); if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 37f8b945d785e..d67178c153e88 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -144,30 +144,8 @@ static void optimizeDiagnosticOpts(DiagnosticOptions &Opts, static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) { BuildInvocation.getMutFileSystemOpts().WorkingDir.clear(); - if (BuildInvocation.getCodeGenOpts().DwarfVersion) { - // It is necessary to explicitly set the DebugCompilationDir - // to a common directory (e.g. root) if IgnoreCWD is true. - // When IgnoreCWD is true, the module's content should not - // depend on the current working directory. However, if dwarf - // information is needed (when CGOpts.DwarfVersion is - // non-zero), then CGOpts.DebugCompilationDir must be - // populated, because otherwise the current working directory - // will be automatically embedded in the dwarf information in - // the pcm, contradicting the assumption that it is safe to - // ignore the CWD. Thus in such cases, - // CGOpts.DebugCompilationDir is explicitly set to a common - // directory. - // FIXME: It is still excessive to create a copy of - // CodeGenOpts for each module. Since we do not modify the - // CodeGenOpts otherwise per module, the following code - // ends up generating identical CodeGenOpts for each module - // with DebugCompilationDir pointing to the root directory. - // We can optimize this away by creating a _single_ copy of - // CodeGenOpts whose DebugCompilationDir points to the root - // directory and reuse it across modules. - BuildInvocation.getMutCodeGenOpts().DebugCompilationDir = - llvm::sys::path::root_path(CWD); - } + BuildInvocation.getMutCodeGenOpts().DebugCompilationDir.clear(); + BuildInvocation.getMutCodeGenOpts().CoverageCompilationDir.clear(); } static std::vector splitString(std::string S, char Separator) { diff --git a/clang/test/ClangScanDeps/modules-debug-dir.c b/clang/test/ClangScanDeps/modules-debug-dir.c index c4fb4982ed791..e2a0e1b7a5b01 100644 --- a/clang/test/ClangScanDeps/modules-debug-dir.c +++ b/clang/test/ClangScanDeps/modules-debug-dir.c @@ -1,5 +1,3 @@ -// REQUIRES: shell - // RUN: rm -rf %t // RUN: split-file %s %t // RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json @@ -7,6 +5,12 @@ // RUN: experimental-full -optimize-args=all > %t/result.json // RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck %s +// RUN: %deps-to-rsp %t/result.json --module-name=mod > %t/mod.rsp +// RUN: %clang @%t/mod.rsp -o %t/mod.pcm +// RUN: llvm-dwarfdump --debug-info %t/mod.pcm | FileCheck %s --check-prefix=DWARF +// DWARF: DW_TAG_compile_unit +// DWARF-NOT: DW_AT_comp_dir + //--- cdb.json.in [{ "directory": "DIR", @@ -28,5 +32,5 @@ module mod { // directory when current working directory optimization is in effect. // CHECK: "modules": [ // CHECK: "command-line": [ -// CHECK: "-fdebug-compilation-dir={{\/|.*:(\\)?}}", +// CHECK-NOT: -fdebug-compilation-dir // CHECK: "translation-units": [ diff --git a/clang/test/CodeGen/debug-info-abspath.c b/clang/test/CodeGen/debug-info-abspath.c index b2047a7deb0e0..193a72c0a66fd 100644 --- a/clang/test/CodeGen/debug-info-abspath.c +++ b/clang/test/CodeGen/debug-info-abspath.c @@ -2,20 +2,15 @@ // RUN: cp %s %t/UNIQUEISH_SENTINEL/debug-info-abspath.c // RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: -fdebug-compilation-dir=%t/UNIQUEISH_SENTINEL/debug-info-abspath.c \ // RUN: %t/UNIQUEISH_SENTINEL/debug-info-abspath.c -emit-llvm -o - \ // RUN: | FileCheck %s // RUN: cp %s %t.c // RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: -fdebug-compilation-dir=%t \ // RUN: %t.c -emit-llvm -o - | FileCheck %s --check-prefix=INTREE -// RUN: cd %t/UNIQUEISH_SENTINEL -// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ -// RUN: debug-info-abspath.c -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CURDIR -// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ -// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefix=CURDIR - void foo(void) {} // Since %s is an absolute path, directory should be the common @@ -28,7 +23,3 @@ void foo(void) {} // INTREE: = distinct !DISubprogram({{.*}}![[SPFILE:[0-9]+]] // INTREE: DIFile({{.*}}directory: "{{.+}}CodeGen{{.*}}") - -// CURDIR: = distinct !DICompileUnit({{.*}}file: ![[CUFILE:[0-9]+]] -// CURDIR: ![[CUFILE]] = !DIFile({{.*}}directory: "{{.+}}UNIQUEISH_SENTINEL") - diff --git a/clang/test/CodeGen/debug-info-compilation-dir.c b/clang/test/CodeGen/debug-info-compilation-dir.c index b49a0f5751f8e..5f5542c525495 100644 --- a/clang/test/CodeGen/debug-info-compilation-dir.c +++ b/clang/test/CodeGen/debug-info-compilation-dir.c @@ -7,3 +7,10 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-DIR %s // CHECK-DIR: CodeGen +/// Test path remapping. +// RUN: %clang_cc1 -fdebug-compilation-dir=%S -main-file-name %s -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-ABS %s +// CHECK-ABS: DIFile(filename: "{{.*}}debug-info-compilation-dir.c", directory: "{{.*}}CodeGen") + +// RUN: %clang_cc1 -main-file-name %s -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-NOMAP %s +// CHECK-NOMAP: DIFile(filename: "{{.*}}debug-info-compilation-dir.c", directory: "") + diff --git a/clang/test/CodeGen/debug-prefix-map.c b/clang/test/CodeGen/debug-prefix-map.c index e2421806b055b..e58909f5acaaa 100644 --- a/clang/test/CodeGen/debug-prefix-map.c +++ b/clang/test/CodeGen/debug-prefix-map.c @@ -12,6 +12,7 @@ // RUN: rm -rf %t && mkdir -p %t/a/b && cp %s %t/a/b/c.c // RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -fdebug-prefix-map=%t/a/b=y -fdebug-prefix-map=%t/a=x %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-X // RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -fdebug-prefix-map=%t/a=x -fdebug-prefix-map=%t/a/b=y %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-Y +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -main-file-name %t/a/b/c.c -fdebug-compilation-dir=%t/a -fdebug-prefix-map=%t/a=x -fdebug-prefix-map=%t/a/b=y %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-REMAP-Y #include "Inputs/stdio.h" @@ -26,9 +27,9 @@ void test_rewrite_includes(void) { vprintf("string", argp); } -// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}", // CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}{{.*}}", // CHECK-NO-MAIN-FILE-NAME-SAME: directory: "") +// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}", // CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}Inputs{{/|\\\\}}stdio.h", // CHECK-NO-MAIN-FILE-NAME-SAME: directory: "") // CHECK-NO-MAIN-FILE-NAME-NOT: !DIFile(filename: @@ -54,3 +55,5 @@ void test_rewrite_includes(void) { // CHECK-X: !DIFile(filename: "x{{/|\\\\}}b{{/|\\\\}}c.c", directory: "") // CHECK-Y: !DIFile(filename: "y{{/|\\\\}}c.c", directory: "") + +// CHECK-REMAP-Y: !DIFile(filename: "y{{/|\\\\}}c.c", directory: "x") diff --git a/clang/test/CodeGenCXX/debug-info-function-context.cpp b/clang/test/CodeGenCXX/debug-info-function-context.cpp index 63fdf877fdb7d..29c87b6ec0055 100644 --- a/clang/test/CodeGenCXX/debug-info-function-context.cpp +++ b/clang/test/CodeGenCXX/debug-info-function-context.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-pc-linux-gnu %s \ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-pc-linux-gnu %s -fdebug-compilation-dir=%S \ // RUN: -dwarf-version=5 -main-file-name debug-info-function-context.cpp -o - | FileCheck %s struct C { diff --git a/clang/test/CodeGenCXX/difile_entry.cpp b/clang/test/CodeGenCXX/difile_entry.cpp index 8bf6dc325470b..5fcd56ee3d053 100644 --- a/clang/test/CodeGenCXX/difile_entry.cpp +++ b/clang/test/CodeGenCXX/difile_entry.cpp @@ -3,7 +3,7 @@ /// Test that we canonicalize the DIFile. // RUN: rm -rf %t && mkdir %t && cd %t // RUN: cp %s . -// RUN: %clang_cc1 -triple %itanium_abi_triple -main-file-name difile_entry.cpp -debug-info-kind=limited %t/difile_entry.cpp -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -main-file-name difile_entry.cpp -fdebug-compilation-dir=%t -debug-info-kind=limited %t/difile_entry.cpp -std=c++11 -emit-llvm -o - | FileCheck %s int x(); static int i = x(); diff --git a/clang/test/PCH/debug-info-pch-path.c b/clang/test/PCH/debug-info-pch-path.c index f94d2fa8d09e9..22b367f344204 100644 --- a/clang/test/PCH/debug-info-pch-path.c +++ b/clang/test/PCH/debug-info-pch-path.c @@ -65,7 +65,8 @@ // RUN: %clang_cc1 -debug-info-kind=standalone \ // RUN: -dwarf-ext-refs -fmodule-format=obj \ // RUN: -triple %itanium_abi_triple \ -// RUN: -include-pch %t/prefix.pch %s -emit-llvm -o %t.abs.ll %s +// RUN: -include-pch %t/prefix.pch %s -emit-llvm \ +// RUN: -fdebug-compilation-dir=%t -o %t.abs.ll %s // RUN: cat %t.abs.ll | FileCheck %s --check-prefix=CHECK-ABS // CHECK-ABS: !DICompileUnit diff --git a/clang/test/Profile/coverage-prefix-map.c b/clang/test/Profile/coverage-prefix-map.c index de9e3773f66d2..1cb095f2bdbf6 100644 --- a/clang/test/Profile/coverage-prefix-map.c +++ b/clang/test/Profile/coverage-prefix-map.c @@ -25,7 +25,7 @@ // COVERAGE-PREFIX-MAP-ORDER: @__llvm_coverage_mapping = {{.*"\\02.*newpath.*root.*nested.*coverage-prefix-map\.c}} // Test that last -fcoverage-prefix-map option (-fcoverage-prefix-map=%/t/root=.) is applied. -// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name coverage-prefix-map.c %t/root/nested/coverage-prefix-map.c -fcoverage-prefix-map==newpath -fcoverage-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=COVERAGE-PREFIX-MAP-REORDER %s +// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name coverage-prefix-map.c %t/root/nested/coverage-prefix-map.c -fcoverage-compilation-dir=%t/root -fcoverage-prefix-map==newpath -fcoverage-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=COVERAGE-PREFIX-MAP-REORDER %s // COVERAGE-PREFIX-MAP-REORDER: @__llvm_coverage_mapping = // COVERAGE-PREFIX-MAP-REORDER-NOT: newpath // COVERAGE-PREFIX-MAP-REORDER-SAME: nested{{.*coverage-prefix-map\.c}} diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp index 90818b72cd6e6..b2792c44ba5fe 100644 --- a/clang/unittests/Frontend/CodeGenActionTest.cpp +++ b/clang/unittests/Frontend/CodeGenActionTest.cpp @@ -76,40 +76,4 @@ TEST(CodeGenTest, CodeGenFromIRMemBuffer) { bool Success = Compiler.ExecuteAction(Action); EXPECT_TRUE(Success); } - -TEST(CodeGenTest, DebugInfoCWDCodeGen) { - // Check that debug info is accessing the current working directory from the - // VFS instead of calling \p llvm::sys::fs::current_path() directly. - - auto Sept = llvm::sys::path::get_separator(); - auto VFS = std::make_unique(); - VFS->setCurrentWorkingDirectory( - std::string(llvm::formatv("{0}in-memory-fs-cwd", Sept))); - std::string TestPath = - std::string(llvm::formatv("{0}in-memory-fs-cwd{0}test.cpp", Sept)); - VFS->addFile(TestPath, 0, llvm::MemoryBuffer::getMemBuffer("int x;\n")); - - auto Invocation = std::make_shared(); - Invocation->getFrontendOpts().Inputs.push_back( - FrontendInputFile("test.cpp", Language::CXX)); - Invocation->getFrontendOpts().ProgramAction = EmitLLVM; - Invocation->getTargetOpts().Triple = "x86_64-unknown-linux-gnu"; - Invocation->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); - CompilerInstance Compiler(std::move(Invocation)); - - SmallString<256> IRBuffer; - Compiler.setOutputStream(std::make_unique(IRBuffer)); - Compiler.createDiagnostics(*VFS); - Compiler.createFileManager(std::move(VFS)); - - EmitLLVMAction Action; - bool Success = Compiler.ExecuteAction(Action); - EXPECT_TRUE(Success); - - SmallString<128> RealCWD; - llvm::sys::fs::current_path(RealCWD); - EXPECT_TRUE(!RealCWD.empty()); - EXPECT_FALSE(IRBuffer.str().contains(RealCWD)); - EXPECT_TRUE(IRBuffer.str().contains("in-memory-fs-cwd")); -} } From a404ce2750462e8c1067b45c2ef10fbfca200942 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Tue, 22 Jul 2025 15:27:09 -0700 Subject: [PATCH 2/2] address review feedback Created using spr 1.3.6 --- clang/lib/CodeGen/CGDebugInfo.cpp | 14 +++++--- clang/lib/CodeGen/CGDebugInfo.h | 1 + clang/lib/CodeGen/CoverageMappingGen.cpp | 7 +++- clang/lib/Driver/ToolChains/Clang.cpp | 3 +- .../DependencyScanning/ModuleDepCollector.cpp | 26 ++++++++++++-- clang/test/ClangScanDeps/modules-debug-dir.c | 10 ++---- clang/test/CodeGen/debug-info-abspath.c | 13 +++++-- .../test/CodeGen/debug-info-compilation-dir.c | 7 ---- clang/test/CodeGen/debug-prefix-map.c | 5 +-- .../debug-info-function-context.cpp | 2 +- clang/test/CodeGenCXX/difile_entry.cpp | 2 +- clang/test/Driver/compilation-dir.c | 4 +++ clang/test/PCH/debug-info-pch-path.c | 3 +- clang/test/Profile/coverage-prefix-map.c | 2 +- .../unittests/Frontend/CodeGenActionTest.cpp | 36 +++++++++++++++++++ 15 files changed, 102 insertions(+), 33 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index fcad19218502a..a371b6755f74d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -643,7 +643,16 @@ unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) { } StringRef CGDebugInfo::getCurrentDirname() { - return CGM.getCodeGenOpts().DebugCompilationDir; + if (!CGM.getCodeGenOpts().DebugCompilationDir.empty()) + return CGM.getCodeGenOpts().DebugCompilationDir; + + if (!CWDName.empty()) + return CWDName; + llvm::ErrorOr CWD = + CGM.getFileSystem()->getCurrentWorkingDirectory(); + if (!CWD) + return StringRef(); + return CWDName = internString(*CWD); } void CGDebugInfo::CreateCompileUnit() { @@ -3237,9 +3246,6 @@ llvm::DIModule *CGDebugInfo::getOrCreateModuleRef(ASTSourceDescriptor Mod, std::string Remapped = remapDIPath(Path); StringRef Relative(Remapped); StringRef CompDir = TheCU->getDirectory(); - if (CompDir.empty()) - return Remapped; - if (Relative.consume_front(CompDir)) Relative.consume_front(llvm::sys::path::get_separator()); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 497d3a6ab17b1..411b2e718da30 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -158,6 +158,7 @@ class CGDebugInfo { /// This is a storage for names that are constructed on demand. For /// example, C++ destructors, C++ operators etc.. llvm::BumpPtrAllocator DebugInfoNames; + StringRef CWDName; llvm::DenseMap DIFileCache; llvm::DenseMap SPCache; diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 38aaceb6c462d..4aafac349e3e9 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -2449,7 +2449,12 @@ CoverageMappingModuleGen::CoverageMappingModuleGen( : CGM(CGM), SourceInfo(SourceInfo) {} std::string CoverageMappingModuleGen::getCurrentDirname() { - return CGM.getCodeGenOpts().CoverageCompilationDir; + if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty()) + return CGM.getCodeGenOpts().CoverageCompilationDir; + + SmallString<256> CWD; + llvm::sys::fs::current_path(CWD); + return CWD.str().str(); } std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index afeea6da5fa89..4f35f1128dbdb 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -253,7 +253,8 @@ static const char *addDebugCompDirArg(const ArgList &Args, else return nullptr; } - CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + DebugCompDir)); + CmdArgs.push_back( + Args.MakeArgString("-fdebug-compilation-dir=" + DebugCompDir)); StringRef Path(CmdArgs.back()); return Path.substr(Path.find('=') + 1).data(); } diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index d67178c153e88..37f8b945d785e 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -144,8 +144,30 @@ static void optimizeDiagnosticOpts(DiagnosticOptions &Opts, static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) { BuildInvocation.getMutFileSystemOpts().WorkingDir.clear(); - BuildInvocation.getMutCodeGenOpts().DebugCompilationDir.clear(); - BuildInvocation.getMutCodeGenOpts().CoverageCompilationDir.clear(); + if (BuildInvocation.getCodeGenOpts().DwarfVersion) { + // It is necessary to explicitly set the DebugCompilationDir + // to a common directory (e.g. root) if IgnoreCWD is true. + // When IgnoreCWD is true, the module's content should not + // depend on the current working directory. However, if dwarf + // information is needed (when CGOpts.DwarfVersion is + // non-zero), then CGOpts.DebugCompilationDir must be + // populated, because otherwise the current working directory + // will be automatically embedded in the dwarf information in + // the pcm, contradicting the assumption that it is safe to + // ignore the CWD. Thus in such cases, + // CGOpts.DebugCompilationDir is explicitly set to a common + // directory. + // FIXME: It is still excessive to create a copy of + // CodeGenOpts for each module. Since we do not modify the + // CodeGenOpts otherwise per module, the following code + // ends up generating identical CodeGenOpts for each module + // with DebugCompilationDir pointing to the root directory. + // We can optimize this away by creating a _single_ copy of + // CodeGenOpts whose DebugCompilationDir points to the root + // directory and reuse it across modules. + BuildInvocation.getMutCodeGenOpts().DebugCompilationDir = + llvm::sys::path::root_path(CWD); + } } static std::vector splitString(std::string S, char Separator) { diff --git a/clang/test/ClangScanDeps/modules-debug-dir.c b/clang/test/ClangScanDeps/modules-debug-dir.c index e2a0e1b7a5b01..c4fb4982ed791 100644 --- a/clang/test/ClangScanDeps/modules-debug-dir.c +++ b/clang/test/ClangScanDeps/modules-debug-dir.c @@ -1,3 +1,5 @@ +// REQUIRES: shell + // RUN: rm -rf %t // RUN: split-file %s %t // RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json @@ -5,12 +7,6 @@ // RUN: experimental-full -optimize-args=all > %t/result.json // RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck %s -// RUN: %deps-to-rsp %t/result.json --module-name=mod > %t/mod.rsp -// RUN: %clang @%t/mod.rsp -o %t/mod.pcm -// RUN: llvm-dwarfdump --debug-info %t/mod.pcm | FileCheck %s --check-prefix=DWARF -// DWARF: DW_TAG_compile_unit -// DWARF-NOT: DW_AT_comp_dir - //--- cdb.json.in [{ "directory": "DIR", @@ -32,5 +28,5 @@ module mod { // directory when current working directory optimization is in effect. // CHECK: "modules": [ // CHECK: "command-line": [ -// CHECK-NOT: -fdebug-compilation-dir +// CHECK: "-fdebug-compilation-dir={{\/|.*:(\\)?}}", // CHECK: "translation-units": [ diff --git a/clang/test/CodeGen/debug-info-abspath.c b/clang/test/CodeGen/debug-info-abspath.c index 193a72c0a66fd..b2047a7deb0e0 100644 --- a/clang/test/CodeGen/debug-info-abspath.c +++ b/clang/test/CodeGen/debug-info-abspath.c @@ -2,15 +2,20 @@ // RUN: cp %s %t/UNIQUEISH_SENTINEL/debug-info-abspath.c // RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ -// RUN: -fdebug-compilation-dir=%t/UNIQUEISH_SENTINEL/debug-info-abspath.c \ // RUN: %t/UNIQUEISH_SENTINEL/debug-info-abspath.c -emit-llvm -o - \ // RUN: | FileCheck %s // RUN: cp %s %t.c // RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ -// RUN: -fdebug-compilation-dir=%t \ // RUN: %t.c -emit-llvm -o - | FileCheck %s --check-prefix=INTREE +// RUN: cd %t/UNIQUEISH_SENTINEL +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: debug-info-abspath.c -emit-llvm -o - \ +// RUN: | FileCheck %s --check-prefix=CURDIR +// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \ +// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefix=CURDIR + void foo(void) {} // Since %s is an absolute path, directory should be the common @@ -23,3 +28,7 @@ void foo(void) {} // INTREE: = distinct !DISubprogram({{.*}}![[SPFILE:[0-9]+]] // INTREE: DIFile({{.*}}directory: "{{.+}}CodeGen{{.*}}") + +// CURDIR: = distinct !DICompileUnit({{.*}}file: ![[CUFILE:[0-9]+]] +// CURDIR: ![[CUFILE]] = !DIFile({{.*}}directory: "{{.+}}UNIQUEISH_SENTINEL") + diff --git a/clang/test/CodeGen/debug-info-compilation-dir.c b/clang/test/CodeGen/debug-info-compilation-dir.c index 5f5542c525495..b49a0f5751f8e 100644 --- a/clang/test/CodeGen/debug-info-compilation-dir.c +++ b/clang/test/CodeGen/debug-info-compilation-dir.c @@ -7,10 +7,3 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-DIR %s // CHECK-DIR: CodeGen -/// Test path remapping. -// RUN: %clang_cc1 -fdebug-compilation-dir=%S -main-file-name %s -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-ABS %s -// CHECK-ABS: DIFile(filename: "{{.*}}debug-info-compilation-dir.c", directory: "{{.*}}CodeGen") - -// RUN: %clang_cc1 -main-file-name %s -emit-llvm -debug-info-kind=limited %s -o - | FileCheck -check-prefix=CHECK-NOMAP %s -// CHECK-NOMAP: DIFile(filename: "{{.*}}debug-info-compilation-dir.c", directory: "") - diff --git a/clang/test/CodeGen/debug-prefix-map.c b/clang/test/CodeGen/debug-prefix-map.c index e58909f5acaaa..e2421806b055b 100644 --- a/clang/test/CodeGen/debug-prefix-map.c +++ b/clang/test/CodeGen/debug-prefix-map.c @@ -12,7 +12,6 @@ // RUN: rm -rf %t && mkdir -p %t/a/b && cp %s %t/a/b/c.c // RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -fdebug-prefix-map=%t/a/b=y -fdebug-prefix-map=%t/a=x %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-X // RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -fdebug-prefix-map=%t/a=x -fdebug-prefix-map=%t/a/b=y %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-Y -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -I%S -main-file-name %t/a/b/c.c -fdebug-compilation-dir=%t/a -fdebug-prefix-map=%t/a=x -fdebug-prefix-map=%t/a/b=y %t/a/b/c.c -o - | FileCheck %s --check-prefix=CHECK-REMAP-Y #include "Inputs/stdio.h" @@ -27,9 +26,9 @@ void test_rewrite_includes(void) { vprintf("string", argp); } +// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}", // CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}{{.*}}", // CHECK-NO-MAIN-FILE-NAME-SAME: directory: "") -// CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}", // CHECK-NO-MAIN-FILE-NAME: !DIFile(filename: "{{/|.:\\\\}}UNLIKELY_PATH{{/|\\\\}}empty{{/|\\\\}}Inputs{{/|\\\\}}stdio.h", // CHECK-NO-MAIN-FILE-NAME-SAME: directory: "") // CHECK-NO-MAIN-FILE-NAME-NOT: !DIFile(filename: @@ -55,5 +54,3 @@ void test_rewrite_includes(void) { // CHECK-X: !DIFile(filename: "x{{/|\\\\}}b{{/|\\\\}}c.c", directory: "") // CHECK-Y: !DIFile(filename: "y{{/|\\\\}}c.c", directory: "") - -// CHECK-REMAP-Y: !DIFile(filename: "y{{/|\\\\}}c.c", directory: "x") diff --git a/clang/test/CodeGenCXX/debug-info-function-context.cpp b/clang/test/CodeGenCXX/debug-info-function-context.cpp index 29c87b6ec0055..63fdf877fdb7d 100644 --- a/clang/test/CodeGenCXX/debug-info-function-context.cpp +++ b/clang/test/CodeGenCXX/debug-info-function-context.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-pc-linux-gnu %s -fdebug-compilation-dir=%S \ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-pc-linux-gnu %s \ // RUN: -dwarf-version=5 -main-file-name debug-info-function-context.cpp -o - | FileCheck %s struct C { diff --git a/clang/test/CodeGenCXX/difile_entry.cpp b/clang/test/CodeGenCXX/difile_entry.cpp index 5fcd56ee3d053..8bf6dc325470b 100644 --- a/clang/test/CodeGenCXX/difile_entry.cpp +++ b/clang/test/CodeGenCXX/difile_entry.cpp @@ -3,7 +3,7 @@ /// Test that we canonicalize the DIFile. // RUN: rm -rf %t && mkdir %t && cd %t // RUN: cp %s . -// RUN: %clang_cc1 -triple %itanium_abi_triple -main-file-name difile_entry.cpp -fdebug-compilation-dir=%t -debug-info-kind=limited %t/difile_entry.cpp -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -main-file-name difile_entry.cpp -debug-info-kind=limited %t/difile_entry.cpp -std=c++11 -emit-llvm -o - | FileCheck %s int x(); static int i = x(); diff --git a/clang/test/Driver/compilation-dir.c b/clang/test/Driver/compilation-dir.c index dbe801c9f5fcb..0e19efee3993f 100644 --- a/clang/test/Driver/compilation-dir.c +++ b/clang/test/Driver/compilation-dir.c @@ -8,3 +8,7 @@ // RUN: %clang -### -integrated-as -ffile-compilation-dir=. -x assembler %s 2>&1 | FileCheck -check-prefixes=CHECK-DEBUG-COMPILATION-DIR %s // CHECK-DEBUG-COMPILATION-DIR: "-fdebug-compilation-dir=." // CHECK-DEBUG-COMPILATION-DIR-NOT: "-ffile-compilation-dir=." + +// RUN: cd %S +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-CWD %s +// CHECK-CWD: -fdebug-compilation-dir={{.*}}Driver diff --git a/clang/test/PCH/debug-info-pch-path.c b/clang/test/PCH/debug-info-pch-path.c index 22b367f344204..f94d2fa8d09e9 100644 --- a/clang/test/PCH/debug-info-pch-path.c +++ b/clang/test/PCH/debug-info-pch-path.c @@ -65,8 +65,7 @@ // RUN: %clang_cc1 -debug-info-kind=standalone \ // RUN: -dwarf-ext-refs -fmodule-format=obj \ // RUN: -triple %itanium_abi_triple \ -// RUN: -include-pch %t/prefix.pch %s -emit-llvm \ -// RUN: -fdebug-compilation-dir=%t -o %t.abs.ll %s +// RUN: -include-pch %t/prefix.pch %s -emit-llvm -o %t.abs.ll %s // RUN: cat %t.abs.ll | FileCheck %s --check-prefix=CHECK-ABS // CHECK-ABS: !DICompileUnit diff --git a/clang/test/Profile/coverage-prefix-map.c b/clang/test/Profile/coverage-prefix-map.c index 1cb095f2bdbf6..de9e3773f66d2 100644 --- a/clang/test/Profile/coverage-prefix-map.c +++ b/clang/test/Profile/coverage-prefix-map.c @@ -25,7 +25,7 @@ // COVERAGE-PREFIX-MAP-ORDER: @__llvm_coverage_mapping = {{.*"\\02.*newpath.*root.*nested.*coverage-prefix-map\.c}} // Test that last -fcoverage-prefix-map option (-fcoverage-prefix-map=%/t/root=.) is applied. -// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name coverage-prefix-map.c %t/root/nested/coverage-prefix-map.c -fcoverage-compilation-dir=%t/root -fcoverage-prefix-map==newpath -fcoverage-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=COVERAGE-PREFIX-MAP-REORDER %s +// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name coverage-prefix-map.c %t/root/nested/coverage-prefix-map.c -fcoverage-prefix-map==newpath -fcoverage-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=COVERAGE-PREFIX-MAP-REORDER %s // COVERAGE-PREFIX-MAP-REORDER: @__llvm_coverage_mapping = // COVERAGE-PREFIX-MAP-REORDER-NOT: newpath // COVERAGE-PREFIX-MAP-REORDER-SAME: nested{{.*coverage-prefix-map\.c}} diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp index b2792c44ba5fe..90818b72cd6e6 100644 --- a/clang/unittests/Frontend/CodeGenActionTest.cpp +++ b/clang/unittests/Frontend/CodeGenActionTest.cpp @@ -76,4 +76,40 @@ TEST(CodeGenTest, CodeGenFromIRMemBuffer) { bool Success = Compiler.ExecuteAction(Action); EXPECT_TRUE(Success); } + +TEST(CodeGenTest, DebugInfoCWDCodeGen) { + // Check that debug info is accessing the current working directory from the + // VFS instead of calling \p llvm::sys::fs::current_path() directly. + + auto Sept = llvm::sys::path::get_separator(); + auto VFS = std::make_unique(); + VFS->setCurrentWorkingDirectory( + std::string(llvm::formatv("{0}in-memory-fs-cwd", Sept))); + std::string TestPath = + std::string(llvm::formatv("{0}in-memory-fs-cwd{0}test.cpp", Sept)); + VFS->addFile(TestPath, 0, llvm::MemoryBuffer::getMemBuffer("int x;\n")); + + auto Invocation = std::make_shared(); + Invocation->getFrontendOpts().Inputs.push_back( + FrontendInputFile("test.cpp", Language::CXX)); + Invocation->getFrontendOpts().ProgramAction = EmitLLVM; + Invocation->getTargetOpts().Triple = "x86_64-unknown-linux-gnu"; + Invocation->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); + CompilerInstance Compiler(std::move(Invocation)); + + SmallString<256> IRBuffer; + Compiler.setOutputStream(std::make_unique(IRBuffer)); + Compiler.createDiagnostics(*VFS); + Compiler.createFileManager(std::move(VFS)); + + EmitLLVMAction Action; + bool Success = Compiler.ExecuteAction(Action); + EXPECT_TRUE(Success); + + SmallString<128> RealCWD; + llvm::sys::fs::current_path(RealCWD); + EXPECT_TRUE(!RealCWD.empty()); + EXPECT_FALSE(IRBuffer.str().contains(RealCWD)); + EXPECT_TRUE(IRBuffer.str().contains("in-memory-fs-cwd")); +} }