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 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 e5566a540dc65..0526ac2a7f2b7 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -12,8 +12,10 @@ // that have enumeration type and VALUE_CODEGENOPT is a code // generation option that describes a value rather than a flag. // -// AFFECTING_VALUE_CODEGENOPT is used for code generation options that can -// affect the AST. +// COMPATIBLE_VALUE_CODEGENOPT is used for code generation options that 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). // //===----------------------------------------------------------------------===// #ifndef CODEGENOPT @@ -30,11 +32,16 @@ CODEGENOPT(Name, Bits, Default) CODEGENOPT(Name, Bits, Default) #endif -#ifndef AFFECTING_VALUE_CODEGENOPT -# define AFFECTING_VALUE_CODEGENOPT(Name, Bits, Default) \ +#ifndef COMPATIBLE_VALUE_CODEGENOPT +# define COMPATIBLE_VALUE_CODEGENOPT(Name, Bits, Default, Description) \ VALUE_CODEGENOPT(Name, Bits, Default) #endif +#ifndef COMPATIBLE_ENUM_CODEGENOPT +# define COMPATIBLE_ENUM_CODEGENOPT(Name, Type, Bits, Default, Description) \ +ENUM_CODEGENOPT(Name, Type, Bits, Default) +#endif + CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as CODEGENOPT(Crel, 1, 0) ///< -Wa,--crel CODEGENOPT(ImplicitMapSyms, 1, 0) ///< -Wa,-mmapsyms=implicit @@ -216,9 +223,9 @@ CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1) CODEGENOPT(ObjCAvoidHeapifyLocalBlocks, 1, 0) -// The optimization options affect frontend options, whicn in turn do affect the AST. -AFFECTING_VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified. -AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. +// The optimization options affect frontend options, which in turn do affect the AST. +COMPATIBLE_VALUE_CODEGENOPT(OptimizationLevel, 2, 0, "optimization level") ///< The -O[0-3] option specified. +COMPATIBLE_VALUE_CODEGENOPT(OptimizeSize, 2, 0, "optimizing for size") ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic CODEGENOPT(ContinuousProfileSync, 1, 0) ///< Enable continuous instrumentation profiling @@ -383,7 +390,7 @@ VALUE_CODEGENOPT(SmallDataLimit, 32, 0) VALUE_CODEGENOPT(SSPBufferSize, 32, 0) /// The kind of inlining to perform. -ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining) +COMPATIBLE_ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining, "inlining kind") /// The maximum stack size a function can have to be considered for inlining. VALUE_CODEGENOPT(InlineMaxStackSize, 32, UINT_MAX) @@ -494,4 +501,5 @@ ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode, #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT -#undef AFFECTING_VALUE_CODEGENOPT +#undef COMPATIBLE_VALUE_CODEGENOPT +#undef COMPATIBLE_ENUM_CODEGENOPT diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 584c8d62280bf..49eb6c195715c 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -41,6 +41,8 @@ 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_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 789761c1f3647..2a6eed0fdc9b3 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -206,8 +206,6 @@ COMPATIBLE_LANGOPT(ModulesValidateTextualHeaderIncludes, 1, 1, "validation of te BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically importing modules as needed when performing error recovery") BENIGN_LANGOPT(ImplicitModules, 1, 1, "building modules that are not specified via -fmodule-file") COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility") -COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") -COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro") COMPATIBLE_LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") VALUE_LANGOPT(PackStruct , 32, 0, "default struct packing maximum alignment") @@ -224,7 +222,6 @@ COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") LANGOPT(ROPI , 1, 0, "Read-only position independence") LANGOPT(RWPI , 1, 0, "Read-write position independence") COMPATIBLE_LANGOPT(GNUInline , 1, 0, "GNU inline semantics") -COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro") COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") COMPATIBLE_LANGOPT(FastMath , 1, 0, "fast FP math optimizations, and __FAST_MATH__ predefined macro") COMPATIBLE_LANGOPT(UnsafeFPMath , 1, 0, "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 LangOpts; + std::unique_ptr 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> Extensions, ArrayRef> 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 7d4b4467eb97d..5b6a296f8a157 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; @@ -1586,6 +1605,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, @@ -1777,6 +1800,7 @@ class ASTReader /// deserializing. ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef> Extensions, StringRef isysroot = "", DisableValidationForModuleKind DisableValidationKind = @@ -1795,6 +1819,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. @@ -1996,14 +2021,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 &Buffer, - ModuleCache &ModCache, + ModuleCache &ModCache, const CodeGenOptions &CodeGenOpts, ArrayRef> 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 Buffer, + const CodeGenOptions &CodeGenOpts, ArrayRef> 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 1f899dee48dbd..4b077c6071da5 100644 --- a/clang/lib/Basic/CodeGenOptions.cpp +++ b/clang/lib/Basic/CodeGenOptions.cpp @@ -26,7 +26,8 @@ void CodeGenOptions::resetNonModularOptions(StringRef ModuleFormat) { #define CODEGENOPT(Name, Bits, Default) Name = Default; #define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default); // Do not reset AST affecting code generation options. -#define AFFECTING_VALUE_CODEGENOPT(Name, Bits, Default) +#define COMPATIBLE_VALUE_CODEGENOPT(Name, Bits, Default, Description) +#define COMPATIBLE_ENUM_CODEGENOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/CodeGenOptions.def" // Next reset all debug options that can always be reset, because they never diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 3feadf1ba0c7d..f2ff0f6d55da1 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); @@ -2273,7 +2274,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 @@ -4344,7 +4345,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) { @@ -4664,7 +4665,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(); @@ -4747,7 +4748,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); @@ -5079,7 +5080,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. @@ -5105,9 +5107,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. @@ -5148,8 +5150,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), @@ -5203,7 +5206,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, auto *Scope = cast(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(BD->getBinding())) { @@ -5301,8 +5304,8 @@ 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, CGM.getLangOpts().Optimize); + auto *L = DBuilder.createLabel(Scope, Name, Unit, Line, + CGM.getCodeGenOpts().OptimizationLevel != 0); // Insert an llvm.dbg.label into the current block. DBuilder.insertLabel(L, @@ -5565,7 +5568,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(), @@ -6340,7 +6344,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> Consumers(2); Consumers[0] = std::make_unique( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().ModuleOutputPath); + CI.getFrontendOpts().ModuleOutputPath, CI.getCodeGenOpts()); Consumers[1] = std::move(Result); return std::make_unique(std::move(Consumers)); } diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 3beff3d6d849f..1b6f03be38c62 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 ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) - : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")), + : CodeGenOpts(std::make_unique()), + 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 &TargetOpts; IntrusiveRefCntPtr &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 &TargetOpts, IntrusiveRefCntPtr &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::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( *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::LoadFromCommandLine( AST->DiagOpts = DiagOpts; AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); + AST->CodeGenOpts = std::make_unique(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::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 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 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 clang::createChainedIncludesSource( ArrayRef> Extensions; auto consumer = std::make_unique( 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 CompilerInstance::createPCHExternalASTSource( DisableValidationForModuleKind DisableValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef> Extensions, ArrayRef> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, @@ -633,7 +634,7 @@ IntrusiveRefCntPtr CompilerInstance::createPCHExternalASTSource( PP.getHeaderSearchInfo().getHeaderSearchOpts(); IntrusiveRefCntPtr 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 f366e90945dac..b3a2fdcc5127e 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4397,22 +4397,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") @@ -5254,6 +5238,15 @@ std::string CompilerInvocation::getModuleHash() const { HBuilder.add(*Build); } + // The default CODEGENOPT is benign, so only include the ones marked as + // compatible into the hash. +#define CODEGENOPT(Name, Bits, Default) +#define COMPATIBLE_VALUE_CODEGENOPT(Name, Bits, Default, Description) \ + HBuilder.add(CodeGenOpts->Name); +#define COMPATIBLE_ENUM_CODEGENOPT(Name, Type, Bits, Default, Description) \ + HBuilder.add(static_cast(CodeGenOpts->get##Name())); +#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) diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index ef7ae27a2694a..7e5668d56f7cd 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 c0ab708d8b844..1d660262d4f4c 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> Consumers; Consumers.push_back(std::make_unique( 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( 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( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().ModuleOutputPath, + CI.getFrontendOpts().ModuleOutputPath, CI.getCodeGenOpts(), +CI.getFrontendOpts().AllowPCMWithCompilerErrors)); } Consumers.push_back(std::make_unique( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().OutputFile, + CI.getFrontendOpts().OutputFile, CI.getCodeGenOpts(), +CI.getFrontendOpts().AllowPCMWithCompilerErrors)); return std::make_unique(std::move(Consumers)); @@ -313,9 +313,9 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, std::unique_ptr GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return std::make_unique(CI.getPreprocessor(), - CI.getModuleCache(), - CI.getFrontendOpts().OutputFile); + return std::make_unique( + 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 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 Buffer) - : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer), + std::shared_ptr Buffer, + const CodeGenOptions &CodeGenOpts) + : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer), CodeGenOpts, ArrayRef>(), /*AllowASTWithErrors=*/true), Action(Action) {} @@ -337,7 +338,8 @@ PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI, Sysroot.clear(); return std::make_unique( - *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer); + *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer, + CI.getCodeGenOpts()); } template bool moveOnNoError(llvm::ErrorOr Val, T &Output) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 486971818f109..1e0a0f2fc6022 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) { @@ -377,6 +386,32 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return false; } +static bool checkCodegenOptions(const CodeGenOptions &CGOpts, + const CodeGenOptions &ExistingCGOpts, + StringRef ModuleFilename, + DiagnosticsEngine *Diags, + bool AllowCompatibleDifferences = true) { +#define CODEGENOPT(Name, Bits, Default) +#define COMPATIBLE_VALUE_CODEGENOPT(Name, Bits, Default, Description) \ + if (!AllowCompatibleDifferences && ExistingCGOpts.Name != CGOpts.Name) { \ + if (Diags) \ + Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \ + << Description << ModuleFilename; \ + return true; \ + } +#define COMPATIBLE_ENUM_CODEGENOPT(Name, Type, Bits, Default, Description) \ + if (!AllowCompatibleDifferences && \ + ExistingCGOpts.get##Name() != CGOpts.get##Name()) { \ + if (Diags) \ + Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \ + << Description << ModuleFilename; \ + return true; \ + } +#include "clang/Basic/CodeGenOptions.def" + + return false; +} + /// Compare the given set of target options against an existing set of /// target options. /// @@ -456,6 +491,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) { @@ -2987,6 +3031,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, @@ -5633,6 +5685,7 @@ namespace { class SimplePCHValidator : public ASTReaderListener { const LangOptions &ExistingLangOpts; + const CodeGenOptions &ExistingCGOpts; const TargetOptions &ExistingTargetOpts; const PreprocessorOptions &ExistingPPOpts; std::string ExistingModuleCachePath; @@ -5641,11 +5694,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), @@ -5658,6 +5712,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 { @@ -6006,9 +6067,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, @@ -6389,6 +6451,23 @@ 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; +#define CODEGENOPT(Name, Bits, Default) +#define COMPATIBLE_VALUE_CODEGENOPT(Name, Bits, Default, Description) \ + CGOpts.Name = static_cast(Record[Idx++]); +#define COMPATIBLE_ENUM_CODEGENOPT(Name, Type, Bits, Default, Description) \ + CGOpts.set##Name(static_cast(Record[Idx++])); +#include "clang/Basic/CodeGenOptions.def" + + return Listener.ReadCodeGenOptions(CGOpts, ModuleFilename, Complain, + AllowCompatibleDifferences); +} + bool ASTReader::ParseTargetOptions(const RecordData &Record, StringRef ModuleFilename, bool Complain, ASTReaderListener &Listener, @@ -10976,6 +11055,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef> Extensions, StringRef isysroot, DisableValidationForModuleKind DisableValidationKind, @@ -10990,6 +11070,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 06cd6c7305114..50d5eb14e456a 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,17 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) { Stream.EmitRecord(LANGUAGE_OPTIONS, Record); + // Codegen options. + Record.clear(); + const CodeGenOptions &CGOpts = getCodeGenOpts(); +#define CODEGENOPT(Name, Bits, Default) +#define COMPATIBLE_VALUE_CODEGENOPT(Name, Bits, Default, Description) \ + Record.push_back(static_cast(CGOpts.Name)); +#define COMPATIBLE_ENUM_CODEGENOPT(Name, Type, Bits, Default, Description) \ + Record.push_back(static_cast(CGOpts.get##Name())); +#include "clang/Basic/CodeGenOptions.def" + Stream.EmitRecord(CODEGEN_OPTIONS, Record); + // Target options. Record.clear(); const TargetInfo &Target = PP.getTargetInfo(); @@ -5384,11 +5396,12 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl &Buffer, ModuleCache &ModCache, + const CodeGenOptions &CodeGenOpts, ArrayRef> 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 Buffer, + const CodeGenOptions &CodeGenOpts, ArrayRef> 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(), + std::make_shared(), CodeGenOpts, /*Extensions=*/ArrayRef>(), AllowASTWithErrors, /*IncludeTimestamps=*/false, /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false, diff --git a/clang/test/Modules/implicit-opt-level.c b/clang/test/Modules/implicit-opt-level.c new file mode 100644 index 0000000000000..f6f1f58d31d79 --- /dev/null +++ b/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 diff --git a/clang/test/PCH/no-validate-pch.cl b/clang/test/PCH/no-validate-pch.cl index f6a7c65461fe1..7d24d85175046 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: optimization level 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) {