diff --git a/clang/include/clang/CodeGen/ModuleBuilder.h b/clang/include/clang/CodeGen/ModuleBuilder.h --- a/clang/include/clang/CodeGen/ModuleBuilder.h +++ b/clang/include/clang/CodeGen/ModuleBuilder.h @@ -14,12 +14,17 @@ #define LLVM_CLANG_CODEGEN_MODULEBUILDER_H #include "clang/AST/ASTConsumer.h" +#include "clang/Basic/LLVM.h" namespace llvm { class Constant; class LLVMContext; class Module; class StringRef; + + namespace vfs { + class FileSystem; + } } namespace clang { @@ -98,10 +103,11 @@ /// the allocated CodeGenerator instance. CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName, + IntrusiveRefCntPtr FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, - llvm::LLVMContext& C, + llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr); } // end namespace clang diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -491,9 +491,11 @@ if (!CWDName.empty()) return CWDName; - SmallString<256> CWD; - llvm::sys::fs::current_path(CWD); - return CWDName = internString(CWD); + llvm::ErrorOr CWD = + CGM.getFileSystem()->getCurrentWorkingDirectory(); + if (!CWD) + return StringRef(); + return CWDName = internString(*CWD); } void CGDebugInfo::CreateCompileUnit() { diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -146,6 +146,7 @@ public: BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, @@ -159,8 +160,8 @@ AsmOutStream(std::move(OS)), Context(nullptr), LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, - CodeGenOpts, C, CoverageInfo)), + Gen(CreateLLVMCodeGen(Diags, InFile, std::move(FS), HeaderSearchOpts, + PPOpts, CodeGenOpts, C, CoverageInfo)), LinkModules(std::move(LinkModules)) { TimerIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; @@ -171,6 +172,7 @@ // to use the clang diagnostic handler for IR input files. It avoids // initializing the OS field. BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, @@ -183,8 +185,8 @@ Context(nullptr), LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, - CodeGenOpts, C, CoverageInfo)), + Gen(CreateLLVMCodeGen(Diags, "", std::move(FS), HeaderSearchOpts, + PPOpts, CodeGenOpts, C, CoverageInfo)), LinkModules(std::move(LinkModules)), CurLinkModule(Module) { TimerIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; @@ -1052,10 +1054,10 @@ CI.getPreprocessor()); std::unique_ptr Result(new BackendConsumer( - BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), - CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), - CI.getLangOpts(), std::string(InFile), std::move(LinkModules), - std::move(OS), *VMContext, CoverageInfo)); + BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(), + CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), + CI.getTargetOpts(), CI.getLangOpts(), std::string(InFile), + std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); BEConsumer = Result.get(); // Enable generating macro debug info only when debug info is not disabled and @@ -1185,9 +1187,10 @@ // Set clang diagnostic handler. To do this we need to create a fake // BackendConsumer. - BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), - CI.getPreprocessorOpts(), CI.getCodeGenOpts(), - CI.getTargetOpts(), CI.getLangOpts(), TheModule.get(), + BackendConsumer Result(BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(), + CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), + CI.getCodeGenOpts(), CI.getTargetOpts(), + CI.getLangOpts(), TheModule.get(), std::move(LinkModules), *VMContext, nullptr); // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be // true here because the valued names are needed for reading textual IR. diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -47,6 +47,10 @@ class FunctionType; class LLVMContext; class IndexedInstrProfReader; + +namespace vfs { +class FileSystem; +} } namespace clang { @@ -293,6 +297,7 @@ private: ASTContext &Context; const LangOptions &LangOpts; + IntrusiveRefCntPtr FS; // Only used for debug info. const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions &CodeGenOpts; @@ -584,7 +589,8 @@ llvm::DenseMap RTTIProxyMap; public: - CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, + CodeGenModule(ASTContext &C, IntrusiveRefCntPtr FS, + const HeaderSearchOptions &headersearchopts, const PreprocessorOptions &ppopts, const CodeGenOptions &CodeGenOpts, llvm::Module &M, DiagnosticsEngine &Diags, @@ -712,6 +718,9 @@ ASTContext &getContext() const { return Context; } const LangOptions &getLangOpts() const { return LangOpts; } + const IntrusiveRefCntPtr &getFileSystem() const { + return FS; + } const HeaderSearchOptions &getHeaderSearchOpts() const { return HeaderSearchOpts; } const PreprocessorOptions &getPreprocessorOpts() diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -96,16 +96,18 @@ llvm_unreachable("invalid C++ ABI kind"); } -CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, +CodeGenModule::CodeGenModule(ASTContext &C, + IntrusiveRefCntPtr FS, + const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, const CodeGenOptions &CGO, llvm::Module &M, DiagnosticsEngine &diags, CoverageSourceInfo *CoverageInfo) - : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO), - PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), - Target(C.getTargetInfo()), ABI(createCXXABI(*this)), - VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)) { + : Context(C), LangOpts(C.getLangOpts()), FS(std::move(FS)), + HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), + TheModule(M), Diags(diags), Target(C.getTargetInfo()), + ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), + VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/VirtualFileSystem.h" #include using namespace clang; @@ -32,6 +33,7 @@ class CodeGeneratorImpl : public CodeGenerator { DiagnosticsEngine &Diags; ASTContext *Ctx; + IntrusiveRefCntPtr FS; // Only used for debug info. const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions CodeGenOpts; // Intentionally copied in. @@ -74,11 +76,12 @@ public: CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName, + IntrusiveRefCntPtr FS, const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, const CodeGenOptions &CGO, llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), + : Diags(diags), Ctx(nullptr), FS(std::move(FS)), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0), CoverageInfo(CoverageInfo), M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) { @@ -158,7 +161,7 @@ if (auto TVSDKVersion = Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion()) M->setDarwinTargetVariantSDKVersion(*TVSDKVersion); - Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, + Builder.reset(new CodeGen::CodeGenModule(Context, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags, CoverageInfo)); @@ -356,11 +359,14 @@ return static_cast(this)->StartModule(ModuleName, C); } -CodeGenerator *clang::CreateLLVMCodeGen( - DiagnosticsEngine &Diags, llvm::StringRef ModuleName, - const HeaderSearchOptions &HeaderSearchOpts, - const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, - llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) { - return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts, - PreprocessorOpts, CGO, C, CoverageInfo); +CodeGenerator * +clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName, + IntrusiveRefCntPtr FS, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PreprocessorOpts, + const CodeGenOptions &CGO, llvm::LLVMContext &C, + CoverageSourceInfo *CoverageInfo) { + return new CodeGeneratorImpl(Diags, ModuleName, std::move(FS), + HeaderSearchOpts, PreprocessorOpts, CGO, C, + CoverageInfo); } diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp --- a/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -45,6 +45,7 @@ const std::string OutputFileName; ASTContext *Ctx; ModuleMap &MMap; + IntrusiveRefCntPtr FS; const HeaderSearchOptions &HeaderSearchOpts; const PreprocessorOptions &PreprocessorOpts; CodeGenOptions CodeGenOpts; @@ -144,6 +145,7 @@ : Diags(CI.getDiagnostics()), MainFileName(MainFileName), OutputFileName(OutputFileName), Ctx(nullptr), MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), + FS(&CI.getVirtualFileSystem()), HeaderSearchOpts(CI.getHeaderSearchOpts()), PreprocessorOpts(CI.getPreprocessorOpts()), TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), @@ -173,7 +175,7 @@ M.reset(new llvm::Module(MainFileName, *VMContext)); M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); Builder.reset(new CodeGen::CodeGenModule( - *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); + *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); // Prepare CGDebugInfo to emit debug info for a clang module. auto *DI = Builder->getModuleDebugInfo(); diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -230,8 +230,9 @@ llvm::LLVMContext &LLVMCtx) { StringRef ModuleName("$__module"); return std::unique_ptr(CreateLLVMCodeGen( - CI.getDiagnostics(), ModuleName, CI.getHeaderSearchOpts(), - CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx)); + CI.getDiagnostics(), ModuleName, &CI.getVirtualFileSystem(), + CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), + LLVMCtx)); } } // namespace init_convenience diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h --- a/clang/unittests/CodeGen/TestCompiler.h +++ b/clang/unittests/CodeGen/TestCompiler.h @@ -56,12 +56,10 @@ compiler.createASTContext(); - CG.reset(CreateLLVMCodeGen(compiler.getDiagnostics(), - "main-module", - compiler.getHeaderSearchOpts(), - compiler.getPreprocessorOpts(), - compiler.getCodeGenOpts(), - Context)); + CG.reset(CreateLLVMCodeGen( + compiler.getDiagnostics(), "main-module", + &compiler.getVirtualFileSystem(), compiler.getHeaderSearchOpts(), + compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context)); } void init(const char *TestProgram, diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp --- a/clang/unittests/Frontend/CodeGenActionTest.cpp +++ b/clang/unittests/Frontend/CodeGenActionTest.cpp @@ -15,6 +15,7 @@ #include "clang/CodeGen/BackendUtil.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/Support/FormatVariadic.h" #include "gtest/gtest.h" using namespace llvm; @@ -76,4 +77,40 @@ 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 VFS = std::make_unique(); + VFS->setCurrentWorkingDirectory("/in-memory-fs-cwd"); + auto Sept = llvm::sys::path::get_separator(); + 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; + + SmallString<256> IRBuffer; + Compiler.setOutputStream(std::make_unique(IRBuffer)); + Compiler.setInvocation(std::move(Invocation)); + Compiler.createDiagnostics(); + 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")); +} }