[clang] [clang-tools-extra] [lldb] [llvm] [clang][modules] Serialize `CodeGenOptions` (PR #146422)
Jan Svoboda via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 15 11:24:04 PDT 2025
https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/146422
>From 69049bfcd81134f3787d1ee14ab3e5c6d91eb87d Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 3 Jul 2025 12:46:58 -0700
Subject: [PATCH 1/4] [clang][modules] Serialize `CodeGenOptions`
---
clang-tools-extra/clangd/ModulesBuilder.cpp | 3 +-
clang/include/clang/Basic/CodeGenOptions.def | 30 ++--
clang/include/clang/Basic/CodeGenOptions.h | 20 ++-
clang/include/clang/Basic/DebugOptions.def | 58 ++++----
.../Basic/DiagnosticSerializationKinds.td | 4 +
clang/include/clang/Basic/LangOptions.def | 3 -
clang/include/clang/Frontend/ASTUnit.h | 2 +
.../include/clang/Frontend/CompilerInstance.h | 1 +
.../include/clang/Serialization/ASTBitCodes.h | 5 +-
clang/include/clang/Serialization/ASTReader.h | 39 ++++--
clang/include/clang/Serialization/ASTWriter.h | 21 ++-
clang/lib/Basic/CodeGenOptions.cpp | 6 +-
clang/lib/CodeGen/CGDebugInfo.cpp | 34 +++--
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 4 +-
clang/lib/CodeGen/CodeGenAction.cpp | 2 +-
clang/lib/Frontend/ASTUnit.cpp | 36 +++--
clang/lib/Frontend/ChainedIncludesSource.cpp | 5 +-
clang/lib/Frontend/CompilerInstance.cpp | 8 +-
clang/lib/Frontend/CompilerInvocation.cpp | 37 +++--
clang/lib/Frontend/FrontendAction.cpp | 5 +-
clang/lib/Frontend/FrontendActions.cpp | 17 +--
clang/lib/Frontend/InitPreprocessor.cpp | 12 +-
clang/lib/Frontend/PrecompiledPreamble.cpp | 8 +-
clang/lib/Serialization/ASTReader.cpp | 130 +++++++++++++++++-
clang/lib/Serialization/ASTWriter.cpp | 21 ++-
clang/lib/Serialization/GeneratePCH.cpp | 6 +-
clang/test/PCH/no-validate-pch.cl | 2 +-
llvm/clang/test/Modules/implicit-opt-level.c | 15 ++
28 files changed, 386 insertions(+), 148 deletions(-)
create mode 100644 llvm/clang/test/Modules/implicit-opt-level.c
diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp
index d88aa01aad05d..b9aeb3889f5f2 100644
--- a/clang-tools-extra/clangd/ModulesBuilder.cpp
+++ b/clang-tools-extra/clangd/ModulesBuilder.cpp
@@ -209,8 +209,9 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath,
IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();
PCHContainerOperations PCHOperations;
+ CodeGenOptions CodeGenOpts;
ASTReader Reader(PP, *ModCache, /*ASTContext=*/nullptr,
- PCHOperations.getRawReader(), {});
+ PCHOperations.getRawReader(), CodeGenOpts, {});
// We don't need any listener here. By default it will use a validator
// listener.
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 41031026c99f6..a11e12d495cd2 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -209,17 +209,17 @@ CODEGENOPT(ObjCAvoidHeapifyLocalBlocks, 1, 0, Benign)
// The optimization options affect frontend options, which in turn do affect the AST.
-VALUE_CODEGENOPT(OptimizationLevel, 2, 0, Affecting) ///< The -O[0-3] option specified.
-VALUE_CODEGENOPT(OptimizeSize, 2, 0, Affecting) ///< If -Os (==1, Benign) or -Oz (==2, Benign) is specified.
+VALUE_CODEGENOPT(OptimizationLevel, 2, 0, Compatible) ///< The -O[0-3] option specified.
+VALUE_CODEGENOPT(OptimizeSize, 2, 0, Compatible) ///< If -Os (==1, Benign) or -Oz (==2, Benign) is specified.
CODEGENOPT(AtomicProfileUpdate , 1, 0, Benign) ///< Set -fprofile-update=atomic
CODEGENOPT(ContinuousProfileSync, 1, 0, Benign) ///< Enable continuous instrumentation profiling
/// Choose profile instrumenation kind or no instrumentation.
-ENUM_CODEGENOPT(ProfileInstr, llvm::driver::ProfileInstrKind, 4, llvm::driver::ProfileInstrKind::ProfileNone, Benign)
+ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 4, ProfileInstrKind::ProfileNone, Benign)
/// Choose profile kind for PGO use compilation.
-ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::ProfileInstrKind::ProfileNone, Benign)
+ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileInstrKind::ProfileNone, Benign)
/// Partition functions into N groups and select only functions in group i to be
/// instrumented. Selected group numbers can be 0 to N-1 inclusive.
VALUE_CODEGENOPT(ProfileTotalFunctionGroups, 32, 1, Benign)
@@ -244,8 +244,8 @@ CODEGENOPT(SaveTempLabels , 1, 0, Benign) ///< Save temporary labels.
CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0, Benign) ///< Enable use-after-scope detection
///< in AddressSanitizer
ENUM_CODEGENOPT(SanitizeAddressUseAfterReturn,
- llvm::AsanDetectStackUseAfterReturnMode, 2,
- llvm::AsanDetectStackUseAfterReturnMode::Runtime,
+ AsanDetectStackUseAfterReturnMode, 2,
+ AsanDetectStackUseAfterReturnMode::Runtime,
Benign
) ///< Set detection mode for stack-use-after-return.
CODEGENOPT(SanitizeAddressPoisonCustomArrayCookie, 1, 0, Benign) ///< Enable poisoning operator new[] which is not a replaceable
@@ -255,9 +255,9 @@ CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0, Benign) ///< Enable linker
CODEGENOPT(SanitizeAddressUseOdrIndicator, 1, 0, Benign) ///< Enable ODR indicator globals
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0, Benign) ///< Enable tracking origins in
///< MemorySanitizer
-ENUM_CODEGENOPT(SanitizeAddressDtor, llvm::AsanDtorKind, 2,
- llvm::AsanDtorKind::Global, Benign) ///< Set how ASan global
- ///< destructors are emitted.
+ENUM_CODEGENOPT(SanitizeAddressDtor, AsanDtorKind, 2,
+ AsanDtorKind::Global, Benign) ///< Set how ASan global
+ ///< destructors are emitted.
CODEGENOPT(SanitizeMemoryParamRetval, 1, 0, Benign) ///< Enable detection of uninitialized
///< parameters and return values
///< in MemorySanitizer
@@ -375,13 +375,13 @@ VALUE_CODEGENOPT(SmallDataLimit, 32, 0, Benign)
VALUE_CODEGENOPT(SSPBufferSize, 32, 0, Benign)
/// The kind of inlining to perform.
-ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining, Benign)
+ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining, Compatible)
/// The maximum stack size a function can have to be considered for inlining.
VALUE_CODEGENOPT(InlineMaxStackSize, 32, UINT_MAX, Benign)
// Vector functions library to use.
-ENUM_CODEGENOPT(VecLib, llvm::driver::VectorLibrary, 4, llvm::driver::VectorLibrary::NoLibrary, Benign)
+ENUM_CODEGENOPT(VecLib, VectorLibrary, 4, VectorLibrary::NoLibrary, Benign)
/// The default TLS model to use.
ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel, Benign)
@@ -457,8 +457,8 @@ ENUM_CODEGENOPT(SwiftAsyncFramePointer, SwiftAsyncFramePointerKind, 2,
CODEGENOPT(SkipRaxSetup, 1, 0, Benign)
/// Whether to zero out caller-used registers before returning.
-ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind,
- 5, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip, Benign)
+ENUM_CODEGENOPT(ZeroCallUsedRegs, ZeroCallUsedRegsKind,
+ 5, ZeroCallUsedRegsKind::Skip, Benign)
/// Modify C++ ABI to returning `this` pointer from constructors and
/// non-deleting destructors. (No effect on Microsoft ABI.)
@@ -477,8 +477,8 @@ CODEGENOPT(ResMayAlias, 1, 0, Benign)
/// Controls how unwind v2 (epilog) information should be generated for x64
/// Windows.
-ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode,
- 2, llvm::WinX64EHUnwindV2Mode::Disabled, Benign)
+ENUM_CODEGENOPT(WinX64EHUnwindV2, WinX64EHUnwindV2Mode,
+ 2, WinX64EHUnwindV2Mode::Disabled, Benign)
/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index fe634d221b424..7cd5ea3256cdb 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -46,13 +46,31 @@ class CodeGenOptionsBase {
enum class CompatibilityKind {
/// Does affect the construction of the AST in a way that does prevent
/// module interoperability.
- Affecting,
+ NotCompatible,
+ /// Does affect the construction of the AST in a way that doesn't prevent
+ /// interoperability (that is, the value can be different between an
+ /// explicit module and the user of that module).
+ Compatible,
/// Does not affect the construction of the AST in any way (that is, the
/// value can be different between an implicit module and the user of that
/// module).
Benign,
};
+ using CFBranchLabelSchemeKind = CFBranchLabelSchemeKind;
+ using ProfileInstrKind = llvm::driver::ProfileInstrKind;
+ using AsanDetectStackUseAfterReturnMode = llvm::AsanDetectStackUseAfterReturnMode;
+ using AsanDtorKind = llvm::AsanDtorKind;
+ using VectorLibrary = llvm::driver::VectorLibrary;
+ using ZeroCallUsedRegsKind = llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind;
+ using WinX64EHUnwindV2Mode = llvm::WinX64EHUnwindV2Mode;
+
+ using DebugCompressionType = llvm::DebugCompressionType;
+ using EmitDwarfUnwindType = llvm::EmitDwarfUnwindType;
+ using DebugTemplateNamesKind = llvm::codegenoptions::DebugTemplateNamesKind;
+ using DebugInfoKind = llvm::codegenoptions::DebugInfoKind;
+ using DebuggerKind = llvm::DebuggerKind;
+
#define CODEGENOPT(Name, Bits, Default, Compatibility) unsigned Name : Bits;
#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility)
#include "clang/Basic/CodeGenOptions.def"
diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def
index e2ab06184b96a..c6e736e92744c 100644
--- a/clang/include/clang/Basic/DebugOptions.def
+++ b/clang/include/clang/Basic/DebugOptions.def
@@ -28,9 +28,9 @@ VALUE_CODEGENOPT(Name, Bits, Default, Compatibility)
ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility)
#endif
-ENUM_DEBUGOPT(CompressDebugSections, llvm::DebugCompressionType, 2,
- llvm::DebugCompressionType::None, Benign)
-DEBUGOPT(Dwarf64, 1, 0, Affecting) ///< -gdwarf64.
+ENUM_DEBUGOPT(CompressDebugSections, DebugCompressionType, 2,
+ DebugCompressionType::None, Benign)
+DEBUGOPT(Dwarf64, 1, 0, Compatible) ///< -gdwarf64.
DEBUGOPT(EnableDIPreservationVerify, 1, 0, Benign) ///< Enable di preservation
///< verify each (it means
///< check the original debug
@@ -40,8 +40,8 @@ DEBUGOPT(ForceDwarfFrameSection , 1, 0, Benign) ///< Set when -fforce-dwarf-fram
///< is enabled.
///< Set when -femit-dwarf-unwind is passed.
-ENUM_DEBUGOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2,
- llvm::EmitDwarfUnwindType::Default, Benign)
+ENUM_DEBUGOPT(EmitDwarfUnwind, EmitDwarfUnwindType, 2,
+ EmitDwarfUnwindType::Default, Benign)
DEBUGOPT(NoDwarfDirectoryAsm , 1, 0, Benign) ///< Set when -fno-dwarf-directory-asm
///< is enabled.
@@ -49,8 +49,8 @@ DEBUGOPT(NoDwarfDirectoryAsm , 1, 0, Benign) ///< Set when -fno-dwarf-directory-
DEBUGOPT(NoInlineLineTables, 1, 0, Benign) ///< Whether debug info should contain
///< inline line tables.
-DEBUGOPT(DebugStrictDwarf, 1, 1, Affecting) ///< Whether or not to use strict DWARF info.
-DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0, Affecting) ///< Omit unreferenced member
+DEBUGOPT(DebugStrictDwarf, 1, 1, Compatible) ///< Whether or not to use strict DWARF info.
+DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0, Compatible) ///< Omit unreferenced member
///< functions in type debug info.
/// Control the Assignment Tracking debug info feature.
@@ -60,73 +60,73 @@ ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2,
/// Whether or not to use Key Instructions to determine breakpoint locations.
DEBUGOPT(DebugKeyInstructions, 1, 0, Benign)
-DEBUGOPT(DebugColumnInfo, 1, 0, Affecting) ///< Whether or not to use column information
+DEBUGOPT(DebugColumnInfo, 1, 0, Compatible) ///< Whether or not to use column information
///< in debug info.
-DEBUGOPT(DebugTypeExtRefs, 1, 0, Affecting) ///< Whether or not debug info should contain
+DEBUGOPT(DebugTypeExtRefs, 1, 0, Compatible) ///< Whether or not debug info should contain
///< external references to a PCH or module.
-DEBUGOPT(DebugExplicitImport, 1, 0, Affecting) ///< Whether or not debug info should
+DEBUGOPT(DebugExplicitImport, 1, 0, Compatible) ///< Whether or not debug info should
///< contain explicit imports for
///< anonymous namespaces
/// Set debug info source file hashing algorithm.
-ENUM_DEBUGOPT(DebugSrcHash, DebugSrcHashKind, 2, DSH_MD5, Affecting)
+ENUM_DEBUGOPT(DebugSrcHash, DebugSrcHashKind, 2, DSH_MD5, Compatible)
-DEBUGOPT(SplitDwarfInlining, 1, 1, Affecting) ///< Whether to include inlining info in the
+DEBUGOPT(SplitDwarfInlining, 1, 1, Compatible) ///< Whether to include inlining info in the
///< skeleton CU to allow for symbolication
///< of inline stack frames without .dwo files.
-DEBUGOPT(DebugFwdTemplateParams, 1, 0, Affecting) ///< Whether to emit complete
+DEBUGOPT(DebugFwdTemplateParams, 1, 0, Compatible) ///< Whether to emit complete
///< template parameter descriptions in
///< forward declarations (versus just
///< including them in the name).
ENUM_DEBUGOPT(DebugSimpleTemplateNames,
- llvm::codegenoptions::DebugTemplateNamesKind, 2,
- llvm::codegenoptions::DebugTemplateNamesKind::Full, Affecting)
+ DebugTemplateNamesKind, 2,
+ DebugTemplateNamesKind::Full, Compatible)
///< Whether to emit template parameters in the textual names of
///< template specializations.
///< Implies DebugFwdTemplateNames to allow decorated names to be
///< reconstructed when needed.
/// The kind of generated debug info.
-ENUM_DEBUGOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4,
- llvm::codegenoptions::NoDebugInfo, Affecting)
+ENUM_DEBUGOPT(DebugInfo, DebugInfoKind, 4,
+ DebugInfoKind::NoDebugInfo, Compatible)
/// Whether to generate macro debug info.
-DEBUGOPT(MacroDebugInfo, 1, 0, Affecting)
+DEBUGOPT(MacroDebugInfo, 1, 0, Compatible)
/// Tune the debug info for this debugger.
-ENUM_DEBUGOPT(DebuggerTuning, llvm::DebuggerKind, 3,
- llvm::DebuggerKind::Default, Affecting)
+ENUM_DEBUGOPT(DebuggerTuning, DebuggerKind, 3,
+ DebuggerKind::Default, Compatible)
/// Dwarf version. Version zero indicates to LLVM that no DWARF should be
/// emitted.
-VALUE_DEBUGOPT(DwarfVersion, 3, 0, Affecting)
+VALUE_DEBUGOPT(DwarfVersion, 3, 0, Compatible)
/// Whether we should emit CodeView debug information. It's possible to emit
/// CodeView and DWARF into the same object.
-DEBUGOPT(EmitCodeView, 1, 0, Affecting)
+DEBUGOPT(EmitCodeView, 1, 0, Compatible)
/// Whether to emit the .debug$H section containing hashes of CodeView types.
-DEBUGOPT(CodeViewGHash, 1, 0, Affecting)
+DEBUGOPT(CodeViewGHash, 1, 0, Compatible)
/// Whether to emit the compiler path and command line into the CodeView debug information.
-DEBUGOPT(CodeViewCommandLine, 1, 0, Affecting)
+DEBUGOPT(CodeViewCommandLine, 1, 0, Compatible)
/// Whether emit extra debug info for sample pgo profile collection.
-DEBUGOPT(DebugInfoForProfiling, 1, 0, Affecting)
+DEBUGOPT(DebugInfoForProfiling, 1, 0, Compatible)
/// Whether to emit DW_TAG_template_alias for template aliases.
-DEBUGOPT(DebugTemplateAlias, 1, 0, Affecting)
+DEBUGOPT(DebugTemplateAlias, 1, 0, Compatible)
/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames.
-DEBUGOPT(DebugNameTable, 2, 0, Affecting)
+DEBUGOPT(DebugNameTable, 2, 0, Compatible)
/// Whether to use DWARF base address specifiers in .debug_ranges.
-DEBUGOPT(DebugRangesBaseAddress, 1, 0, Affecting)
+DEBUGOPT(DebugRangesBaseAddress, 1, 0, Compatible)
/// Whether to embed source in DWARF debug line section.
-DEBUGOPT(EmbedSource, 1, 0, Affecting)
+DEBUGOPT(EmbedSource, 1, 0, Compatible)
#undef DEBUGOPT
#undef ENUM_DEBUGOPT
diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index 584c8d62280bf..fc3585ffe8549 100644
--- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -41,6 +41,10 @@ def err_ast_file_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in
"precompiled file '%3' but is currently %select{disabled|enabled}2">;
def err_ast_file_langopt_value_mismatch : Error<
"%0 differs in precompiled file '%1' vs. current file">;
+def err_ast_file_codegenopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "
+ "precompiled file '%3' but is currently %select{disabled|enabled}2">;
+def err_ast_file_codegenopt_value_mismatch
+ : Error<"%0 differs in precompiled file '%1' vs. current file">;
def err_ast_file_diagopt_mismatch : Error<"%0 is currently enabled, but was not in "
"the precompiled file '%1'">;
def err_ast_file_modulecache_mismatch : Error<"precompiled file '%2' was compiled with module cache "
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 72321c204ce96..851074c500d6e 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -161,8 +161,6 @@ LANGOPT(ModulesValidateTextualHeaderIncludes, 1, 1, Compatible, "validation of t
LANGOPT(ModulesErrorRecovery, 1, 1, Benign, "automatically importing modules as needed when performing error recovery")
LANGOPT(ImplicitModules, 1, 1, Benign, "building modules that are not specified via -fmodule-file")
LANGOPT(ModulesLocalVisibility, 1, 0, Compatible, "local submodule visibility")
-LANGOPT(Optimize , 1, 0, Compatible, "__OPTIMIZE__ predefined macro")
-LANGOPT(OptimizeSize , 1, 0, Compatible, "__OPTIMIZE_SIZE__ predefined macro")
LANGOPT(Static , 1, 0, Compatible, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
VALUE_LANGOPT(PackStruct , 32, 0, NotCompatible,
"default struct packing maximum alignment")
@@ -179,7 +177,6 @@ VALUE_LANGOPT(PIE , 1, 0, Compatible, "is pie")
LANGOPT(ROPI , 1, 0, NotCompatible, "Read-only position independence")
LANGOPT(RWPI , 1, 0, NotCompatible, "Read-write position independence")
LANGOPT(GNUInline , 1, 0, Compatible, "GNU inline semantics")
-LANGOPT(NoInlineDefine , 1, 0, Compatible, "__NO_INLINE__ predefined macro")
LANGOPT(Deprecated , 1, 0, Compatible, "__DEPRECATED predefined macro")
LANGOPT(FastMath , 1, 0, Compatible, "fast FP math optimizations, and __FAST_MATH__ predefined macro")
LANGOPT(UnsafeFPMath , 1, 0, Compatible, "Unsafe Floating Point Math")
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index 1485192e8f1e3..1286fe4cca0f4 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -62,6 +62,7 @@ class ASTContext;
class ASTDeserializationListener;
class ASTMutationListener;
class ASTReader;
+class CodeGenOptions;
class CompilerInstance;
class CompilerInvocation;
class Decl;
@@ -107,6 +108,7 @@ class ASTUnit {
private:
std::unique_ptr<LangOptions> LangOpts;
+ std::unique_ptr<CodeGenOptions> CodeGenOpts;
// FIXME: The documentation on \c LoadFrom* member functions states that the
// DiagnosticsEngine (and therefore DiagnosticOptions) must outlive the
// returned ASTUnit. This is not the case. Enfore it by storing non-owning
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 0ae490f0e8073..2408367e19833 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -720,6 +720,7 @@ class CompilerInstance : public ModuleLoader {
DisableValidationForModuleKind DisableValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache,
ASTContext &Context, const PCHContainerReader &PCHContainerRdr,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener,
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 9d265f27b8e31..441047d64f48c 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -44,7 +44,7 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
-const unsigned VERSION_MAJOR = 34;
+const unsigned VERSION_MAJOR = 35;
/// AST file minor version number supported by this version of
/// Clang.
@@ -399,6 +399,9 @@ enum OptionsRecordTypes {
/// Record code for the preprocessor options table.
PREPROCESSOR_OPTIONS,
+
+ /// Record code for the codegen options table.
+ CODEGEN_OPTIONS,
};
/// Record codes for the unhashed control block.
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 3d96f8e65180d..7ce626cedae74 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -72,6 +72,7 @@ class ASTContext;
class ASTDeserializationListener;
class ASTReader;
class ASTRecordReader;
+class CodeGenOptions;
class CXXTemporary;
class Decl;
class DeclarationName;
@@ -137,6 +138,15 @@ class ASTReaderListener {
return false;
}
+ /// Receives the codegen options.
+ ///
+ /// \returns true to indicate the options are invalid or false otherwise.
+ virtual bool ReadCodeGenOptions(const CodeGenOptions &CGOpts,
+ StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) {
+ return false;
+ }
+
/// Receives the target options.
///
/// \returns true to indicate the target options are invalid, or false
@@ -281,6 +291,9 @@ class ChainedASTReaderListener : public ASTReaderListener {
bool ReadLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override;
+ bool ReadCodeGenOptions(const CodeGenOptions &CGOpts,
+ StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) override;
bool ReadTargetOptions(const TargetOptions &TargetOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override;
@@ -322,6 +335,9 @@ class PCHValidator : public ASTReaderListener {
bool ReadLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override;
+ bool ReadCodeGenOptions(const CodeGenOptions &CGOpts,
+ StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) override;
bool ReadTargetOptions(const TargetOptions &TargetOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override;
@@ -493,6 +509,9 @@ class ASTReader
/// The AST consumer.
ASTConsumer *Consumer = nullptr;
+ /// The codegen options.
+ const CodeGenOptions &CodeGenOpts;
+
/// The module manager which manages modules and their dependencies
ModuleManager ModuleMgr;
@@ -1580,6 +1599,10 @@ class ASTReader
StringRef ModuleFilename, bool Complain,
ASTReaderListener &Listener,
bool AllowCompatibleDifferences);
+ static bool ParseCodeGenOptions(const RecordData &Record,
+ StringRef ModuleFilename, bool Complain,
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences);
static bool ParseTargetOptions(const RecordData &Record,
StringRef ModuleFilename, bool Complain,
ASTReaderListener &Listener,
@@ -1771,6 +1794,7 @@ class ASTReader
/// deserializing.
ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context,
const PCHContainerReader &PCHContainerRdr,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
StringRef isysroot = "",
DisableValidationForModuleKind DisableValidationKind =
@@ -1789,6 +1813,7 @@ class ASTReader
SourceManager &getSourceManager() const { return SourceMgr; }
FileManager &getFileManager() const { return FileMgr; }
DiagnosticsEngine &getDiags() const { return Diags; }
+ const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
/// Flags that indicate what kind of AST loading failures the client
/// of the AST reader can directly handle.
@@ -1990,14 +2015,12 @@ class ASTReader
/// Determine whether the given AST file is acceptable to load into a
/// translation unit with the given language and target options.
- static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
- const ModuleCache &ModCache,
- const PCHContainerReader &PCHContainerRdr,
- const LangOptions &LangOpts,
- const TargetOptions &TargetOpts,
- const PreprocessorOptions &PPOpts,
- StringRef ExistingModuleCachePath,
- bool RequireStrictOptionMatches = false);
+ static bool isAcceptableASTFile(
+ StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
+ const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts,
+ const CodeGenOptions &CGOpts, const TargetOptions &TargetOpts,
+ const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath,
+ bool RequireStrictOptionMatches = false);
/// Returns the suggested contents of the predefines buffer,
/// which contains a (typically-empty) subset of the predefines
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index c86019f01d9f3..edf5bbaddf1aa 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -49,6 +49,7 @@ namespace clang {
class ASTContext;
class ASTReader;
class Attr;
+class CodeGenOptions;
class CXXRecordDecl;
class FileEntry;
class FPOptionsOverride;
@@ -124,6 +125,8 @@ class ASTWriter : public ASTDeserializationListener,
/// The PCM manager which manages memory buffers for pcm files.
ModuleCache &ModCache;
+ const CodeGenOptions &CodeGenOpts;
+
/// The preprocessor we're writing.
Preprocessor *PP = nullptr;
@@ -686,13 +689,14 @@ class ASTWriter : public ASTDeserializationListener,
/// Create a new precompiled header writer that outputs to
/// the given bitstream.
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
- ModuleCache &ModCache,
+ ModuleCache &ModCache, const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
bool GeneratingReducedBMI = false);
~ASTWriter() override;
const LangOptions &getLangOpts() const;
+ const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
/// Get a timestamp for output into the AST file. The actual timestamp
/// of the specified file may be ignored if we have been instructed to not
@@ -999,6 +1003,7 @@ class PCHGenerator : public SemaConsumer {
public:
PCHGenerator(Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile,
StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
bool BuildingImplicitModule = false,
@@ -1021,13 +1026,14 @@ class CXX20ModulesGenerator : public PCHGenerator {
virtual Module *getEmittingModule(ASTContext &Ctx) override;
CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
- StringRef OutputFile, bool GeneratingReducedBMI,
- bool AllowASTWithErrors);
+ StringRef OutputFile, const CodeGenOptions &CodeGenOpts,
+ bool GeneratingReducedBMI, bool AllowASTWithErrors);
public:
CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
- StringRef OutputFile, bool AllowASTWithErrors = false)
- : CXX20ModulesGenerator(PP, ModCache, OutputFile,
+ StringRef OutputFile, const CodeGenOptions &CodeGenOpts,
+ bool AllowASTWithErrors = false)
+ : CXX20ModulesGenerator(PP, ModCache, OutputFile, CodeGenOpts,
/*GeneratingReducedBMI=*/false,
AllowASTWithErrors) {}
@@ -1039,8 +1045,9 @@ class ReducedBMIGenerator : public CXX20ModulesGenerator {
public:
ReducedBMIGenerator(Preprocessor &PP, ModuleCache &ModCache,
- StringRef OutputFile, bool AllowASTWithErrors = false)
- : CXX20ModulesGenerator(PP, ModCache, OutputFile,
+ StringRef OutputFile, const CodeGenOptions &CodeGenOpts,
+ bool AllowASTWithErrors = false)
+ : CXX20ModulesGenerator(PP, ModCache, OutputFile, CodeGenOpts,
/*GeneratingReducedBMI=*/true,
AllowASTWithErrors) {}
};
diff --git a/clang/lib/Basic/CodeGenOptions.cpp b/clang/lib/Basic/CodeGenOptions.cpp
index 9a2aa9beb9e0d..ed877c40573ac 100644
--- a/clang/lib/Basic/CodeGenOptions.cpp
+++ b/clang/lib/Basic/CodeGenOptions.cpp
@@ -36,13 +36,13 @@ void CodeGenOptions::resetNonModularOptions(StringRef ModuleFormat) {
// emitted into the PCM (-gmodules).
if (ModuleFormat == "raw" && !DebugTypeExtRefs) {
#define DEBUGOPT(Name, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Affecting) \
+ if constexpr (CK::Compatibility != CK::Benign) \
Name = Default;
#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Affecting) \
+ if constexpr (CK::Compatibility == CK::Benign) \
Name = Default;
#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Affecting) \
+ if constexpr (CK::Compatibility == CK::Benign) \
set##Name(Default);
#include "clang/Basic/DebugOptions.def"
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 8bf7d24d8551d..875356455bca9 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -797,7 +797,8 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
TheCU = DBuilder.createCompileUnit(
LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "",
- LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO,
+ CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO ||
+ CGOpts.PrepareForThinLTO,
CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind,
DwoId, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
NameTableKind, CGOpts.DebugRangesBaseAddress, remapDIPath(Sysroot), SDK);
@@ -2282,7 +2283,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
Flags |= llvm::DINode::FlagRValueReference;
if (!Method->isExternallyVisible())
SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
- if (CGM.getLangOpts().Optimize)
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
// In this debug mode, emit type info for a class when its constructor type
@@ -4353,7 +4354,7 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC));
if (!FD->isExternallyVisible())
SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
- if (CGM.getLangOpts().Optimize)
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
if (Stub) {
@@ -4679,7 +4680,7 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (Fn->hasLocalLinkage())
SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
- if (CGM.getLangOpts().Optimize)
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs();
@@ -4762,7 +4763,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = 0;
llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero;
- if (CGM.getLangOpts().Optimize)
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
@@ -5094,7 +5095,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
// Use VarDecl's Tag, Scope and Line number.
auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
- Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize,
+ Scope, FieldName, Unit, Line, FieldTy,
+ CGM.getCodeGenOpts().OptimizationLevel != 0,
Flags | llvm::DINode::FlagArtificial, FieldAlign);
// Insert an llvm.dbg.declare into the current block.
@@ -5120,9 +5122,9 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
llvm::DILocalVariable *D = nullptr;
if (ArgNo) {
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD);
- D = DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags,
- Annotations);
+ D = DBuilder.createParameterVariable(
+ Scope, Name, *ArgNo, Unit, Line, Ty,
+ CGM.getCodeGenOpts().OptimizationLevel != 0, Flags, Annotations);
} else {
// For normal local variable, we will try to find out whether 'VD' is the
// copy parameter of coroutine.
@@ -5163,8 +5165,9 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
D = RemapCoroArgToLocalVar();
// Or we will create a new DIVariable for this Decl if D dose not exists.
if (!D)
- D = DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags, Align);
+ D = DBuilder.createAutoVariable(
+ Scope, Name, Unit, Line, Ty,
+ CGM.getCodeGenOpts().OptimizationLevel != 0, Flags, Align);
}
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -5218,7 +5221,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
// Create the descriptor for the variable.
llvm::DILocalVariable *D = DBuilder.createAutoVariable(
- Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize,
+ Scope, Name, Unit, Line, Ty, CGM.getCodeGenOpts().OptimizationLevel != 0,
llvm::DINode::FlagZero, Align);
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
@@ -5318,7 +5321,7 @@ void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) {
// Create the descriptor for the label.
auto *L = DBuilder.createLabel(
Scope, Name, Unit, Line, Column, /*IsArtificial=*/false,
- /*CoroSuspendIdx=*/std::nullopt, CGM.getLangOpts().Optimize);
+ /*CoroSuspendIdx=*/std::nullopt, CGM.getCodeGenOpts().OptimizationLevel != 0);
// Insert an llvm.dbg.label into the current block.
DBuilder.insertLabel(L,
@@ -5581,7 +5584,8 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
// Create the descriptor for the parameter.
auto *debugVar = DBuilder.createParameterVariable(
- scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags);
+ scope, Name, ArgNo, tunit, line, type,
+ CGM.getCodeGenOpts().OptimizationLevel != 0, flags);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(),
@@ -6356,7 +6360,7 @@ llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) {
llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const {
// Call site-related attributes are only useful in optimized programs, and
// when there's a possibility of debugging backtraces.
- if (!CGM.getLangOpts().Optimize ||
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0 ||
DebugKind == llvm::codegenoptions::NoDebugInfo ||
DebugKind == llvm::codegenoptions::LocTrackingOnly)
return llvm::DINode::FlagZero;
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 8ccc37ef98a74..d26461d8e427a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1092,7 +1092,7 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Name, &CGM.getModule());
CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
- if (CGM.getLangOpts().Optimize) {
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
Fn->removeFnAttr(llvm::Attribute::NoInline);
Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
Fn->addFnAttr(llvm::Attribute::AlwaysInline);
@@ -3199,7 +3199,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
&CGM.getModule());
CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
TaskPrivatesMapFnInfo);
- if (CGM.getLangOpts().Optimize) {
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 5493cc92bd8b0..eb5b6045510df 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -995,7 +995,7 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::vector<std::unique_ptr<ASTConsumer>> Consumers(2);
Consumers[0] = std::make_unique<ReducedBMIGenerator>(
CI.getPreprocessor(), CI.getModuleCache(),
- CI.getFrontendOpts().ModuleOutputPath);
+ CI.getFrontendOpts().ModuleOutputPath, CI.getCodeGenOpts());
Consumers[1] = std::move(Result);
return std::make_unique<MultiplexConsumer>(std::move(Consumers));
}
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 4ebec8e074330..dcf2865c94723 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -215,8 +215,8 @@ struct ASTUnit::ASTWriterData {
llvm::BitstreamWriter Stream;
ASTWriter Writer;
- ASTWriterData(ModuleCache &ModCache)
- : Stream(Buffer), Writer(Stream, Buffer, ModCache, {}) {}
+ ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts)
+ : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {}
};
void ASTUnit::clearFileLevelDecls() {
@@ -235,7 +235,8 @@ const unsigned DefaultPreambleRebuildInterval = 5;
static std::atomic<unsigned> ActiveASTUnitObjects;
ASTUnit::ASTUnit(bool _MainFileIsAST)
- : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
+ : CodeGenOpts(std::make_unique<CodeGenOptions>()),
+ MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
ShouldCacheCodeCompletionResults(false),
IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
UnsafeToFree(false) {
@@ -516,6 +517,7 @@ class ASTInfoCollector : public ASTReaderListener {
HeaderSearchOptions &HSOpts;
PreprocessorOptions &PPOpts;
LangOptions &LangOpt;
+ CodeGenOptions &CodeGenOpts;
std::shared_ptr<TargetOptions> &TargetOpts;
IntrusiveRefCntPtr<TargetInfo> &Target;
unsigned &Counter;
@@ -525,12 +527,12 @@ class ASTInfoCollector : public ASTReaderListener {
public:
ASTInfoCollector(Preprocessor &PP, ASTContext *Context,
HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
- LangOptions &LangOpt,
+ LangOptions &LangOpt, CodeGenOptions &CodeGenOpts,
std::shared_ptr<TargetOptions> &TargetOpts,
IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
: PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),
- LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
- Counter(Counter) {}
+ LangOpt(LangOpt), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts),
+ Target(Target), Counter(Counter) {}
bool ReadLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename, bool Complain,
@@ -555,6 +557,13 @@ class ASTInfoCollector : public ASTReaderListener {
return false;
}
+ bool ReadCodeGenOptions(const CodeGenOptions &CGOpts,
+ StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) override {
+ this->CodeGenOpts = CGOpts;
+ return false;
+ }
+
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
StringRef ModuleFilename,
StringRef SpecificModuleCachePath,
@@ -858,14 +867,16 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
DisableValidationForModuleKind::None;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = DisableValidationForModuleKind::All;
- AST->Reader = new ASTReader(
- PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, {}, /*isysroot=*/"",
- /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);
+ AST->Reader = new ASTReader(PP, *AST->ModCache, AST->Ctx.get(),
+ PCHContainerRdr, *AST->CodeGenOpts, {},
+ /*isysroot=*/"",
+ /*DisableValidationKind=*/disableValid,
+ AllowASTWithCompilerErrors);
unsigned Counter = 0;
AST->Reader->setListener(std::make_unique<ASTInfoCollector>(
*AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
- AST->TargetOpts, AST->Target, Counter));
+ *AST->CodeGenOpts, AST->TargetOpts, AST->Target, Counter));
// Attach the AST reader to the AST context as an external AST
// source, so that declarations will be deserialized from the
@@ -1836,6 +1847,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
AST->DiagOpts = DiagOpts;
AST->Diagnostics = Diags;
AST->FileSystemOpts = CI->getFileSystemOpts();
+ AST->CodeGenOpts = std::make_unique<CodeGenOptions>(CI->getCodeGenOpts());
VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->StorePreamblesInMemory = StorePreamblesInMemory;
@@ -1851,7 +1863,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
AST->Invocation = CI;
AST->SkipFunctionBodies = SkipFunctionBodies;
if (ForSerialization)
- AST->WriterData.reset(new ASTWriterData(*AST->ModCache));
+ AST->WriterData.reset(new ASTWriterData(*AST->ModCache, *AST->CodeGenOpts));
// Zero out now to ease cleanup during crash recovery.
CI = nullptr;
Diags = nullptr;
@@ -2385,7 +2397,7 @@ bool ASTUnit::serialize(raw_ostream &OS) {
SmallString<128> Buffer;
llvm::BitstreamWriter Stream(Buffer);
IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();
- ASTWriter Writer(Stream, Buffer, *ModCache, {});
+ ASTWriter Writer(Stream, Buffer, *ModCache, *CodeGenOpts, {});
return serializeUnit(Writer, Buffer, getSema(), OS);
}
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index f9a398dbfb90f..ba7c767f8e987 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -62,7 +62,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
std::unique_ptr<ASTReader> Reader;
Reader.reset(new ASTReader(
PP, CI.getModuleCache(), &CI.getASTContext(), CI.getPCHContainerReader(),
- /*Extensions=*/{},
+ CI.getCodeGenOpts(), /*Extensions=*/{},
/*isysroot=*/"", DisableValidationForModuleKind::PCH));
for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
StringRef sr(bufNames[ti]);
@@ -138,7 +138,8 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions;
auto consumer = std::make_unique<PCHGenerator>(
Clang->getPreprocessor(), Clang->getModuleCache(), "-", /*isysroot=*/"",
- Buffer, Extensions, /*AllowASTWithErrors=*/true);
+ Buffer, Clang->getCodeGenOpts(), Extensions,
+ /*AllowASTWithErrors=*/true);
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(std::move(consumer));
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 09a66b652518f..6c8b08b6acb1b 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -614,7 +614,7 @@ void CompilerInstance::createPCHExternalASTSource(
TheASTReader = createPCHExternalASTSource(
Path, getHeaderSearchOpts().Sysroot, DisableValidation,
AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(),
- getASTContext(), getPCHContainerReader(),
+ getASTContext(), getPCHContainerReader(), getCodeGenOpts(),
getFrontendOpts().ModuleFileExtensions, DependencyCollectors,
DeserializationListener, OwnDeserializationListener, Preamble,
getFrontendOpts().UseGlobalModuleIndex);
@@ -625,6 +625,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
DisableValidationForModuleKind DisableValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache,
ASTContext &Context, const PCHContainerReader &PCHContainerRdr,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener,
@@ -633,7 +634,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
PP.getHeaderSearchInfo().getHeaderSearchOpts();
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
- PP, ModCache, &Context, PCHContainerRdr, Extensions,
+ PP, ModCache, &Context, PCHContainerRdr, CodeGenOpts, Extensions,
Sysroot.empty() ? "" : Sysroot.data(), DisableValidation,
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
HSOpts.ModulesValidateSystemHeaders,
@@ -1746,7 +1747,8 @@ void CompilerInstance::createASTReader() {
"Reading modules", *timerGroup);
TheASTReader = new ASTReader(
getPreprocessor(), getModuleCache(), &getASTContext(),
- getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions,
+ getPCHContainerReader(), getCodeGenOpts(),
+ getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(),
PPOpts.DisablePCHOrModuleValidation,
/*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b9f75796ecc16..0bdd9f0a6dec2 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4436,22 +4436,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.OpenACCMacroOverride = A->getValue();
}
- // FIXME: Eliminate this dependency.
- unsigned Opt = getOptimizationLevel(Args, IK, Diags),
- OptSize = getOptimizationLevelSize(Args);
- Opts.Optimize = Opt != 0;
- Opts.OptimizeSize = OptSize != 0;
-
- // This is the __NO_INLINE__ define, which just depends on things like the
- // optimization level and -fno-inline, not actually whether the backend has
- // inlining enabled.
- Opts.NoInlineDefine = !Opts.Optimize;
- if (Arg *InlineArg = Args.getLastArg(
- options::OPT_finline_functions, options::OPT_finline_hint_functions,
- options::OPT_fno_inline_functions, options::OPT_fno_inline))
- if (InlineArg->getOption().matches(options::OPT_fno_inline))
- Opts.NoInlineDefine = true;
-
if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
StringRef Val = A->getValue();
if (Val == "fast")
@@ -5301,6 +5285,21 @@ std::string CompilerInvocation::getModuleHash() const {
HBuilder.add(*Build);
}
+ // Extend the signature with affecting codegen options.
+ {
+ using CK = CodeGenOptions::CompatibilityKind;
+#define CODEGENOPT(Name, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) \
+ HBuilder.add(CodeGenOpts->Name);
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) \
+ HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
+#define DEBUGOPT(Name, Bits, Default, Compatibility)
+#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
+#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
+#include "clang/Basic/CodeGenOptions.def"
+ }
+
// When compiling with -gmodules, also hash -fdebug-prefix-map as it
// affects the debug info in the PCM.
if (getCodeGenOpts().DebugTypeExtRefs)
@@ -5311,13 +5310,13 @@ std::string CompilerInvocation::getModuleHash() const {
// FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
using CK = CodeGenOptions::CompatibilityKind;
#define DEBUGOPT(Name, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Affecting) \
+ if constexpr (CK::Compatibility != CK::Benign) \
HBuilder.add(CodeGenOpts->Name);
#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Affecting) \
+ if constexpr (CK::Compatibility != CK::Benign) \
HBuilder.add(CodeGenOpts->Name);
#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Affecting) \
+ if constexpr (CK::Compatibility != CK::Benign) \
HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
#include "clang/Basic/DebugOptions.def"
}
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index f5996a8e1e88b..1d82fc775b28a 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -947,8 +947,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (ASTReader::isAcceptableASTFile(
Dir->path(), FileMgr, CI.getModuleCache(),
CI.getPCHContainerReader(), CI.getLangOpts(),
- CI.getTargetOpts(), CI.getPreprocessorOpts(),
- SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) {
+ CI.getCodeGenOpts(), CI.getTargetOpts(),
+ CI.getPreprocessorOpts(), SpecificModuleCachePath,
+ /*RequireStrictOptionMatches=*/true)) {
PPOpts.ImplicitPCHInclude = std::string(Dir->path());
Found = true;
break;
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 89eb0b689f85c..dcfbd5386f3dc 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -139,7 +139,7 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(std::make_unique<PCHGenerator>(
CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
- FrontendOpts.ModuleFileExtensions,
+ CI.getCodeGenOpts(), FrontendOpts.ModuleFileExtensions,
CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
FrontendOpts.IncludeTimestamps, FrontendOpts.BuildingImplicitModule,
+CI.getLangOpts().CacheGeneratedPCH));
@@ -199,7 +199,7 @@ GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,
Consumers.push_back(std::make_unique<PCHGenerator>(
CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
- CI.getFrontendOpts().ModuleFileExtensions,
+ CI.getCodeGenOpts(), CI.getFrontendOpts().ModuleFileExtensions,
/*AllowASTWithErrors=*/
+CI.getFrontendOpts().AllowPCMWithCompilerErrors,
/*IncludeTimestamps=*/
@@ -292,13 +292,13 @@ GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
!CI.getFrontendOpts().ModuleOutputPath.empty()) {
Consumers.push_back(std::make_unique<ReducedBMIGenerator>(
CI.getPreprocessor(), CI.getModuleCache(),
- CI.getFrontendOpts().ModuleOutputPath,
+ CI.getFrontendOpts().ModuleOutputPath, CI.getCodeGenOpts(),
+CI.getFrontendOpts().AllowPCMWithCompilerErrors));
}
Consumers.push_back(std::make_unique<CXX20ModulesGenerator>(
CI.getPreprocessor(), CI.getModuleCache(),
- CI.getFrontendOpts().OutputFile,
+ CI.getFrontendOpts().OutputFile, CI.getCodeGenOpts(),
+CI.getFrontendOpts().AllowPCMWithCompilerErrors));
return std::make_unique<MultiplexConsumer>(std::move(Consumers));
@@ -313,9 +313,9 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
std::unique_ptr<ASTConsumer>
GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
- return std::make_unique<ReducedBMIGenerator>(CI.getPreprocessor(),
- CI.getModuleCache(),
- CI.getFrontendOpts().OutputFile);
+ return std::make_unique<ReducedBMIGenerator>(
+ CI.getPreprocessor(), CI.getModuleCache(),
+ CI.getFrontendOpts().OutputFile, CI.getCodeGenOpts());
}
bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
@@ -358,7 +358,8 @@ void VerifyPCHAction::ExecuteAction() {
const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
std::unique_ptr<ASTReader> Reader(new ASTReader(
CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(),
- CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,
+ CI.getPCHContainerReader(), CI.getCodeGenOpts(),
+ CI.getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(),
DisableValidationForModuleKind::None,
/*AllowASTWithCompilerErrors*/ false,
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index f64613fb4a6cb..3eb5e6ff1c0bd 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -865,6 +865,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
const LangOptions &LangOpts,
const FrontendOptions &FEOpts,
const PreprocessorOptions &PPOpts,
+ const CodeGenOptions &CGOpts,
MacroBuilder &Builder) {
// Compiler version introspection macros.
Builder.defineMacro("__llvm__"); // LLVM Backend
@@ -1073,9 +1074,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__clang_wide_literal_encoding__", "\"UTF-16\"");
}
- if (LangOpts.Optimize)
+ if (CGOpts.OptimizationLevel != 0)
Builder.defineMacro("__OPTIMIZE__");
- if (LangOpts.OptimizeSize)
+ if (CGOpts.OptimizeSize != 0)
Builder.defineMacro("__OPTIMIZE_SIZE__");
if (LangOpts.FastMath)
@@ -1396,7 +1397,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (LangOpts.GNUCVersion)
addLockFreeMacros("__GCC_ATOMIC_");
- if (LangOpts.NoInlineDefine)
+ if (CGOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
Builder.defineMacro("__NO_INLINE__");
if (unsigned PICLevel = LangOpts.PICLevel) {
@@ -1575,10 +1576,11 @@ void clang::InitializePreprocessor(Preprocessor &PP,
// macros. This is not the right way to handle this.
if ((LangOpts.CUDA || LangOpts.isTargetDevice()) && PP.getAuxTargetInfo())
InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts,
- PP.getPreprocessorOpts(), Builder);
+ PP.getPreprocessorOpts(), CodeGenOpts,
+ Builder);
InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts,
- PP.getPreprocessorOpts(), Builder);
+ PP.getPreprocessorOpts(), CodeGenOpts, Builder);
// Install definitions to make Objective-C++ ARC work well with various
// C++ Standard Library implementations.
diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp
index 3f3fe3c9937e4..146cf903a5727 100644
--- a/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -293,8 +293,9 @@ class PrecompilePreambleConsumer : public PCHGenerator {
public:
PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP,
ModuleCache &ModCache, StringRef isysroot,
- std::shared_ptr<PCHBuffer> Buffer)
- : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer),
+ std::shared_ptr<PCHBuffer> Buffer,
+ const CodeGenOptions &CodeGenOpts)
+ : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer), CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
/*AllowASTWithErrors=*/true),
Action(Action) {}
@@ -337,7 +338,8 @@ PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
Sysroot.clear();
return std::make_unique<PrecompilePreambleConsumer>(
- *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer);
+ *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer,
+ CI.getCodeGenOpts());
}
template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 30e0973149594..4a96e65bb536c 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -175,6 +175,15 @@ bool ChainedASTReaderListener::ReadLanguageOptions(
AllowCompatibleDifferences);
}
+bool ChainedASTReaderListener::ReadCodeGenOptions(
+ const CodeGenOptions &CGOpts, StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) {
+ return First->ReadCodeGenOptions(CGOpts, ModuleFilename, Complain,
+ AllowCompatibleDifferences) ||
+ Second->ReadCodeGenOptions(CGOpts, ModuleFilename, Complain,
+ AllowCompatibleDifferences);
+}
+
bool ChainedASTReaderListener::ReadTargetOptions(
const TargetOptions &TargetOpts, StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) {
@@ -383,6 +392,68 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
return false;
}
+static bool checkCodegenOptions(const CodeGenOptions &CGOpts,
+ const CodeGenOptions &ExistingCGOpts,
+ StringRef ModuleFilename,
+ DiagnosticsEngine *Diags,
+ bool AllowCompatibleDifferences = true) {
+ // FIXME: Specify and print a description for each option instead of the name.
+ // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
+ using CK = CodeGenOptions::CompatibilityKind;
+#define CODEGENOPT(Name, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) { \
+ if ((CK::Compatibility == CK::NotCompatible) || \
+ (CK::Compatibility == CK::Compatible && \
+ !AllowCompatibleDifferences)) { \
+ if (ExistingCGOpts.Name != CGOpts.Name) { \
+ if (Diags) { \
+ if (Bits == 1) \
+ Diags->Report(diag::err_ast_file_codegenopt_mismatch) \
+ << #Name << CGOpts.Name << ExistingCGOpts.Name \
+ << ModuleFilename; \
+ else \
+ Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \
+ << #Name << ModuleFilename; \
+ } \
+ return true; \
+ } \
+ } \
+ }
+
+#define VALUE_CODEGENOPT(Name, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) { \
+ if ((CK::Compatibility == CK::NotCompatible) || \
+ (CK::Compatibility == CK::Compatible && \
+ !AllowCompatibleDifferences)) { \
+ if (ExistingCGOpts.Name != CGOpts.Name) { \
+ if (Diags) \
+ Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \
+ << #Name << ModuleFilename; \
+ return true; \
+ } \
+ } \
+ }
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) { \
+ if ((CK::Compatibility == CK::NotCompatible) || \
+ (CK::Compatibility == CK::Compatible && \
+ !AllowCompatibleDifferences)) { \
+ if (ExistingCGOpts.get##Name() != CGOpts.get##Name()) { \
+ if (Diags) \
+ Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \
+ << #Name << ModuleFilename; \
+ return true; \
+ } \
+ } \
+ }
+#define DEBUGOPT(Name, Bits, Default, Compatibility)
+#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
+#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
+#include "clang/Basic/CodeGenOptions.def"
+
+ return false;
+}
+
/// Compare the given set of target options against an existing set of
/// target options.
///
@@ -462,6 +533,15 @@ bool PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
AllowCompatibleDifferences);
}
+bool PCHValidator::ReadCodeGenOptions(const CodeGenOptions &CGOpts,
+ StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) {
+ const CodeGenOptions &ExistingCGOpts = Reader.getCodeGenOpts();
+ return checkCodegenOptions(ExistingCGOpts, CGOpts, ModuleFilename,
+ Complain ? &Reader.Diags : nullptr,
+ AllowCompatibleDifferences);
+}
+
bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) {
@@ -2993,6 +3073,14 @@ ASTReader::ASTReadResult ASTReader::ReadOptionsBlock(
break;
}
+ case CODEGEN_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (ParseCodeGenOptions(Record, Filename, Complain, Listener,
+ AllowCompatibleConfigurationMismatch))
+ Result = ConfigurationMismatch;
+ break;
+ }
+
case TARGET_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
if (ParseTargetOptions(Record, Filename, Complain, Listener,
@@ -5639,6 +5727,7 @@ namespace {
class SimplePCHValidator : public ASTReaderListener {
const LangOptions &ExistingLangOpts;
+ const CodeGenOptions &ExistingCGOpts;
const TargetOptions &ExistingTargetOpts;
const PreprocessorOptions &ExistingPPOpts;
std::string ExistingModuleCachePath;
@@ -5647,11 +5736,12 @@ namespace {
public:
SimplePCHValidator(const LangOptions &ExistingLangOpts,
+ const CodeGenOptions &ExistingCGOpts,
const TargetOptions &ExistingTargetOpts,
const PreprocessorOptions &ExistingPPOpts,
StringRef ExistingModuleCachePath, FileManager &FileMgr,
bool StrictOptionMatches)
- : ExistingLangOpts(ExistingLangOpts),
+ : ExistingLangOpts(ExistingLangOpts), ExistingCGOpts(ExistingCGOpts),
ExistingTargetOpts(ExistingTargetOpts),
ExistingPPOpts(ExistingPPOpts),
ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr),
@@ -5664,6 +5754,13 @@ namespace {
nullptr, AllowCompatibleDifferences);
}
+ bool ReadCodeGenOptions(const CodeGenOptions &CGOpts,
+ StringRef ModuleFilename, bool Complain,
+ bool AllowCompatibleDifferences) override {
+ return checkCodegenOptions(ExistingCGOpts, CGOpts, ModuleFilename,
+ nullptr, AllowCompatibleDifferences);
+ }
+
bool ReadTargetOptions(const TargetOptions &TargetOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override {
@@ -6012,9 +6109,10 @@ bool ASTReader::readASTFileControlBlock(
bool ASTReader::isAcceptableASTFile(
StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts,
- const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts,
- StringRef ExistingModuleCachePath, bool RequireStrictOptionMatches) {
- SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
+ const CodeGenOptions &CGOpts, const TargetOptions &TargetOpts,
+ const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath,
+ bool RequireStrictOptionMatches) {
+ SimplePCHValidator validator(LangOpts, CGOpts, TargetOpts, PPOpts,
ExistingModuleCachePath, FileMgr,
RequireStrictOptionMatches);
return !readASTFileControlBlock(Filename, FileMgr, ModCache, PCHContainerRdr,
@@ -6395,6 +6493,28 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
AllowCompatibleDifferences);
}
+bool ASTReader::ParseCodeGenOptions(const RecordData &Record,
+ StringRef ModuleFilename, bool Complain,
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences) {
+ unsigned Idx = 0;
+ CodeGenOptions CGOpts;
+ using CK = CodeGenOptions::CompatibilityKind;
+#define CODEGENOPT(Name, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) \
+ CGOpts.Name = static_cast<unsigned>(Record[Idx++]);
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) \
+ CGOpts.set##Name(static_cast<clang::CodeGenOptions::Type>(Record[Idx++]));
+#define DEBUGOPT(Name, Bits, Default, Compatibility)
+#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
+#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
+#include "clang/Basic/CodeGenOptions.def"
+
+ return Listener.ReadCodeGenOptions(CGOpts, ModuleFilename, Complain,
+ AllowCompatibleDifferences);
+}
+
bool ASTReader::ParseTargetOptions(const RecordData &Record,
StringRef ModuleFilename, bool Complain,
ASTReaderListener &Listener,
@@ -10985,6 +11105,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache,
ASTContext *Context,
const PCHContainerReader &PCHContainerRdr,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
StringRef isysroot,
DisableValidationForModuleKind DisableValidationKind,
@@ -10999,6 +11120,7 @@ ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache,
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()),
StackHandler(Diags), PP(PP), ContextObj(Context),
+ CodeGenOpts(CodeGenOpts),
ModuleMgr(PP.getFileManager(), ModCache, PCHContainerRdr,
PP.getHeaderSearchInfo()),
DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 1a20fc9595dce..847283e9842e5 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -898,6 +898,7 @@ void ASTWriter::WriteBlockInfoBlock() {
BLOCK(OPTIONS_BLOCK);
RECORD(LANGUAGE_OPTIONS);
+ RECORD(CODEGEN_OPTIONS);
RECORD(TARGET_OPTIONS);
RECORD(FILE_SYSTEM_OPTIONS);
RECORD(HEADER_SEARCH_OPTIONS);
@@ -1646,6 +1647,23 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
Stream.EmitRecord(LANGUAGE_OPTIONS, Record);
+ // Codegen options.
+ // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
+ using CK = CodeGenOptions::CompatibilityKind;
+ Record.clear();
+ const CodeGenOptions &CGOpts = getCodeGenOpts();
+#define CODEGENOPT(Name, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) \
+ Record.push_back(static_cast<unsigned>(CGOpts.Name));
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \
+ if constexpr (CK::Compatibility != CK::Benign) \
+ Record.push_back(static_cast<unsigned>(CGOpts.get##Name()));
+#define DEBUGOPT(Name, Bits, Default, Compatibility)
+#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
+#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
+#include "clang/Basic/CodeGenOptions.def"
+ Stream.EmitRecord(CODEGEN_OPTIONS, Record);
+
// Target options.
Record.clear();
const TargetInfo &Target = PP.getTargetInfo();
@@ -5384,11 +5402,12 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
SmallVectorImpl<char> &Buffer, ModuleCache &ModCache,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps, bool BuildingImplicitModule,
bool GeneratingReducedBMI)
: Stream(Stream), Buffer(Buffer), ModCache(ModCache),
- IncludeTimestamps(IncludeTimestamps),
+ CodeGenOpts(CodeGenOpts), IncludeTimestamps(IncludeTimestamps),
BuildingImplicitModule(BuildingImplicitModule),
GeneratingReducedBMI(GeneratingReducedBMI) {
for (const auto &Ext : Extensions) {
diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp
index 77317f0a1db32..f8be0e45078db 100644
--- a/clang/lib/Serialization/GeneratePCH.cpp
+++ b/clang/lib/Serialization/GeneratePCH.cpp
@@ -25,13 +25,14 @@ using namespace clang;
PCHGenerator::PCHGenerator(
Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile,
StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
+ const CodeGenOptions &CodeGenOpts,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors, bool IncludeTimestamps,
bool BuildingImplicitModule, bool ShouldCacheASTInMemory,
bool GeneratingReducedBMI)
: PP(PP), Subject(&PP), OutputFile(OutputFile), isysroot(isysroot.str()),
Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
- Writer(Stream, this->Buffer->Data, ModCache, Extensions,
+ Writer(Stream, this->Buffer->Data, ModCache, CodeGenOpts, Extensions,
IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI),
AllowASTWithErrors(AllowASTWithErrors),
ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
@@ -102,11 +103,12 @@ void PCHGenerator::anchor() {}
CXX20ModulesGenerator::CXX20ModulesGenerator(Preprocessor &PP,
ModuleCache &ModCache,
StringRef OutputFile,
+ const CodeGenOptions &CodeGenOpts,
bool GeneratingReducedBMI,
bool AllowASTWithErrors)
: PCHGenerator(
PP, ModCache, OutputFile, llvm::StringRef(),
- std::make_shared<PCHBuffer>(),
+ std::make_shared<PCHBuffer>(), CodeGenOpts,
/*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
AllowASTWithErrors, /*IncludeTimestamps=*/false,
/*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false,
diff --git a/clang/test/PCH/no-validate-pch.cl b/clang/test/PCH/no-validate-pch.cl
index f6a7c65461fe1..ce3a9095fe2e6 100644
--- a/clang/test/PCH/no-validate-pch.cl
+++ b/clang/test/PCH/no-validate-pch.cl
@@ -16,7 +16,7 @@
// CHECK: note: previous definition is here
// CHECK: #define X 4
-// CHECK-VAL: error: __OPTIMIZE__ predefined macro was enabled in precompiled file '{{.*}}' but is currently disabled
+// CHECK-VAL: error: OptimizationLevel differs in precompiled file '{{.*}}' vs. current file
// CHECK-VAL: error: definition of macro 'X' differs between the precompiled file '{{.*}}' ('4') and the command line ('5')
void test(void) {
diff --git a/llvm/clang/test/Modules/implicit-opt-level.c b/llvm/clang/test/Modules/implicit-opt-level.c
new file mode 100644
index 0000000000000..f6f1f58d31d79
--- /dev/null
+++ b/llvm/clang/test/Modules/implicit-opt-level.c
@@ -0,0 +1,15 @@
+// This test checks that under implicit modules, different optimization levels
+// get different context hashes.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+//--- module.modulemap
+module M { header "M.h" }
+//--- M.h
+//--- tu.c
+#include "M.h"
+
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -O0 -fsyntax-only %t/tu.c
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -O1 -fsyntax-only %t/tu.c
+// RUN: find %t/cache -name "M-*.pcm" | count 2
>From 163b26b37410eb27351caaaeff1bcf44127e9200 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 7 Jul 2025 09:39:59 -0700
Subject: [PATCH 2/4] clang-format
---
clang/include/clang/Basic/CodeGenOptions.h | 3 ++-
clang/lib/CodeGen/CGDebugInfo.cpp | 7 ++++---
clang/lib/Serialization/ASTReader.cpp | 2 +-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 7cd5ea3256cdb..1c3b2719c2d97 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -59,7 +59,8 @@ class CodeGenOptionsBase {
using CFBranchLabelSchemeKind = CFBranchLabelSchemeKind;
using ProfileInstrKind = llvm::driver::ProfileInstrKind;
- using AsanDetectStackUseAfterReturnMode = llvm::AsanDetectStackUseAfterReturnMode;
+ using AsanDetectStackUseAfterReturnMode =
+ llvm::AsanDetectStackUseAfterReturnMode;
using AsanDtorKind = llvm::AsanDtorKind;
using VectorLibrary = llvm::driver::VectorLibrary;
using ZeroCallUsedRegsKind = llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 875356455bca9..ef9f4b61dfd5e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -5319,9 +5319,10 @@ void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) {
StringRef Name = D->getName();
// Create the descriptor for the label.
- auto *L = DBuilder.createLabel(
- Scope, Name, Unit, Line, Column, /*IsArtificial=*/false,
- /*CoroSuspendIdx=*/std::nullopt, CGM.getCodeGenOpts().OptimizationLevel != 0);
+ auto *L = DBuilder.createLabel(Scope, Name, Unit, Line, Column,
+ /*IsArtificial=*/false,
+ /*CoroSuspendIdx=*/std::nullopt,
+ CGM.getCodeGenOpts().OptimizationLevel != 0);
// Insert an llvm.dbg.label into the current block.
DBuilder.insertLabel(L,
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 4a96e65bb536c..d0bb7fb1d06ad 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -425,7 +425,7 @@ static bool checkCodegenOptions(const CodeGenOptions &CGOpts,
if ((CK::Compatibility == CK::NotCompatible) || \
(CK::Compatibility == CK::Compatible && \
!AllowCompatibleDifferences)) { \
- if (ExistingCGOpts.Name != CGOpts.Name) { \
+ if (ExistingCGOpts.Name != CGOpts.Name) { \
if (Diags) \
Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \
<< #Name << ModuleFilename; \
>From 0af9560d315bb747277089fe703de37c56088660 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 7 Jul 2025 10:38:02 -0700
Subject: [PATCH 3/4] Fix lldb build
---
.../Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 82e07bb8e0ffb..c033a41cdf330 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -474,20 +474,6 @@ static void ParseLangArgs(LangOptions &Opts, ArchSpec arch) {
// specified, or -std is set to a conforming mode.
Opts.Trigraphs = !Opts.GNUMode;
Opts.CharIsSigned = arch.CharIsSignedByDefault();
- Opts.OptimizeSize = 0;
-
- // FIXME: Eliminate this dependency.
- // unsigned Opt =
- // Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags);
- // Opts.Optimize = Opt != 0;
- unsigned Opt = 0;
-
- // This is the __NO_INLINE__ define, which just depends on things like the
- // optimization level and -fno-inline, not actually whether the backend has
- // inlining enabled.
- //
- // FIXME: This is affected by other options (-fno-inline).
- Opts.NoInlineDefine = !Opt;
// This is needed to allocate the extra space for the owning module
// on each decl.
>From e0a28a261aadc17a27e020c8e0c04b12f8c4464d Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 15 Jul 2025 11:23:47 -0700
Subject: [PATCH 4/4] Preserve conditions in
`CodeGenOptions::resetNonModularOptions()`
---
clang/lib/Basic/CodeGenOptions.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Basic/CodeGenOptions.cpp b/clang/lib/Basic/CodeGenOptions.cpp
index ed877c40573ac..db8a77cd93cf6 100644
--- a/clang/lib/Basic/CodeGenOptions.cpp
+++ b/clang/lib/Basic/CodeGenOptions.cpp
@@ -39,10 +39,10 @@ void CodeGenOptions::resetNonModularOptions(StringRef ModuleFormat) {
if constexpr (CK::Compatibility != CK::Benign) \
Name = Default;
#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Benign) \
+ if constexpr (CK::Compatibility != CK::Benign) \
Name = Default;
#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \
- if constexpr (CK::Compatibility == CK::Benign) \
+ if constexpr (CK::Compatibility != CK::Benign) \
set##Name(Default);
#include "clang/Basic/DebugOptions.def"
}
More information about the llvm-commits
mailing list