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); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
