[clang] 73fc71b - [clang][test] Fix lifetimes of HS/PP options (#225885)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 25 08:57:52 PDT 2026
Author: Jan Svoboda
Date: 2026-09-25T08:57:45-07:00
New Revision: 73fc71b19905b15e6ff14ae3149c6fabce961c1b
URL: https://github.com/llvm/llvm-project/commit/73fc71b19905b15e6ff14ae3149c6fabce961c1b
DIFF: https://github.com/llvm/llvm-project/commit/73fc71b19905b15e6ff14ae3149c6fabce961c1b.diff
LOG: [clang][test] Fix lifetimes of HS/PP options (#225885)
PR #133467 changed how lifetimes work for `PreprocessorOptions`. In
LexerTest.cpp, the lifetimes were set up incorrectly, leading to
potential use-after-free crashes. This PR fixes that by expanding the
lifetime of both `PreprocessorOptions` and `HeaderSearchOptions`.
Added:
Modified:
clang/unittests/Lex/LexerTest.cpp
Removed:
################################################################################
diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp
index eaac861fa5e2c..8f632ccc5b931 100644
--- a/clang/unittests/Lex/LexerTest.cpp
+++ b/clang/unittests/Lex/LexerTest.cpp
@@ -43,34 +43,29 @@ class LexerTest : public ::testing::Test {
LexerTest()
: FileMgr(FileMgrOpts),
Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()),
- SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
- TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
- Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);
- }
-
- std::unique_ptr<Preprocessor> CreatePP(StringRef Source,
- TrivialModuleLoader &ModLoader) {
+ SourceMgr(Diags, FileMgr), TargetOpts([] {
+ TargetOptions TargetOpts;
+ TargetOpts.Triple = "x86_64-apple-darwin11.1.0";
+ return TargetOpts;
+ }()),
+ Target(TargetInfo::CreateTargetInfo(Diags, TargetOpts)),
+ HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get()),
+ PP(std::make_unique<Preprocessor>(PPOpts, Diags, LangOpts, SourceMgr,
+ HeaderInfo, ModLoader)) {}
+
+ void InitializePP(StringRef Source) {
std::unique_ptr<llvm::MemoryBuffer> Buf =
llvm::MemoryBuffer::getMemBuffer(Source);
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
- HeaderSearchOptions HSOpts;
- HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());
- PreprocessorOptions PPOpts;
- std::unique_ptr<Preprocessor> PP = std::make_unique<Preprocessor>(
- PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,
- /*IILookup =*/nullptr,
- /*OwnsHeaderSearch =*/false);
if (!PreDefines.empty())
PP->setPredefines(PreDefines);
PP->Initialize(*Target);
PP->EnterMainSourceFile();
- return PP;
}
std::vector<Token> Lex(StringRef Source) {
- TrivialModuleLoader ModLoader;
- PP = CreatePP(Source, ModLoader);
+ InitializePP(Source);
std::vector<Token> toks;
PP->LexTokensUntilEOF(&toks);
@@ -130,8 +125,12 @@ class LexerTest : public ::testing::Test {
DiagnosticsEngine Diags;
SourceManager SourceMgr;
LangOptions LangOpts;
- std::shared_ptr<TargetOptions> TargetOpts;
+ TargetOptions TargetOpts;
IntrusiveRefCntPtr<TargetInfo> Target;
+ HeaderSearchOptions HSOpts;
+ HeaderSearch HeaderInfo;
+ TrivialModuleLoader ModLoader;
+ PreprocessorOptions PPOpts;
std::unique_ptr<Preprocessor> PP;
std::string PreDefines;
};
@@ -471,8 +470,7 @@ TEST_F(LexerTest, DontMergeMacroArgsFromDifferentMacroFiles) {
}
TEST_F(LexerTest, DontOverallocateStringifyArgs) {
- TrivialModuleLoader ModLoader;
- auto PP = CreatePP("\"StrArg\", 5, 'C'", ModLoader);
+ InitializePP("\"StrArg\", 5, 'C'");
llvm::BumpPtrAllocator Allocator;
std::array<IdentifierInfo *, 3> ParamList;
@@ -498,7 +496,7 @@ TEST_F(LexerTest, DontOverallocateStringifyArgs) {
ArgTokens.push_back(tok);
}
- auto MacroArgsDeleter = [&PP](MacroArgs *M) { M->destroy(*PP); };
+ auto MacroArgsDeleter = [this](MacroArgs *M) { M->destroy(*PP); };
std::unique_ptr<MacroArgs, decltype(MacroArgsDeleter)> MA(
MacroArgs::create(MI, ArgTokens, false, *PP), MacroArgsDeleter);
auto StringifyArg = [&](int ArgNo) {
@@ -571,9 +569,15 @@ TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) {
}
}
-TEST_F(LexerTest, AvoidPastEndOfStringDereference) {
+TEST_F(LexerTest, AvoidPastEndOfStringDereference01) {
EXPECT_TRUE(Lex(" // \\\n").empty());
+}
+
+TEST_F(LexerTest, AvoidPastEndOfStringDereference02) {
EXPECT_TRUE(Lex("#include <\\\\").empty());
+}
+
+TEST_F(LexerTest, AvoidPastEndOfStringDereference03) {
EXPECT_TRUE(Lex("#include <\\\\\n").empty());
}
@@ -709,8 +713,7 @@ TEST_F(LexerTest, FindPreviousTokenIncludingComments) {
}
TEST_F(LexerTest, CreatedFIDCountForPredefinedBuffer) {
- TrivialModuleLoader ModLoader;
- auto PP = CreatePP("", ModLoader);
+ InitializePP("");
PP->LexTokensUntilEOF();
EXPECT_EQ(SourceMgr.getNumCreatedFIDsForFileID(PP->getPredefinesFileID()),
1U);
@@ -804,51 +807,46 @@ TEST(LexerPreambleTest, PreambleBounds) {
}
}
-TEST_F(LexerTest, CheckFirstPPToken) {
+TEST_F(LexerTest, CheckFirstPPToken01) {
LangOpts.CPlusPlusModules = true;
- {
- TrivialModuleLoader ModLoader;
- auto PP = CreatePP("// This is a comment\n"
- "int a;",
- ModLoader);
- Token Tok;
- PP->Lex(Tok);
- EXPECT_TRUE(Tok.is(tok::kw_int));
- EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc().isValid());
- EXPECT_EQ(PP->getMainFileFirstPPTokenLoc(), Tok.getLocation());
- }
- {
- TrivialModuleLoader ModLoader;
- auto PP = CreatePP("// This is a comment\n"
- "#define FOO int\n"
- "FOO a;",
- ModLoader);
- Token Tok;
- PP->Lex(Tok);
- EXPECT_TRUE(Tok.is(tok::kw_int));
- EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok,
- PP->getSourceManager(), PP->getLangOpts(),
- /*IgnoreWhiteSpace=*/false));
- EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation());
- EXPECT_TRUE(Tok.is(tok::hash));
- }
+ InitializePP("// This is a comment\n"
+ "int a;");
+ Token Tok;
+ PP->Lex(Tok);
+ EXPECT_TRUE(Tok.is(tok::kw_int));
+ EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc().isValid());
+ EXPECT_EQ(PP->getMainFileFirstPPTokenLoc(), Tok.getLocation());
+}
- {
- PreDefines = "#define FOO int\n";
- TrivialModuleLoader ModLoader;
- auto PP = CreatePP("// This is a comment\n"
- "FOO a;",
- ModLoader);
- Token Tok;
- PP->Lex(Tok);
- EXPECT_TRUE(Tok.is(tok::kw_int));
- EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok,
- PP->getSourceManager(), PP->getLangOpts(),
- /*IgnoreWhiteSpace=*/false));
- EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation());
- EXPECT_TRUE(Tok.is(tok::raw_identifier));
- EXPECT_TRUE(Tok.getRawIdentifier() == "FOO");
- }
+TEST_F(LexerTest, CheckFirstPPToken02) {
+ LangOpts.CPlusPlusModules = true;
+ InitializePP("// This is a comment\n"
+ "#define FOO int\n"
+ "FOO a;");
+ Token Tok;
+ PP->Lex(Tok);
+ EXPECT_TRUE(Tok.is(tok::kw_int));
+ EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok,
+ PP->getSourceManager(), PP->getLangOpts(),
+ /*IgnoreWhiteSpace=*/false));
+ EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation());
+ EXPECT_TRUE(Tok.is(tok::hash));
+}
+
+TEST_F(LexerTest, CheckFirstPPToken03) {
+ LangOpts.CPlusPlusModules = true;
+ PreDefines = "#define FOO int\n";
+ InitializePP("// This is a comment\n"
+ "FOO a;");
+ Token Tok;
+ PP->Lex(Tok);
+ EXPECT_TRUE(Tok.is(tok::kw_int));
+ EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok,
+ PP->getSourceManager(), PP->getLangOpts(),
+ /*IgnoreWhiteSpace=*/false));
+ EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation());
+ EXPECT_TRUE(Tok.is(tok::raw_identifier));
+ EXPECT_TRUE(Tok.getRawIdentifier() == "FOO");
}
TEST_F(LexerTest, FindEndOfIdentifierContinuation) {
More information about the cfe-commits
mailing list