[clang] 10b965f - [Clang] ASTUnit should use the CompilerInstance's CodeGenOptions (#195338)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 9 19:55:45 PDT 2026
Author: Sirraide
Date: 2026-07-10T04:55:40+02:00
New Revision: 10b965f0788ac4cf9a2c9ebd6c65d433aad19729
URL: https://github.com/llvm/llvm-project/commit/10b965f0788ac4cf9a2c9ebd6c65d433aad19729
DIFF: https://github.com/llvm/llvm-project/commit/10b965f0788ac4cf9a2c9ebd6c65d433aad19729.diff
LOG: [Clang] ASTUnit should use the CompilerInstance's CodeGenOptions (#195338)
Currently, `ASTUnit::LoadFromCompilerInvocation()` just calls the
constructor of `ASTUnit`, which default-constructs a `CodeGenOptions`
instance. The options from the `CompilerInstance` are never actually
saved in the `ASTUnit`. As a result, serialising the `ASTUnit` ends up
serialising the default-constructed `CodeGenOptions` rather than the
_actual_ `CodeGenOptions`.
This is problematic if you attempt to do the following:
1. Call e.g. `buildASTFromCodeWithArgs()` to build an `ASTUnit`
2. Serialise that `ASTUnit`.
3. Call e.g. `buildASTFromCodeWithArgs()` again with the exact same
arguments and add use the first `ASTUnit` as a PCH using `-include-pch`.
This causes Clang to error because the `CodeGenOptions` we deserialised
for the first `ASTUnit` (the default-constructed ones) are incompatible
with the `CodeGenOptions` implicitly created for the second TU (which
were created by the `CompilerInstance` and potentially modified due to
command-line argument parsing)... despite the fact that we basically
just attempted to build two TUs with the same arguments.
To fix this, copy the `CodeGenOptions` from the `CompilerInstance` into
the `ASTUnit`.
Added:
Modified:
clang/lib/Frontend/ASTUnit.cpp
clang/unittests/Frontend/ASTUnitTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 2974cf2660184..75e4f7772f47c 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1679,6 +1679,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
// Create the AST unit.
std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
+ *AST->CodeGenOpts = CI->getCodeGenOpts();
AST->DiagOpts = DiagOpts;
AST->Diagnostics = Diags;
AST->OnlyLocalDecls = OnlyLocalDecls;
diff --git a/clang/unittests/Frontend/ASTUnitTest.cpp b/clang/unittests/Frontend/ASTUnitTest.cpp
index bf9e4e184b5db..08dcd80a414ef 100644
--- a/clang/unittests/Frontend/ASTUnitTest.cpp
+++ b/clang/unittests/Frontend/ASTUnitTest.cpp
@@ -38,13 +38,15 @@ class ASTUnitTest : public ::testing::Test {
std::shared_ptr<CompilerInvocation> CInvok;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
- std::unique_ptr<ASTUnit> createASTUnit(bool isVolatile) {
+ std::unique_ptr<ASTUnit>
+ createASTUnit(bool isVolatile, ArrayRef<const char *> ExtraArgs = {}) {
EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD,
InputFileName));
input_file = std::make_unique<ToolOutputFile>(InputFileName, FD);
input_file->os() << "";
- const char *Args[] = {"clang", "-xc++", InputFileName.c_str()};
+ SmallVector<const char *> Args{"clang", "-xc++", InputFileName.c_str()};
+ append_range(Args, ExtraArgs);
auto VFS = llvm::vfs::getRealFileSystem();
Diags = CompilerInstance::createDiagnostics(*VFS, *DiagOpts);
@@ -109,6 +111,42 @@ TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) {
EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
}
+TEST_F(ASTUnitTest, SaveLoadPreservesCodeGenOptions) {
+ // Check that the CodeGenOptions are preserved when saving and loading an
+ // ASTUnit from a file.
+
+ {
+ std::unique_ptr<ASTUnit> AST = createASTUnit(false);
+ if (!AST)
+ FAIL() << "failed to create ASTUnit";
+ EXPECT_EQ(AST->getCodeGenOpts().OptimizationLevel, 0u);
+ }
+
+ std::unique_ptr<ASTUnit> AST = createASTUnit(false, {"-O3"});
+ if (!AST)
+ FAIL() << "failed to create ASTUnit";
+ EXPECT_EQ(AST->getCodeGenOpts().OptimizationLevel, 3u);
+
+ llvm::SmallString<256> ASTFileName;
+ ASSERT_FALSE(
+ llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
+ ToolOutputFile ast_file(ASTFileName, FD);
+ AST->Save(ASTFileName.str());
+
+ EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
+ HeaderSearchOptions HSOpts;
+
+ std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
+ ASTFileName, PCHContainerOps->getRawReader(), ASTUnit::LoadEverything,
+ llvm::vfs::getRealFileSystem(), DiagOpts, Diags, FileSystemOptions(),
+ HSOpts);
+
+ if (!AU)
+ FAIL() << "failed to load ASTUnit";
+
+ EXPECT_EQ(AU->getCodeGenOpts().OptimizationLevel, 3u);
+}
+
TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) {
std::unique_ptr<ASTUnit> AST = createASTUnit(true);
More information about the cfe-commits
mailing list