https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/178001
>From 1d3080cb1f4258d3842f6a38241189d3007f2743 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <[email protected]> Date: Mon, 26 Jan 2026 09:19:02 -0800 Subject: [PATCH 1/2] [clang] Fix dependency output for #embed When requesting FileEntryRef for embedded file, make sure to not use an absolute path. Instead, create a proper relative path if we're looking for a file from current file. Fixes https://github.com/llvm/llvm-project/issues/161950 --- clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/Lex/Preprocessor.h | 11 +-- clang/lib/Lex/PPDirectives.cpp | 30 ++++--- clang/lib/Lex/PPMacroExpansion.cpp | 5 +- clang/test/Preprocessor/embed_dependencies.c | 7 +- .../Lex/PPDependencyDirectivesTest.cpp | 81 +++++++++++++++++++ 6 files changed, 106 insertions(+), 30 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f0d3d81f14e43..88faf96bc6297 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -194,6 +194,8 @@ Bug Fixes in This Version - Fix lifetime extension of temporaries in for-range-initializers in templates. (#GH165182) +- Clang now outputs relative paths of embeds for dependency output. (#GH161950) + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 5adc45a19ca79..5fb83eafc6b2a 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2604,13 +2604,11 @@ class Preprocessor { /// resource. \p isAngled indicates whether the file reference is for /// system \#include's or not (i.e. using <> instead of ""). If \p OpenFile /// is true, the file looked up is opened for reading, otherwise it only - /// validates that the file exists. Quoted filenames are looked up relative - /// to \p LookupFromFile if it is nonnull. + /// validates that the file exists. /// /// Returns std::nullopt on failure. - OptionalFileEntryRef - LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, - const FileEntry *LookupFromFile = nullptr); + OptionalFileEntryRef LookupEmbedFile(StringRef Filename, bool isAngled, + bool OpenFile); /// Return true if we're in the top-level file, not in a \#include. bool isInPrimaryFile() const; @@ -2920,8 +2918,7 @@ class Preprocessor { SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath, ModuleMap::KnownHeader &SuggestedModule, bool isAngled); // Binary data inclusion - void HandleEmbedDirective(SourceLocation HashLoc, Token &Tok, - const FileEntry *LookupFromFile = nullptr); + void HandleEmbedDirective(SourceLocation HashLoc, Token &Tok); void HandleEmbedDirectiveImpl(SourceLocation HashLoc, const LexEmbedParametersResult &Params, StringRef BinaryContents, StringRef FileName); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index b1d5c3636c99b..50611e4c0e07f 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1187,9 +1187,9 @@ OptionalFileEntryRef Preprocessor::LookupFile( return std::nullopt; } -OptionalFileEntryRef -Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, - const FileEntry *LookupFromFile) { +OptionalFileEntryRef Preprocessor::LookupEmbedFile(StringRef Filename, + bool isAngled, + bool OpenFile) { FileManager &FM = this->getFileManager(); if (llvm::sys::path::is_absolute(Filename)) { // lookup path or immediately fail @@ -1215,13 +1215,15 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, SmallString<512> LookupPath; // Non-angled lookup if (!isAngled) { + OptionalFileEntryRef LookupFromFile = getCurrentFileLexer()->getFileEntry(); if (LookupFromFile) { // Use file-based lookup. - StringRef FullFileDir = LookupFromFile->tryGetRealPathName(); - if (!FullFileDir.empty()) { - SeparateComponents(LookupPath, FullFileDir, Filename, true); + SmallString<1024> TmpDir; + TmpDir = LookupFromFile->getDir().getName(); + llvm::sys::path::append(TmpDir, Filename); + if (!TmpDir.empty()) { llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef( - LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); + TmpDir, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); @@ -1487,12 +1489,8 @@ void Preprocessor::HandleDirective(Token &Result) { return HandleIdentSCCSDirective(Result); case tok::pp_sccs: return HandleIdentSCCSDirective(Result); - case tok::pp_embed: { - if (PreprocessorLexer *CurrentFileLexer = getCurrentFileLexer()) - if (OptionalFileEntryRef FERef = CurrentFileLexer->getFileEntry()) - return HandleEmbedDirective(Introducer.getLocation(), Result, *FERef); - return HandleEmbedDirective(Introducer.getLocation(), Result, nullptr); - } + case tok::pp_embed: + return HandleEmbedDirective(Introducer.getLocation(), Result); case tok::pp_assert: //isExtension = true; // FIXME: implement #assert break; @@ -4076,8 +4074,8 @@ void Preprocessor::HandleEmbedDirectiveImpl( EnterTokenStream(std::move(Toks), TotalNumToks, true, true); } -void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok, - const FileEntry *LookupFromFile) { +void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, + Token &EmbedTok) { // Give the usual extension/compatibility warnings. if (LangOpts.C23) Diag(EmbedTok, diag::warn_compat_pp_embed_directive); @@ -4126,7 +4124,7 @@ void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok, return; OptionalFileEntryRef MaybeFileRef = - this->LookupEmbedFile(Filename, isAngled, true, LookupFromFile); + this->LookupEmbedFile(Filename, isAngled, /*OpenFile=*/ true); if (!MaybeFileRef) { // could not find file if (Callbacks && Callbacks->EmbedFileNotFound(Filename)) { diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 5efa4b5b3f872..4c07e7ab73ef2 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1287,11 +1287,8 @@ EmbedResult Preprocessor::EvaluateHasEmbed(Token &Tok, IdentifierInfo *II) { this->GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename); // If GetIncludeFilenameSpelling set the start ptr to null, there was an // error. - const FileEntry *LookupFromFile = - this->getCurrentFileLexer() ? *this->getCurrentFileLexer()->getFileEntry() - : static_cast<FileEntry *>(nullptr); OptionalFileEntryRef MaybeFileEntry = - this->LookupEmbedFile(Filename, isAngled, false, LookupFromFile); + this->LookupEmbedFile(Filename, isAngled, false); if (Callbacks) { Callbacks->HasEmbed(LParenLoc, Filename, isAngled, MaybeFileEntry); } diff --git a/clang/test/Preprocessor/embed_dependencies.c b/clang/test/Preprocessor/embed_dependencies.c index 4e00dc79ac190..d3a36d973c887 100644 --- a/clang/test/Preprocessor/embed_dependencies.c +++ b/clang/test/Preprocessor/embed_dependencies.c @@ -1,4 +1,4 @@ -// RUN: %clang %s -fsyntax-only -std=c23 -M --embed-dir=%S/Inputs -Xclang -verify | FileCheck %s +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c23 -MT %s.o --embed-dir=%S/Inputs -dependency-file - | FileCheck %s // Yes this looks very strange indeed, but the goal is to test that we add // files referenced by both __has_embed and #embed when we generate @@ -14,7 +14,8 @@ _Static_assert('b' == data); #endif // expected-no-diagnostics -// CHECK: embed_dependencies.c \ -// CHECK-NEXT: jk.txt \ +// CHECK: embed_dependencies.c.o +// CHECK-NEXT: embed_dependencies.c +// CHECK-NEXT: jk.txt // CHECK-NEXT: Inputs{{[/\\]}}single_byte.txt diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp index 15cc2835e3fb7..0e12e476508f7 100644 --- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp +++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp @@ -69,6 +69,33 @@ class IncludeCollector : public PPCallbacks { } }; +class EmbedCollector : public PPCallbacks { +public: + Preprocessor &PP; + SmallVectorImpl<StringRef> &EmbeddedFiles; + + EmbedCollector(Preprocessor &PP, SmallVectorImpl<StringRef> &EmbeddedFiles) + : PP(PP), EmbeddedFiles(EmbeddedFiles) {} + + void EmbedDirective(SourceLocation, StringRef, bool, + OptionalFileEntryRef File, + const LexEmbedParametersResult &) override { + assert(File && "expected to only be called when the file is found"); + StringRef Filename = + llvm::sys::path::remove_leading_dotslash(File->getName()); + EmbeddedFiles.push_back(Filename); + } + + void HasEmbed(SourceLocation, StringRef, bool, + OptionalFileEntryRef File) override { + if (!File) + return; + StringRef Filename = + llvm::sys::path::remove_leading_dotslash(File->getName()); + EmbeddedFiles.push_back(Filename); + } +}; + TEST_F(PPDependencyDirectivesTest, MacroGuard) { // "head1.h" has a macro guard and should only be included once. // "head2.h" and "head3.h" have tokens following the macro check, they should @@ -155,4 +182,58 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) { EXPECT_EQ(IncludedFilesSlash, ExpectedIncludes); } + +TEST_F(PPDependencyDirectivesTest, Embed) { + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); + VFS->setCurrentWorkingDirectory("/source"); + VFS->addFile("/source/inputs/jk.txt", 0, llvm::MemoryBuffer::getMemBuffer("jk")); + VFS->addFile( + "/source/inputs/single_byte.txt", 0, + llvm::MemoryBuffer::getMemBuffer("a")); + VFS->addFile( + "/source/inputs/single_byte1.txt", 0, + llvm::MemoryBuffer::getMemBuffer("b")); + VFS->addFile( + "/source/inc/head.h", 0, + llvm::MemoryBuffer::getMemBuffer("#embed \"inputs/single_byte.txt\"\n" + "extern int foo;\n")); + VFS->addFile("main.c", 0, + llvm::MemoryBuffer::getMemBuffer( + "#include \"inc/head.h\"\n" + "#if __has_embed(\"inputs/jk.txt\")\n" + "const char arr[] =\n" + "#embed \"inputs/single_byte1.txt\"\n" + ";\n" + "#endif\n" + )); + FileMgr.setVirtualFileSystem(VFS); + + OptionalFileEntryRef FE; + ASSERT_THAT_ERROR(FileMgr.getFileRef("main.c").moveInto(FE), + llvm::Succeeded()); + SourceMgr.setMainFileID( + SourceMgr.createFileID(*FE, SourceLocation(), SrcMgr::C_User)); + PreprocessorOptions PPOpts; + HeaderSearchOptions HSOpts; + TrivialModuleLoader ModLoader; + HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get()); + Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader, + /*IILookup =*/nullptr, + /*OwnsHeaderSearch =*/false); + PP.Initialize(*Target); + + SmallVector<StringRef> EmbeddedFiles; + PP.addPPCallbacks(std::make_unique<EmbedCollector>(PP, EmbeddedFiles)); + PP.EnterMainSourceFile(); + PP.LexTokensUntilEOF(); + + + SmallVector<StringRef> ExpectedEmbeds{ + "inputs/single_byte.txt", + "inputs/jk.txt", + "inputs/single_byte1.txt", + }; + EXPECT_EQ(EmbeddedFiles, ExpectedEmbeds); +} + } // anonymous namespace >From 88610f58fd4b468caa55a3596a0e1ed74cf1cc7e Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <[email protected]> Date: Mon, 26 Jan 2026 10:10:04 -0800 Subject: [PATCH 2/2] Fix format --- clang/lib/Lex/PPDirectives.cpp | 2 +- .../Lex/PPDependencyDirectivesTest.cpp | 32 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 50611e4c0e07f..8d4c9c49f756a 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -4124,7 +4124,7 @@ void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, return; OptionalFileEntryRef MaybeFileRef = - this->LookupEmbedFile(Filename, isAngled, /*OpenFile=*/ true); + this->LookupEmbedFile(Filename, isAngled, /*OpenFile=*/true); if (!MaybeFileRef) { // could not find file if (Callbacks && Callbacks->EmbedFileNotFound(Filename)) { diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp index 0e12e476508f7..6beb66d1a36f5 100644 --- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp +++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp @@ -182,30 +182,27 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) { EXPECT_EQ(IncludedFilesSlash, ExpectedIncludes); } - TEST_F(PPDependencyDirectivesTest, Embed) { auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory("/source"); - VFS->addFile("/source/inputs/jk.txt", 0, llvm::MemoryBuffer::getMemBuffer("jk")); - VFS->addFile( - "/source/inputs/single_byte.txt", 0, - llvm::MemoryBuffer::getMemBuffer("a")); - VFS->addFile( - "/source/inputs/single_byte1.txt", 0, - llvm::MemoryBuffer::getMemBuffer("b")); + VFS->addFile("/source/inputs/jk.txt", 0, + llvm::MemoryBuffer::getMemBuffer("jk")); + VFS->addFile("/source/inputs/single_byte.txt", 0, + llvm::MemoryBuffer::getMemBuffer("a")); + VFS->addFile("/source/inputs/single_byte1.txt", 0, + llvm::MemoryBuffer::getMemBuffer("b")); VFS->addFile( "/source/inc/head.h", 0, llvm::MemoryBuffer::getMemBuffer("#embed \"inputs/single_byte.txt\"\n" "extern int foo;\n")); - VFS->addFile("main.c", 0, - llvm::MemoryBuffer::getMemBuffer( - "#include \"inc/head.h\"\n" - "#if __has_embed(\"inputs/jk.txt\")\n" - "const char arr[] =\n" - "#embed \"inputs/single_byte1.txt\"\n" - ";\n" - "#endif\n" - )); + VFS->addFile( + "main.c", 0, + llvm::MemoryBuffer::getMemBuffer("#include \"inc/head.h\"\n" + "#if __has_embed(\"inputs/jk.txt\")\n" + "const char arr[] =\n" + "#embed \"inputs/single_byte1.txt\"\n" + ";\n" + "#endif\n")); FileMgr.setVirtualFileSystem(VFS); OptionalFileEntryRef FE; @@ -227,7 +224,6 @@ TEST_F(PPDependencyDirectivesTest, Embed) { PP.EnterMainSourceFile(); PP.LexTokensUntilEOF(); - SmallVector<StringRef> ExpectedEmbeds{ "inputs/single_byte.txt", "inputs/jk.txt", _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
