From 4a2ab1b1fd2d637b01f7e2ac22f5381aa01bc87c Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Tue, 2 Dec 2025 14:09:42 +0000 Subject: [PATCH 1/3] [Clang] Fix `PPChainedCallbacks::EmbedFileNotFound()` --- clang/include/clang/Lex/PPCallbacks.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Lex/PPCallbacks.h b/clang/include/clang/Lex/PPCallbacks.h index 313b730afbab8..e6120c5648798 100644 --- a/clang/include/clang/Lex/PPCallbacks.h +++ b/clang/include/clang/Lex/PPCallbacks.h @@ -499,10 +499,10 @@ class PPChainedCallbacks : public PPCallbacks { } bool EmbedFileNotFound(StringRef FileName) override { - bool Skip = First->FileNotFound(FileName); + bool Skip = First->EmbedFileNotFound(FileName); // Make sure to invoke the second callback, no matter if the first already // returned true to skip the file. - Skip |= Second->FileNotFound(FileName); + Skip |= Second->EmbedFileNotFound(FileName); return Skip; } From 61166af34dfa6f9244ec0e2b4094b4e5f895400a Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Tue, 2 Dec 2025 17:23:24 +0000 Subject: [PATCH 2/3] Add test case --- clang/lib/Lex/PPDirectives.cpp | 11 ++++---- clang/unittests/Lex/PPCallbacksTest.cpp | 34 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 891c8ab7f3155..1c3d9480651da 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1397,11 +1397,12 @@ void Preprocessor::HandleDirective(Token &Result) { return HandleIdentSCCSDirective(Result); case tok::pp_sccs: return HandleIdentSCCSDirective(Result); - case tok::pp_embed: - return HandleEmbedDirective(SavedHash.getLocation(), Result, - getCurrentFileLexer() - ? *getCurrentFileLexer()->getFileEntry() - : static_cast(nullptr)); + case tok::pp_embed: { + if (auto *CurrentFileLexer = getCurrentFileLexer()) + if (auto FERef = CurrentFileLexer->getFileEntry()) + return HandleEmbedDirective(SavedHash.getLocation(), Result, *FERef); + return HandleEmbedDirective(SavedHash.getLocation(), Result, nullptr); + } case tok::pp_assert: //isExtension = true; // FIXME: implement #assert break; diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index 990689c6b1e45..f32fe5f6342be 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -463,6 +463,40 @@ TEST_F(PPCallbacksTest, FileNotFoundSkipped) { ASSERT_EQ(0u, DiagConsumer->getNumErrors()); } +TEST_F(PPCallbacksTest, EmbedFileNotFoundChained) { + const char *SourceText = "#embed \"notfound.h\"\n"; + + std::unique_ptr SourceBuf = + llvm::MemoryBuffer::getMemBuffer(SourceText); + SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf))); + + HeaderSearchOptions HSOpts; + TrivialModuleLoader ModLoader; + PreprocessorOptions PPOpts; + HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get()); + + DiagnosticConsumer *DiagConsumer = new DiagnosticConsumer; + DiagnosticsEngine EmbedFileNotFoundDiags(DiagID, DiagOpts, DiagConsumer); + Preprocessor PP(PPOpts, EmbedFileNotFoundDiags, LangOpts, SourceMgr, + HeaderInfo, ModLoader, /*IILookup=*/nullptr, + /*OwnsHeaderSearch=*/false); + PP.Initialize(*Target); + + class EmbedFileNotFoundCallbacks : public PPCallbacks { + public: + bool EmbedFileNotFound(StringRef FileName) override { return true; } + }; + + PP.addPPCallbacks(std::make_unique()); + PP.addPPCallbacks(std::make_unique()); + + // Lex source text. + PP.EnterMainSourceFile(); + PP.LexTokensUntilEOF(); + + ASSERT_EQ(0u, DiagConsumer->getNumErrors()); +} + TEST_F(PPCallbacksTest, OpenCLExtensionPragmaEnabled) { const char* Source = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"; From 901a4ed5cc262d976137ee766c7fde10155e46d9 Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Wed, 3 Dec 2025 11:41:18 +0000 Subject: [PATCH 3/3] Fix nits --- clang/lib/Lex/PPDirectives.cpp | 4 ++-- clang/unittests/Lex/PPCallbacksTest.cpp | 28 ++++++++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 1c3d9480651da..764a893eebe3c 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1398,8 +1398,8 @@ void Preprocessor::HandleDirective(Token &Result) { case tok::pp_sccs: return HandleIdentSCCSDirective(Result); case tok::pp_embed: { - if (auto *CurrentFileLexer = getCurrentFileLexer()) - if (auto FERef = CurrentFileLexer->getFileEntry()) + if (PreprocessorLexer *CurrentFileLexer = getCurrentFileLexer()) + if (OptionalFileEntryRef FERef = CurrentFileLexer->getFileEntry()) return HandleEmbedDirective(SavedHash.getLocation(), Result, *FERef); return HandleEmbedDirective(SavedHash.getLocation(), Result, nullptr); } diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index f32fe5f6342be..9533fbc776e6e 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -437,6 +437,7 @@ TEST_F(PPCallbacksTest, FileNotFoundSkipped) { PreprocessorOptions PPOpts; HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get()); + unsigned int NumCalls = 0; DiagnosticConsumer *DiagConsumer = new DiagnosticConsumer; DiagnosticsEngine FileNotFoundDiags(DiagID, DiagOpts, DiagConsumer); Preprocessor PP(PPOpts, FileNotFoundDiags, LangOpts, SourceMgr, HeaderInfo, @@ -445,21 +446,23 @@ TEST_F(PPCallbacksTest, FileNotFoundSkipped) { class FileNotFoundCallbacks : public PPCallbacks { public: - unsigned int NumCalls = 0; + unsigned int &NumCalls; + + FileNotFoundCallbacks(unsigned int &NumCalls) : NumCalls(NumCalls) {} + bool FileNotFound(StringRef FileName) override { NumCalls++; return FileName == "skipped.h"; } }; - auto *Callbacks = new FileNotFoundCallbacks; - PP.addPPCallbacks(std::unique_ptr(Callbacks)); + PP.addPPCallbacks(std::make_unique(NumCalls)); // Lex source text. PP.EnterMainSourceFile(); PP.LexTokensUntilEOF(); - ASSERT_EQ(1u, Callbacks->NumCalls); + ASSERT_EQ(1u, NumCalls); ASSERT_EQ(0u, DiagConsumer->getNumErrors()); } @@ -470,6 +473,7 @@ TEST_F(PPCallbacksTest, EmbedFileNotFoundChained) { llvm::MemoryBuffer::getMemBuffer(SourceText); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf))); + unsigned int NumCalls = 0; HeaderSearchOptions HSOpts; TrivialModuleLoader ModLoader; PreprocessorOptions PPOpts; @@ -484,16 +488,26 @@ TEST_F(PPCallbacksTest, EmbedFileNotFoundChained) { class EmbedFileNotFoundCallbacks : public PPCallbacks { public: - bool EmbedFileNotFound(StringRef FileName) override { return true; } + unsigned int &NumCalls; + + EmbedFileNotFoundCallbacks(unsigned int &NumCalls) : NumCalls(NumCalls) {} + + bool EmbedFileNotFound(StringRef FileName) override { + NumCalls++; + return true; + } }; - PP.addPPCallbacks(std::make_unique()); - PP.addPPCallbacks(std::make_unique()); + // Add two instances of `EmbedFileNotFoundCallbacks` to ensure the + // preprocessor is using an instance of `PPChainedCallbaks`. + PP.addPPCallbacks(std::make_unique(NumCalls)); + PP.addPPCallbacks(std::make_unique(NumCalls)); // Lex source text. PP.EnterMainSourceFile(); PP.LexTokensUntilEOF(); + ASSERT_EQ(2u, NumCalls); ASSERT_EQ(0u, DiagConsumer->getNumErrors()); }