From 3f98ce16010147f0d4fd5e74ac484844ae7ea78d Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Wed, 8 Nov 2023 09:55:07 +0800 Subject: [PATCH 1/3] [C++20] [Modules] Introduce thin BMI Close https://github.com/llvm/llvm-project/issues/71034 This patch introduces thin BMI, which doesn't contain the definitions of functions and variables if its definitions won't contribute to the ABI. Testing is a big part of the patch. We want to make sure the thin BMI contains the same behavior with the existing and relatively stable fatBMI. This is pretty helpful for further reduction. For user interfeaces, this patch introduces `-fthinBMI-output=` arguments to specify the position of thin BMI. This should be used when compiling a single module unit. The design is helpful to use thin BMI in two phase compilations too. With thin BMI, In two phase compilations, we'll generate 2 BMIs, one thin BMI for being used by consumers, one fat BMI for compiling itself to object files. Maybe it sounds confusing to have 2 BMIs for one module unit. But only the thin BMI will be the BMI we're talking about generally and the fat BMI is only visible by the module unit itself. With one phase compilation, we may find the behavior of `-fthinBMI-output=` is pretty similar with `-fmodule-output=`, except one generating thin BMI and the other generating fat BMI. The design here is based on 2 things: (1) The serialization of C++ is pretty complex. We can't be sure we're handling every detail correctly in the every beginning. (2) The fat BMI is relatively widely used and relatively stable. So it looks not good to replace the fat BMI immediately with thin BMI. But, of course, in the end of the day, we want the consumers to use the thin BMI only. When that day comes, the `-fmodule-output=` will be an alias to `-fthinBMI-output=`. Another design choice is to reuse `-fmodule-output=` and introduce a flag `-femit-thin-BMI`. Then `-femit-thin-BMI -fmodule-output=` will have the same effect with `-fthinBMI-output=` now. The flag `-femit-thin-BMI` should be opt-in now and opt-off later and finally deprecated. The roadmap for thin BMI in my mind is: (1) In clang18, release thin BMI and mark it as experimental. Also encourage users and build systems to try this new mode. (2) In clang19 or clang20 (based on the issue feedbacks), remove the experimental mark for thin BMI and mark fat BMI as deprecated to be used by consumers. (3) In clang21 or clang22, error out if we found the users are trying to import a fat BMI. --- .../clang/Basic/DiagnosticDriverKinds.td | 2 + clang/include/clang/Driver/Options.td | 9 +++- .../include/clang/Frontend/FrontendActions.h | 18 ++++++- .../include/clang/Frontend/FrontendOptions.h | 9 +++- clang/include/clang/Serialization/ASTWriter.h | 30 ++++++++++- clang/lib/Driver/Driver.cpp | 7 +++ clang/lib/Driver/ToolChains/Clang.cpp | 2 + clang/lib/Frontend/CompilerInvocation.cpp | 2 + clang/lib/Frontend/FrontendActions.cpp | 49 +++++++++++++++-- .../ExecuteCompilerInvocation.cpp | 2 + clang/lib/Serialization/ASTWriter.cpp | 32 ++++++----- clang/lib/Serialization/ASTWriterDecl.cpp | 53 ++++++++++++++++--- clang/lib/Serialization/GeneratePCH.cpp | 36 ++++++++++++- clang/test/CXX/basic/basic.link/p10-ex2.cpp | 3 +- .../p4-friend-in-reachable-class.cpp | 6 ++- clang/test/Driver/thinBMI-output.cppm | 29 ++++++++++ .../test/Modules/InheritDefaultArguments.cppm | 3 ++ clang/test/Modules/Reachability-Private.cpp | 10 ++++ .../Modules/Reachability-func-default-arg.cpp | 3 ++ clang/test/Modules/Reachability-func-ret.cpp | 3 ++ .../Reachability-template-default-arg.cpp | 3 ++ .../Reachability-template-instantiation.cpp | 4 ++ .../Modules/Reachability-using-templates.cpp | 3 ++ clang/test/Modules/Reachability-using.cpp | 3 ++ clang/test/Modules/concept.cppm | 4 ++ clang/test/Modules/concept_differ.cppm | 5 ++ clang/test/Modules/ctor.arg.dep.cppm | 4 ++ clang/test/Modules/cxx20-10-1-ex1.cpp | 13 +++++ clang/test/Modules/cxx20-10-1-ex2.cpp | 36 ++++++++++--- clang/test/Modules/cxx20-10-2-ex2.cpp | 12 +++++ clang/test/Modules/cxx20-10-2-ex5.cpp | 12 +++++ clang/test/Modules/cxx20-10-3-ex1.cpp | 14 +++++ clang/test/Modules/cxx20-10-3-ex2.cpp | 10 ++++ clang/test/Modules/cxx20-10-5-ex1.cpp | 12 +++++ .../Modules/cxx20-import-diagnostics-a.cpp | 39 ++++++++++++++ .../Modules/cxx20-import-diagnostics-b.cpp | 25 +++++++++ .../Modules/cxx20-module-file-info-macros.cpp | 3 ++ clang/test/Modules/deduction-guide.cppm | 3 ++ clang/test/Modules/deduction-guide2.cppm | 3 ++ clang/test/Modules/deduction-guide3.cppm | 3 ++ clang/test/Modules/derived_class.cpp | 3 ++ ...duplicated-module-file-eq-module-name.cppm | 4 ++ clang/test/Modules/enum-class.cppm | 3 ++ .../explicitly-specialized-template.cpp | 3 ++ .../test/Modules/export-language-linkage.cppm | 5 ++ clang/test/Modules/ftime-trace.cppm | 9 ++++ .../inconsistent-deduction-guide-linkage.cppm | 6 +++ clang/test/Modules/inconsistent-export.cppm | 13 +++++ clang/test/Modules/inherited_arg.cppm | 11 ++++ .../Modules/instantiation-argdep-lookup.cppm | 3 ++ clang/test/Modules/lambdas.cppm | 15 ++++++ .../Modules/merge-concepts-cxx-modules.cpp | 12 +++++ .../Modules/merge-constrained-friends.cpp | 3 ++ clang/test/Modules/merge-lambdas.cppm | 4 ++ .../Modules/merge-requires-with-lambdas.cppm | 19 +++++++ .../merge-var-template-spec-cxx-modules.cppm | 5 ++ clang/test/Modules/mismatch-diagnostics.cpp | 11 ++++ .../module-init-duplicated-import.cppm | 11 ++++ clang/test/Modules/named-modules-adl-2.cppm | 4 ++ clang/test/Modules/named-modules-adl-3.cppm | 17 ++++++ clang/test/Modules/named-modules-adl.cppm | 3 ++ .../Modules/no-duplicate-codegen-in-GMF.cppm | 8 +++ clang/test/Modules/pair-unambiguous-ctor.cppm | 9 ++++ .../test/Modules/partial_specialization.cppm | 3 ++ .../test/Modules/placement-new-reachable.cpp | 3 ++ clang/test/Modules/polluted-operator.cppm | 3 ++ clang/test/Modules/pr54457.cppm | 3 ++ clang/test/Modules/pr56916.cppm | 12 +++++ clang/test/Modules/pr58532.cppm | 6 +++ clang/test/Modules/pr58716.cppm | 2 +- clang/test/Modules/pr59719.cppm | 3 ++ clang/test/Modules/pr59780.cppm | 8 +++ clang/test/Modules/pr59999.cppm | 13 +++++ clang/test/Modules/pr60036.cppm | 14 +++++ clang/test/Modules/pr60085.cppm | 17 ++++++ clang/test/Modules/pr60275.cppm | 7 ++- clang/test/Modules/pr60486.cppm | 3 ++ clang/test/Modules/pr60693.cppm | 4 ++ clang/test/Modules/pr60775.cppm | 13 +++++ clang/test/Modules/pr60890.cppm | 6 +++ clang/test/Modules/pr61065.cppm | 13 +++++ clang/test/Modules/pr61065_2.cppm | 15 ++++++ clang/test/Modules/pr61067.cppm | 14 +++++ clang/test/Modules/pr61317.cppm | 9 ++++ clang/test/Modules/pr61783.cppm | 8 +++ clang/test/Modules/pr61892.cppm | 40 +++++++------- clang/test/Modules/pr62158.cppm | 9 ++++ clang/test/Modules/pr62359.cppm | 16 ++++++ clang/test/Modules/pr62589.cppm | 3 ++ clang/test/Modules/pr62705.cppm | 8 +++ clang/test/Modules/pr62796.cppm | 4 ++ clang/test/Modules/pr62943.cppm | 12 +++++ clang/test/Modules/pr63544.cppm | 12 +++++ clang/test/Modules/pr63595.cppm | 10 ++++ clang/test/Modules/pr67627.cppm | 4 ++ clang/test/Modules/pr67893.cppm | 12 +++++ clang/test/Modules/predefined.cpp | 3 ++ clang/test/Modules/preferred_name.cppm | 10 ++++ clang/test/Modules/redefinition-merges.cppm | 6 +++ .../redundant-template-default-arg.cpp | 3 ++ .../redundant-template-default-arg2.cpp | 3 ++ .../redundant-template-default-arg3.cpp | 3 ++ clang/test/Modules/search-partitions.cpp | 16 ++++++ ...unction-definition-for-template-class.cppm | 12 +++++ .../template-function-specialization.cpp | 5 +- clang/test/Modules/template-lambdas.cppm | 15 ++++++ clang/test/Modules/template-pack.cppm | 3 ++ .../Modules/template_default_argument.cpp | 3 ++ clang/unittests/Sema/SemaNoloadLookupTest.cpp | 9 ++-- .../Serialization/ForceCheckFileInputTest.cpp | 10 ++-- .../Serialization/NoCommentsTest.cpp | 9 ++-- .../Serialization/VarDeclConstantInitTest.cpp | 13 +++-- 112 files changed, 1049 insertions(+), 83 deletions(-) create mode 100644 clang/test/Driver/thinBMI-output.cppm diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 676f1a62b49dd..aad67a9f4c7da 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -158,6 +158,8 @@ def err_drv_invalid_output_with_multiple_archs : Error< def err_drv_no_input_files : Error<"no input files">; def err_drv_output_argument_with_multiple_files : Error< "cannot specify -o when generating multiple output files">; +def err_drv_thin_bmi_output_argument_with_multiple_files : Error < + "cannot specify -fthinBMI-output when generating multiple module files">; def err_drv_out_file_argument_with_multiple_sources : Error< "cannot specify '%0%1' when compiling multiple source files">; def err_no_external_assembler : Error< diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 36052511203f6..12785f280183e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2915,6 +2915,11 @@ def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>, HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">; +def fthinBMI_output_EQ : Joined<["-"], "fthinBMI-output=">, Group, + HelpText<"Specify the output path for the thin BMI for C++20 Named modules">, + Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, + MarshallingInfoString>; + def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">, @@ -7223,7 +7228,9 @@ def ast_view : Flag<["-"], "ast-view">, def emit_module : Flag<["-"], "emit-module">, HelpText<"Generate pre-compiled module file from a module map">; def emit_module_interface : Flag<["-"], "emit-module-interface">, - HelpText<"Generate pre-compiled module file from a C++ module interface">; + HelpText<"Generate pre-compiled module file from a standard C++ module interface unit">; +def emit_thin_module_interface : Flag<["-"], "emit-thin-module-interface">, + HelpText<"Generate reduced prebuilt module interface from a standard C++ module interface unit">; def emit_header_unit : Flag<["-"], "emit-header-unit">, HelpText<"Generate C++20 header units from header files">; def emit_pch : Flag<["-"], "emit-pch">, diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 3940e00eeb8db..c419deb80034f 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -118,6 +118,9 @@ class GenerateModuleAction : public ASTFrontendAction { CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0; protected: + std::vector> + CreateMultiplexConsumer(CompilerInstance &CI, StringRef InFile); + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; @@ -147,14 +150,27 @@ class GenerateModuleFromModuleMapAction : public GenerateModuleAction { CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; +/// Generates fatBMI (which contains full information to generate the object +/// files) for C++20 Named Modules. Also generates the thin BMI (only contains +/// necessary information for importers) if `-fthinBMI-output=`. class GenerateModuleInterfaceAction : public GenerateModuleAction { -private: +protected: bool BeginSourceFileAction(CompilerInstance &CI) override; + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + std::unique_ptr CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; +/// Only generates the thin BMI. This action is mainly used by tests. +class GenerateThinModuleInterfaceAction : public GenerateModuleInterfaceAction { +private: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + class GenerateHeaderUnitAction : public GenerateModuleAction { private: diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 53a8681cfdbba..719d4ca813361 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -85,9 +85,13 @@ enum ActionKind { /// Generate pre-compiled module from a module map. GenerateModule, - /// Generate pre-compiled module from a C++ module interface file. + /// Generate pre-compiled module from a standard C++ module interface unit. GenerateModuleInterface, + /// Generate reduced module interface for a standard C++ module interface + /// unit. + GenerateThinModuleInterface, + /// Generate a C++20 header unit module from a header file. GenerateHeaderUnit, @@ -549,6 +553,9 @@ class FrontendOptions { /// Path which stores the output files for -ftime-trace std::string TimeTracePath; + /// Path to the thin BMI for -fthinbmi-output= + std::string ThinBMIPath; + public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 3019bbc2ddc9c..3ccb35aa72f9b 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -166,6 +166,10 @@ class ASTWriter : public ASTDeserializationListener, /// Indicates that the AST contained compiler errors. bool ASTHasCompilerErrors = false; + /// Indicates that we're going to generate the reduced BMI for C++20 + /// named modules. + bool GeneratingThinBMI = false; + /// Mapping from input file entries to the index into the /// offset table where information about that input file is stored. llvm::DenseMap InputFileIDs; @@ -582,7 +586,8 @@ class ASTWriter : public ASTDeserializationListener, ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl &Buffer, InMemoryModuleCache &ModuleCache, ArrayRef> Extensions, - bool IncludeTimestamps = true, bool BuildingImplicitModule = false); + bool IncludeTimestamps = true, bool BuildingImplicitModule = false, + bool GeneratingThinBMI = false); ~ASTWriter() override; ASTContext &getASTContext() const { @@ -813,6 +818,13 @@ class PCHGenerator : public SemaConsumer { const ASTWriter &getWriter() const { return Writer; } SmallVectorImpl &getPCH() const { return Buffer->Data; } + bool isComplete() const { return Buffer->IsComplete; } + PCHBuffer *getBufferPtr() { return Buffer.get(); } + StringRef getOutputFile() const { return OutputFile; } + DiagnosticsEngine &getDiagnostics() const { + return SemaPtr->getDiagnostics(); + } + public: PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, StringRef isysroot, @@ -820,7 +832,8 @@ class PCHGenerator : public SemaConsumer { ArrayRef> Extensions, bool AllowASTWithErrors = false, bool IncludeTimestamps = true, bool BuildingImplicitModule = false, - bool ShouldCacheASTInMemory = false); + bool ShouldCacheASTInMemory = false, + bool GeneratingThinBMI = false); ~PCHGenerator() override; void InitializeSema(Sema &S) override { SemaPtr = &S; } @@ -830,6 +843,19 @@ class PCHGenerator : public SemaConsumer { bool hasEmittedPCH() const { return Buffer->IsComplete; } }; +class ThinBMIGenerator : public PCHGenerator { +public: + ThinBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, + StringRef OutputFile, std::shared_ptr Buffer, + bool IncludeTimestamps); + + void HandleTranslationUnit(ASTContext &Ctx) override; +}; + +/// If the definition may impact the ABI. If yes, we're allowed to eliminate +/// the definition of D in thin BMI. +bool MayDefAffectABI(const Decl *D); + /// A simple helper class to pack several bits in order into (a) 32 bit /// integer(s). class BitsPacker { diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 6f5ff81410326..76def412d1255 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4086,6 +4086,13 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, } } + // Diagnose misuse of -fthinBMI-output. It should be an error if we specify + // -fthinBMI-output with multiple precompilation jobs. Here we didn't check if + // there are multiple module units in the inputs. + if (C.getArgs().getLastArg(options::OPT_fthinBMI_output_EQ) && + Inputs.size() > 1) + Diag(clang::diag::err_drv_thin_bmi_output_argument_with_multiple_files); + handleArguments(C, Args, Inputs, Actions); bool UseNewOffloadingDriver = diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 22f992166ded6..5bb945be78dcb 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3940,6 +3940,8 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D, Args.ClaimAllArgs(options::OPT_fmodule_output); Args.ClaimAllArgs(options::OPT_fmodule_output_EQ); + Args.AddLastArg(CmdArgs, options::OPT_fthinBMI_output_EQ); + return HaveModules; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 637c6a35af653..b6245d0dddb10 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2554,6 +2554,7 @@ static const auto &getFrontendActionTable() { {frontend::GenerateModule, OPT_emit_module}, {frontend::GenerateModuleInterface, OPT_emit_module_interface}, + {frontend::GenerateThinModuleInterface, OPT_emit_thin_module_interface}, {frontend::GenerateHeaderUnit, OPT_emit_header_unit}, {frontend::GeneratePCH, OPT_emit_pch}, {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs}, @@ -4236,6 +4237,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::FixIt: case frontend::GenerateModule: case frontend::GenerateModuleInterface: + case frontend::GenerateThinModuleInterface: case frontend::GenerateHeaderUnit: case frontend::GeneratePCH: case frontend::GenerateInterfaceStubs: diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 2afcf1cf9f68c..1aaebd1602016 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -184,12 +184,12 @@ bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) { return true; } -std::unique_ptr -GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { +std::vector> +GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI, + StringRef InFile) { std::unique_ptr OS = CreateOutputFile(CI, InFile); if (!OS) - return nullptr; + return {}; std::string OutputFile = CI.getFrontendOpts().OutputFile; std::string Sysroot; @@ -210,6 +210,17 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, +CI.getFrontendOpts().BuildingImplicitModule)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, std::string(InFile), OutputFile, std::move(OS), Buffer)); + return std::move(Consumers); +} + +std::unique_ptr +GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + std::vector> Consumers = + CreateMultiplexConsumer(CI, InFile); + if (Consumers.empty()) + return nullptr; + return std::make_unique(std::move(Consumers)); } @@ -264,6 +275,35 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm"); } +static std::unique_ptr +CreateThinBMIGenerator(CompilerInstance &CI, StringRef OutputFile) { + auto Buffer = std::make_shared(); + return std::make_unique( + CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Buffer, + /*IncludeTimestamps=*/+CI.getFrontendOpts().IncludeTimestamps); +} + +std::unique_ptr +GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + std::vector> Consumers = + CreateMultiplexConsumer(CI, InFile); + if (Consumers.empty()) + return nullptr; + + if (!CI.getFrontendOpts().ThinBMIPath.empty()) + Consumers.push_back( + CreateThinBMIGenerator(CI, CI.getFrontendOpts().ThinBMIPath)); + + return std::make_unique(std::move(Consumers)); +} + +std::unique_ptr +GenerateThinModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return CreateThinBMIGenerator(CI, CI.getFrontendOpts().OutputFile); +} + bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) { if (!CI.getLangOpts().CPlusPlusModules) { CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules); @@ -830,7 +870,6 @@ void DumpModuleInfoAction::ExecuteAction() { const LangOptions &LO = getCurrentASTUnit().getLangOpts(); if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) { - ASTReader *R = getCurrentASTUnit().getASTReader().get(); unsigned SubModuleCount = R->getTotalNumSubmodules(); serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule(); diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index b280a1359d2f2..59f7f955db509 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -65,6 +65,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { return std::make_unique(); case GenerateModuleInterface: return std::make_unique(); + case GenerateThinModuleInterface: + return std::make_unique(); case GenerateHeaderUnit: return std::make_unique(); case GeneratePCH: return std::make_unique(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 0d347d86cb2eb..ee8ba8a6874b5 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4593,10 +4593,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl &Buffer, InMemoryModuleCache &ModuleCache, ArrayRef> Extensions, - bool IncludeTimestamps, bool BuildingImplicitModule) + bool IncludeTimestamps, bool BuildingImplicitModule, + bool GeneratingThinBMI) : Stream(Stream), Buffer(Buffer), ModuleCache(ModuleCache), IncludeTimestamps(IncludeTimestamps), - BuildingImplicitModule(BuildingImplicitModule) { + BuildingImplicitModule(BuildingImplicitModule), + GeneratingThinBMI(GeneratingThinBMI) { for (const auto &Ext : Extensions) { if (auto Writer = Ext->createExtensionWriter(*this)) ModuleFileExtensionWriters.push_back(std::move(Writer)); @@ -5403,18 +5405,20 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { // Add a trailing update record, if any. These must go last because we // lazily load their attached statement. - if (HasUpdatedBody) { - const auto *Def = cast(D); - Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION); - Record.push_back(Def->isInlined()); - Record.AddSourceLocation(Def->getInnerLocStart()); - Record.AddFunctionDefinition(Def); - } else if (HasAddedVarDefinition) { - const auto *VD = cast(D); - Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION); - Record.push_back(VD->isInline()); - Record.push_back(VD->isInlineSpecified()); - Record.AddVarDeclInit(VD); + if (!GeneratingThinBMI || MayDefAffectABI(D)) { + if (HasUpdatedBody) { + const auto *Def = cast(D); + Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION); + Record.push_back(Def->isInlined()); + Record.AddSourceLocation(Def->getInnerLocStart()); + Record.AddFunctionDefinition(Def); + } else if (HasAddedVarDefinition) { + const auto *VD = cast(D); + Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION); + Record.push_back(VD->isInline()); + Record.push_back(VD->isInlineSpecified()); + Record.AddVarDeclInit(VD); + } } OffsetsRecord.push_back(GetDeclRef(D)); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 763b610288f11..00a04ee2fa730 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" +#include "clang/AST/ODRHash.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/SourceManager.h" @@ -40,11 +41,14 @@ namespace clang { serialization::DeclCode Code; unsigned AbbrevToUse; + bool GeneratingThinBMI = false; + public: ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, - ASTWriter::RecordDataImpl &Record) + ASTWriter::RecordDataImpl &Record, bool GeneratingThinBMI) : Writer(Writer), Context(Context), Record(Writer, Record), - Code((serialization::DeclCode)0), AbbrevToUse(0) {} + Code((serialization::DeclCode)0), AbbrevToUse(0), + GeneratingThinBMI(GeneratingThinBMI) {} uint64_t Emit(Decl *D) { if (!Code) @@ -270,6 +274,35 @@ namespace clang { }; } +bool clang::MayDefAffectABI(const Decl *D) { + if (auto *FD = dyn_cast(D)) { + if (FD->isInlined() || FD->isConstexpr()) + return true; + + // Non-user-provided functions get emitted as weak definitions with every + // use, no matter whether they've been explicitly instantiated etc. + if (!FD->isUserProvided()) + return true; + + if (FD->isDependentContext()) + return true; + + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return true; + } + + if (auto *VD = dyn_cast(D)) { + if (!VD->getDeclContext()->getRedeclContext()->isFileContext() || + VD->isInline() || VD->isConstexpr() || isa(VD)) + return true; + + if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return true; + } + + return false; +} + void ASTDeclWriter::Visit(Decl *D) { DeclVisitor::Visit(D); @@ -285,9 +318,12 @@ void ASTDeclWriter::Visit(Decl *D) { // have been written. We want it last because we will not read it back when // retrieving it from the AST, we'll just lazily set the offset. if (auto *FD = dyn_cast(D)) { - Record.push_back(FD->doesThisDeclarationHaveABody()); - if (FD->doesThisDeclarationHaveABody()) - Record.AddFunctionDefinition(FD); + if (!GeneratingThinBMI || MayDefAffectABI(FD)) { + Record.push_back(FD->doesThisDeclarationHaveABody()); + if (FD->doesThisDeclarationHaveABody()) + Record.AddFunctionDefinition(FD); + } else + Record.push_back(0); } // Similar to FunctionDecls, handle VarDecl's initializer here and write it @@ -295,7 +331,10 @@ void ASTDeclWriter::Visit(Decl *D) { // we have finished recursive deserialization, because it can recursively // refer back to the variable. if (auto *VD = dyn_cast(D)) { - Record.AddVarDeclInit(VD); + if (!GeneratingThinBMI || MayDefAffectABI(VD)) + Record.AddVarDeclInit(VD); + else + Record.push_back(0); } // And similarly for FieldDecls. We already serialized whether there is a @@ -2486,7 +2525,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { assert(ID >= FirstDeclID && "invalid decl ID"); RecordData Record; - ASTDeclWriter W(*this, Context, Record); + ASTDeclWriter W(*this, Context, Record, GeneratingThinBMI); // Build a record for this declaration W.Visit(D); diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index cf8084333811f..a51047a148c93 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -12,9 +12,11 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaConsumer.h" +#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/Bitstream/BitstreamWriter.h" @@ -25,11 +27,12 @@ PCHGenerator::PCHGenerator( StringRef OutputFile, StringRef isysroot, std::shared_ptr Buffer, ArrayRef> Extensions, bool AllowASTWithErrors, bool IncludeTimestamps, - bool BuildingImplicitModule, bool ShouldCacheASTInMemory) + bool BuildingImplicitModule, bool ShouldCacheASTInMemory, + bool GeneratingThinBMI) : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data), Writer(Stream, this->Buffer->Data, ModuleCache, Extensions, - IncludeTimestamps, BuildingImplicitModule), + IncludeTimestamps, BuildingImplicitModule, GeneratingThinBMI), AllowASTWithErrors(AllowASTWithErrors), ShouldCacheASTInMemory(ShouldCacheASTInMemory) { this->Buffer->IsComplete = false; @@ -78,3 +81,32 @@ ASTMutationListener *PCHGenerator::GetASTMutationListener() { ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { return &Writer; } + +ThinBMIGenerator::ThinBMIGenerator( + const Preprocessor &PP, InMemoryModuleCache &ModuleCache, + StringRef OutputFile, std::shared_ptr Buffer, + bool IncludeTimestamps) + : PCHGenerator( + PP, ModuleCache, OutputFile, llvm::StringRef(), Buffer, + /*Extensions=*/ArrayRef>(), + /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/IncludeTimestamps, + /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false, + /*GeneratingThinBMI=*/true) {} + +void ThinBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) { + PCHGenerator::HandleTranslationUnit(Ctx); + + if (!isComplete()) + return; + + std::error_code EC; + auto OS = std::make_unique(getOutputFile(), EC); + if (EC) { + getDiagnostics().Report(diag::err_fe_unable_to_open_output) + << getOutputFile() << EC.message() << "\n"; + return; + } + + *OS << getBufferPtr()->Data; + OS->flush(); +} diff --git a/clang/test/CXX/basic/basic.link/p10-ex2.cpp b/clang/test/CXX/basic/basic.link/p10-ex2.cpp index 95fdb56f78d62..98daf12cefc64 100644 --- a/clang/test/CXX/basic/basic.link/p10-ex2.cpp +++ b/clang/test/CXX/basic/basic.link/p10-ex2.cpp @@ -4,8 +4,9 @@ // RUN: cd %t // // RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify -// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm +// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm -fthinBMI-output=M.thin.pcm // RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M=M.pcm -verify +// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M=M.thin.pcm -verify //--- decls.h int f(); // #1, attached to the global module diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp index 638057cbd681f..3a46a218bef03 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp @@ -7,8 +7,10 @@ // RUN: mkdir %t // RUN: split-file %s %t // -// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Friend-in-reachable-class.cppm -o %t/X.pcm -// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Friend-in-reachable-class.cppm \ +// RUN: -fthinBMI-output=%t/X.thin.pcm -o %t/X.pcm +// RUN: %clang_cc1 -std=c++20 -fmodule-file=X=%t/X.pcm %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fmodule-file=X=%t/X.thin.pcm %t/Use.cpp -verify -fsyntax-only // //--- Friend-in-reachable-class.cppm module; diff --git a/clang/test/Driver/thinBMI-output.cppm b/clang/test/Driver/thinBMI-output.cppm new file mode 100644 index 0000000000000..e3268dcf6c159 --- /dev/null +++ b/clang/test/Driver/thinBMI-output.cppm @@ -0,0 +1,29 @@ +// It is annoying to handle different slash direction +// in Windows and Linux. So we disable the test on Windows +// here. +// REQUIRES: !system-windows +// On AIX, the default output for `-c` may be `.s` instead of `.o`, +// which makes the test fail. So disable the test on AIX. +// REQUIRES: !system-aix +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/Hello.cppm -fthinBMI-output=%t/Hello.pcm -c -o %t/Hello.o \ +// RUN: -### 2>&1 | FileCheck %t/Hello.cppm +// RUN: %clang -std=c++20 %t/Hello.cppm -fthinBMI-output=%t/Hello.pcm --precompile \ +// RUN: -o %t/Hello.pcm -### 2>&1 | FileCheck %t/Hello.cppm +// +// Tests that we can't use `-fthinBMI-output=` with multiple input files +// RUN: not %clang -std=c++20 %t/Hello.cppm %t/a.cppm -fthinBMI-output=%t/Hello.pcm \ +// RUN: -o %t/a.out -### 2>&1 | FileCheck %t/a.cppm + +//--- Hello.cppm +export module Hello; + +// CHECK: "-emit-module-interface"{{.*}}"-fthinBMI-output={{[a-zA-Z0-9./-]*}}Hello.pcm" + +//--- a.cppm +export module a; +// CHECK: cannot specify -fthinBMI-output when generating multiple module files diff --git a/clang/test/Modules/InheritDefaultArguments.cppm b/clang/test/Modules/InheritDefaultArguments.cppm index 0afb46319ff85..1bf7c3210bf61 100644 --- a/clang/test/Modules/InheritDefaultArguments.cppm +++ b/clang/test/Modules/InheritDefaultArguments.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only + //--- foo.h template class Templ; diff --git a/clang/test/Modules/Reachability-Private.cpp b/clang/test/Modules/Reachability-Private.cpp index 9a7c3ba231f17..e29906ccf743c 100644 --- a/clang/test/Modules/Reachability-Private.cpp +++ b/clang/test/Modules/Reachability-Private.cpp @@ -9,6 +9,16 @@ // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \ // RUN: -DTEST_BADINLINE -verify -fsyntax-only +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/Private.cppm -emit-thin-module-interface \ +// RUN: -o %t/Private.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \ +// RUN: -DTEST_BADINLINE -verify -fsyntax-only + //--- Private.cppm export module Private; #ifdef TEST_BADINLINE diff --git a/clang/test/Modules/Reachability-func-default-arg.cpp b/clang/test/Modules/Reachability-func-default-arg.cpp index 0d6d8655d5329..6bf0bcadc7e76 100644 --- a/clang/test/Modules/Reachability-func-default-arg.cpp +++ b/clang/test/Modules/Reachability-func-default-arg.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-module-interface -o %t/func_default_arg.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + +// RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-thin-module-interface -o %t/func_default_arg.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only // //--- func_default_arg.cppm export module func_default_arg; diff --git a/clang/test/Modules/Reachability-func-ret.cpp b/clang/test/Modules/Reachability-func-ret.cpp index ca5bbc68d759f..4bc2e0c5ec294 100644 --- a/clang/test/Modules/Reachability-func-ret.cpp +++ b/clang/test/Modules/Reachability-func-ret.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-module-interface -o %t/func_ret.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + +// RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-thin-module-interface -o %t/func_ret.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only // //--- func_ret.cppm export module func_ret; diff --git a/clang/test/Modules/Reachability-template-default-arg.cpp b/clang/test/Modules/Reachability-template-default-arg.cpp index 6fb109e41fcf0..3e1bcd1888ef8 100644 --- a/clang/test/Modules/Reachability-template-default-arg.cpp +++ b/clang/test/Modules/Reachability-template-default-arg.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-module-interface -o %t/template_default_arg.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify + +// RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-thin-module-interface -o %t/template_default_arg.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // //--- template_default_arg.cppm export module template_default_arg; diff --git a/clang/test/Modules/Reachability-template-instantiation.cpp b/clang/test/Modules/Reachability-template-instantiation.cpp index 2170c7b92a370..3dd2268a23433 100644 --- a/clang/test/Modules/Reachability-template-instantiation.cpp +++ b/clang/test/Modules/Reachability-template-instantiation.cpp @@ -5,6 +5,10 @@ // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/Use.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only + +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-thin-module-interface -o %t/Use.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only // //--- Templ.h #ifndef TEMPL_H diff --git a/clang/test/Modules/Reachability-using-templates.cpp b/clang/test/Modules/Reachability-using-templates.cpp index f530e15bd4d2b..5dc5b48cbaf85 100644 --- a/clang/test/Modules/Reachability-using-templates.cpp +++ b/clang/test/Modules/Reachability-using-templates.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-module-interface -o %t/mod.templates.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify + +// RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-thin-module-interface -o %t/mod.templates.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // //--- mod.templates.cppm export module mod.templates; diff --git a/clang/test/Modules/Reachability-using.cpp b/clang/test/Modules/Reachability-using.cpp index 642b97dd8432c..eaa7ed852ed14 100644 --- a/clang/test/Modules/Reachability-using.cpp +++ b/clang/test/Modules/Reachability-using.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-module-interface -o %t/mod.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify + +// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-thin-module-interface -o %t/mod.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // //--- mod.cppm export module mod; diff --git a/clang/test/Modules/concept.cppm b/clang/test/Modules/concept.cppm index 0e85a46411a54..a41ce72ed9e26 100644 --- a/clang/test/Modules/concept.cppm +++ b/clang/test/Modules/concept.cppm @@ -5,6 +5,10 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.full.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify //--- foo.h #ifndef FOO_H diff --git a/clang/test/Modules/concept_differ.cppm b/clang/test/Modules/concept_differ.cppm index ccb29d26e53d1..7341af8f39984 100644 --- a/clang/test/Modules/concept_differ.cppm +++ b/clang/test/Modules/concept_differ.cppm @@ -5,6 +5,11 @@ // RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-module-interface -o %t/B.pcm // RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp -verify +// +// RUN: rm %t/A.pcm %t/B.pcm +// RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-thin-module-interface -o %t/B.pcm +// RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp -verify //--- foo.h template diff --git a/clang/test/Modules/ctor.arg.dep.cppm b/clang/test/Modules/ctor.arg.dep.cppm index 0e5b1a694f6a5..28ab704e5628d 100644 --- a/clang/test/Modules/ctor.arg.dep.cppm +++ b/clang/test/Modules/ctor.arg.dep.cppm @@ -5,6 +5,10 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only // +// RUN: rm %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// //--- foo.h namespace ns { diff --git a/clang/test/Modules/cxx20-10-1-ex1.cpp b/clang/test/Modules/cxx20-10-1-ex1.cpp index b9a5e8023d035..772555b25b80a 100644 --- a/clang/test/Modules/cxx20-10-1-ex1.cpp +++ b/clang/test/Modules/cxx20-10-1-ex1.cpp @@ -17,6 +17,19 @@ // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex1-tu4.cpp \ // RUN: -fmodule-file=%t/A.pcm -o %t/ex1.o +// RUN: rm %t/A_Internals.pcm %t/A_Foo.pcm %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex1-tu1.cpp \ +// RUN: -o %t/A_Internals.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex1-tu2.cpp \ +// RUN: -fmodule-file=%t/A_Internals.pcm -o %t/A_Foo.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex1-tu3.cpp \ +// RUN: -fmodule-file=%t/A_Foo.pcm -o %t/A.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex1-tu4.cpp \ +// RUN: -fmodule-file=%t/A.pcm -o %t/ex1.o + // expected-no-diagnostics //--- std10-1-ex1-tu1.cpp diff --git a/clang/test/Modules/cxx20-10-1-ex2.cpp b/clang/test/Modules/cxx20-10-1-ex2.cpp index 8b908d5fa2eda..f273655783eec 100644 --- a/clang/test/Modules/cxx20-10-1-ex2.cpp +++ b/clang/test/Modules/cxx20-10-1-ex2.cpp @@ -5,26 +5,50 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu1.cpp \ // RUN: -o %t/B_Y.pcm - +// // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu2.cpp \ // RUN: -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B.pcm - +// // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu3.cpp \ // RUN: -o %t/B_X1.pcm -verify - +// // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu4.cpp \ // RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B_X2.pcm - +// // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \ // RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm -o %t/b_tu5.o - +// // RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \ // RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm -o %t/b_tu6.s -verify - +// // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu7.cpp \ // RUN: -fmodule-file=B:X2=%t/B_X2.pcm -fmodule-file=B=%t/B.pcm \ // RUN: -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B_X3.pcm -verify +// Test again with thin BMI. +// RUN: rm %t/B_X2.pcm %t/B.pcm %t/B_Y.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu1.cpp \ +// RUN: -o %t/B_Y.pcm +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu2.cpp \ +// RUN: -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B.pcm +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu3.cpp \ +// RUN: -o %t/B_X1.pcm -verify +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu4.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B_X2.pcm +// +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm -o %t/b_tu5.o +// +// RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm -o %t/b_tu6.s -verify +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu7.cpp \ +// RUN: -fmodule-file=B:X2=%t/B_X2.pcm -fmodule-file=B=%t/B.pcm \ +// RUN: -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B_X3.pcm -verify + //--- std10-1-ex2-tu1.cpp module B:Y; int y(); diff --git a/clang/test/Modules/cxx20-10-2-ex2.cpp b/clang/test/Modules/cxx20-10-2-ex2.cpp index bc66d6a2ec1a9..21fae454d5105 100644 --- a/clang/test/Modules/cxx20-10-2-ex2.cpp +++ b/clang/test/Modules/cxx20-10-2-ex2.cpp @@ -14,6 +14,18 @@ // RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=X=%t/X.pcm \ // RUN: -pedantic-errors -verify -o %t/M.pcm +// Test again with thin BMI. +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I %t \ +// RUN: -xc++-user-header std-10-2-ex2-c.h -o %t/std-10-2-ex2-c.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std-10-2-ex2-tu1.cpp \ +// RUN: -o %t/X.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std-10-2-ex2-tu2.cpp \ +// RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=X=%t/X.pcm \ +// RUN: -pedantic-errors -verify -o %t/M.pcm + + //--- std-10-2-ex2-b.h int f(); diff --git a/clang/test/Modules/cxx20-10-2-ex5.cpp b/clang/test/Modules/cxx20-10-2-ex5.cpp index 49c5934c8f217..c3555cf8f67eb 100644 --- a/clang/test/Modules/cxx20-10-2-ex5.cpp +++ b/clang/test/Modules/cxx20-10-2-ex5.cpp @@ -13,6 +13,18 @@ // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \ // RUN: -fmodule-file=M=%t/M.pcm -verify -o %t/main.o +// Test again with thin BMI. +// RUN: rm %t/M.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std-10-2-ex5-tu1.cpp \ +// RUN: -o %t/M.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu2.cpp \ +// RUN: -fmodule-file=M=%t/M.pcm -o %t/tu-2.o + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \ +// RUN: -fmodule-file=M=%t/M.pcm -verify -o %t/main.o + + //--- std-10-2-ex5-tu1.cpp export module M; export struct X { diff --git a/clang/test/Modules/cxx20-10-3-ex1.cpp b/clang/test/Modules/cxx20-10-3-ex1.cpp index 5d6e2554f753b..c87e6d084d10c 100644 --- a/clang/test/Modules/cxx20-10-3-ex1.cpp +++ b/clang/test/Modules/cxx20-10-3-ex1.cpp @@ -14,6 +14,20 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu4.cpp \ // RUN: -fmodule-file=M:Part=%t/M_Part.pcm -o %t/M.pcm +// Test again with thin BMI. +// RUN: rm %t/M_PartImpl.pcm %t/M.pcm %t/M_Part.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu1.cpp \ +// RUN: -o %t/M_PartImpl.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu2.cpp \ +// RUN: -fmodule-file=M:PartImpl=%t/M_PartImpl.pcm -o %t/M.pcm -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu3.cpp \ +// RUN: -o %t/M_Part.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu4.cpp \ +// RUN: -fmodule-file=M:Part=%t/M_Part.pcm -o %t/M.pcm + //--- std10-3-ex1-tu1.cpp module M:PartImpl; diff --git a/clang/test/Modules/cxx20-10-3-ex2.cpp b/clang/test/Modules/cxx20-10-3-ex2.cpp index b1d6d669c0a0e..9367114181038 100644 --- a/clang/test/Modules/cxx20-10-3-ex2.cpp +++ b/clang/test/Modules/cxx20-10-3-ex2.cpp @@ -11,6 +11,16 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex2-tu3.cpp \ // RUN: -o %t/M.pcm -verify +// Test again with thin BMI. +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex2-tu1.cpp \ +// RUN: -o %t/M.pcm + +// RUN: %clang_cc1 -std=c++20 -S %t/std10-3-ex2-tu2.cpp \ +// RUN: -fmodule-file=M=%t/M.pcm -o %t/tu_8.s -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex2-tu3.cpp \ +// RUN: -o %t/M.pcm -verify + //--- std10-3-ex2-tu1.cpp export module M; diff --git a/clang/test/Modules/cxx20-10-5-ex1.cpp b/clang/test/Modules/cxx20-10-5-ex1.cpp index a83162c5c1501..2eb27d2c93c54 100644 --- a/clang/test/Modules/cxx20-10-5-ex1.cpp +++ b/clang/test/Modules/cxx20-10-5-ex1.cpp @@ -11,6 +11,18 @@ // RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp -fmodule-file=A=A.pcm \ // RUN: -fsyntax-only -verify +// Test again with thin BMI. +// RUN: rm A.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface std-10-5-ex1-interface.cpp \ +// RUN: -DBAD_FWD_DECL -fsyntax-only -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface std-10-5-ex1-interface.cpp \ +// RUN: -o A.pcm + +// RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp -fmodule-file=A=A.pcm \ +// RUN: -fsyntax-only -verify + + //--- std-10-5-ex1-interface.cpp export module A; diff --git a/clang/test/Modules/cxx20-import-diagnostics-a.cpp b/clang/test/Modules/cxx20-import-diagnostics-a.cpp index a5cf44ed82d5f..fb4d5d917a9e3 100644 --- a/clang/test/Modules/cxx20-import-diagnostics-a.cpp +++ b/clang/test/Modules/cxx20-import-diagnostics-a.cpp @@ -36,6 +36,45 @@ // RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \ // RUN: -fmodule-file=C=%t/C.pcm -o %t/impl.o +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu1.cpp \ +// RUN: -o %t/B.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu2.cpp \ +// RUN: -o %t/C.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu3.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/AOK1.pcm + +// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu4.cpp \ +// RUN: -fmodule-file=AOK1=%t/AOK1.pcm -fmodule-file=B=%t/B.pcm \ +// RUN: -fmodule-file=C=%t/C.pcm -o %t/tu_3.s -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu5.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/BC.pcm -verify + +// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu6.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/tu_5.s -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu7.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -o %t/D.pcm -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu8.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -o %t/D.pcm -verify + +// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu9.cpp \ +// RUN: -fmodule-file=B=%t/B.pcm -o %t/tu_8.s -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu10.cpp \ +// RUN: -o %t/B.pcm -verify + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \ +// RUN: -fmodule-file=C=%t/C.pcm -o %t/impl.o + // Test diagnostics for incorrect module import sequences. //--- import-diags-tu1.cpp diff --git a/clang/test/Modules/cxx20-import-diagnostics-b.cpp b/clang/test/Modules/cxx20-import-diagnostics-b.cpp index 7d432633552a2..baba79c4384f6 100644 --- a/clang/test/Modules/cxx20-import-diagnostics-b.cpp +++ b/clang/test/Modules/cxx20-import-diagnostics-b.cpp @@ -22,6 +22,31 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/g.cpp \ // RUN: -fmodule-file=a=%t/a.pcm -o %t/g.pcm -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cpp -o %t/a.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/c.cpp \ +// RUN: -fmodule-file=a=%t/a.pcm -o %t/c.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/d.cpp \ +// RUN: -fmodule-file=a=%t/a.pcm -o %t/d.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/e.cpp \ +// RUN: -fmodule-file=a=%t/a.pcm -o %t/e.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a-part.cpp \ +// RUN: -o %t/a-part.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/f.cpp \ +// RUN: -fmodule-file=a=%t/a.pcm -o %t/f.pcm -verify + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/g.cpp \ +// RUN: -fmodule-file=a=%t/a.pcm -o %t/g.pcm -verify + //--- a.cpp export module a; diff --git a/clang/test/Modules/cxx20-module-file-info-macros.cpp b/clang/test/Modules/cxx20-module-file-info-macros.cpp index bc7df1c9f50b5..caa7fe49a89db 100644 --- a/clang/test/Modules/cxx20-module-file-info-macros.cpp +++ b/clang/test/Modules/cxx20-module-file-info-macros.cpp @@ -17,6 +17,9 @@ // RUN: %clang_cc1 -std=c++20 %t/named_module.cppm -emit-module-interface -o %t/M.pcm // RUN: %clang_cc1 -module-file-info %t/M.pcm | FileCheck %t/named_module.cppm +// RUN: %clang_cc1 -std=c++20 %t/named_module.cppm -emit-thin-module-interface -o %t/M.pcm +// RUN: %clang_cc1 -module-file-info %t/M.pcm | FileCheck %t/named_module.cppm + //--- foo.h #pragma once #define FOO diff --git a/clang/test/Modules/deduction-guide.cppm b/clang/test/Modules/deduction-guide.cppm index 9c959a71365da..01ffc990bb067 100644 --- a/clang/test/Modules/deduction-guide.cppm +++ b/clang/test/Modules/deduction-guide.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + //--- foo.h template class Templ { diff --git a/clang/test/Modules/deduction-guide2.cppm b/clang/test/Modules/deduction-guide2.cppm index a163c36568310..c5ae73fe7bbc0 100644 --- a/clang/test/Modules/deduction-guide2.cppm +++ b/clang/test/Modules/deduction-guide2.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + //--- Templ.cppm export module Templ; export template diff --git a/clang/test/Modules/deduction-guide3.cppm b/clang/test/Modules/deduction-guide3.cppm index 8fa08a0625d7c..38a817a9e3323 100644 --- a/clang/test/Modules/deduction-guide3.cppm +++ b/clang/test/Modules/deduction-guide3.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + //--- Templ.cppm export module Templ; template diff --git a/clang/test/Modules/derived_class.cpp b/clang/test/Modules/derived_class.cpp index ee9e0ae4637ec..c016d5b0477f4 100644 --- a/clang/test/Modules/derived_class.cpp +++ b/clang/test/Modules/derived_class.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-module-interface -o %t/foo.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify + +// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-thin-module-interface -o %t/foo.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // //--- bar.h struct bar_base { diff --git a/clang/test/Modules/duplicated-module-file-eq-module-name.cppm b/clang/test/Modules/duplicated-module-file-eq-module-name.cppm index e86dbe2b941ef..1d84a1ce3f6dc 100644 --- a/clang/test/Modules/duplicated-module-file-eq-module-name.cppm +++ b/clang/test/Modules/duplicated-module-file-eq-module-name.cppm @@ -8,6 +8,10 @@ // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 %t/u.cpp -fmodule-file=a=%t/unexist.pcm \ // RUN: -fmodule-file=a=%t/a.pcm -verify -fsyntax-only +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/u.cpp -fmodule-file=a=%t/unexist.pcm \ +// RUN: -fmodule-file=a=%t/a.pcm -verify -fsyntax-only //--- a.cppm export module a; diff --git a/clang/test/Modules/enum-class.cppm b/clang/test/Modules/enum-class.cppm index 01ae8c0d8814d..0c4f2079a3c5f 100644 --- a/clang/test/Modules/enum-class.cppm +++ b/clang/test/Modules/enum-class.cppm @@ -6,6 +6,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only //--- foo.h enum class foo { diff --git a/clang/test/Modules/explicitly-specialized-template.cpp b/clang/test/Modules/explicitly-specialized-template.cpp index 89677254ea739..0ccd8aa771f18 100644 --- a/clang/test/Modules/explicitly-specialized-template.cpp +++ b/clang/test/Modules/explicitly-specialized-template.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-module-interface -o %t/X.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // +// RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-thin-module-interface -o %t/X.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify +// //--- foo.h #ifndef FOO_H #define FOO_H diff --git a/clang/test/Modules/export-language-linkage.cppm b/clang/test/Modules/export-language-linkage.cppm index 331a620aaad06..4927eb18b1523 100644 --- a/clang/test/Modules/export-language-linkage.cppm +++ b/clang/test/Modules/export-language-linkage.cppm @@ -7,6 +7,11 @@ // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fsyntax-only -verify // RUN: %clang_cc1 -module-file-info %t/a.pcm | FileCheck %t/a.cppm +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fsyntax-only -verify +// RUN: %clang_cc1 -module-file-info %t/a.pcm | FileCheck %t/a.cppm + //--- a.cppm export module a; export extern "C++" int foo() { return 43; } diff --git a/clang/test/Modules/ftime-trace.cppm b/clang/test/Modules/ftime-trace.cppm index 48cd4113ec782..f8c8f7dfb0b2b 100644 --- a/clang/test/Modules/ftime-trace.cppm +++ b/clang/test/Modules/ftime-trace.cppm @@ -9,5 +9,14 @@ // RUN: %clang_cc1 -std=c++20 %t/a.pcm -ftime-trace=%t/a.json -o - // RUN: ls %t | grep "a.json" +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/a.pcm -ftime-trace=%t/a.json -o - +// RUN: ls %t | grep "a.json" + //--- a.cppm export module a; diff --git a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm index abcbec07f97de..17740cf1f5fd2 100644 --- a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm +++ b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm @@ -8,6 +8,12 @@ // RUN: %clang_cc1 -std=c++20 %t/D.cppm -I%t -emit-module-interface -o %t/D.pcm // RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/D-part.cppm -I%t -fprebuilt-module-path=%t -verify +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -I%t -emit-thin-module-interface -o %t/B.pcm +// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/A.cppm -I%t -fprebuilt-module-path=%t -verify +// +// RUN: %clang_cc1 -std=c++20 %t/D.cppm -I%t -emit-thin-module-interface -o %t/D.pcm +// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/D-part.cppm -I%t -fprebuilt-module-path=%t -verify + //--- A.cppm module; export module baz:A; diff --git a/clang/test/Modules/inconsistent-export.cppm b/clang/test/Modules/inconsistent-export.cppm index 5e94d2b37b757..14689407b45d5 100644 --- a/clang/test/Modules/inconsistent-export.cppm +++ b/clang/test/Modules/inconsistent-export.cppm @@ -9,6 +9,19 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -emit-obj +// Test again with thin BMI. +// RUN: rm -fr %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/m-a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/m-b.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-thin-module-interface -o %t/m.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -emit-obj + + //--- a.cppm export module m:a; namespace n { diff --git a/clang/test/Modules/inherited_arg.cppm b/clang/test/Modules/inherited_arg.cppm index eb66b70cdce33..d638882e77980 100644 --- a/clang/test/Modules/inherited_arg.cppm +++ b/clang/test/Modules/inherited_arg.cppm @@ -7,6 +7,17 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/A-B.cppm -I%t -emit-thin-module-interface -o %t/A-B.pcm +// RUN: %clang_cc1 -std=c++20 %t/A-C.cppm -I%t -emit-thin-module-interface -o %t/A-C.pcm +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + + //--- foo.h template class pair {}; diff --git a/clang/test/Modules/instantiation-argdep-lookup.cppm b/clang/test/Modules/instantiation-argdep-lookup.cppm index fc9009a5bc13d..7d8ff9899cff0 100644 --- a/clang/test/Modules/instantiation-argdep-lookup.cppm +++ b/clang/test/Modules/instantiation-argdep-lookup.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only // +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// //--- foo.h namespace ns { diff --git a/clang/test/Modules/lambdas.cppm b/clang/test/Modules/lambdas.cppm index 7f00cf6f8682a..4d15b1c7c3993 100644 --- a/clang/test/Modules/lambdas.cppm +++ b/clang/test/Modules/lambdas.cppm @@ -11,6 +11,21 @@ // RUN: -o %t/lambdas2.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \ // RUN: -verify -DUSE_LAMBDA2 +// +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/lambdas.cppm -emit-thin-module-interface \ +// RUN: -o %t/lambdas.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \ +// RUN: -verify +// +// RUN: %clang_cc1 -std=c++20 %t/lambdas2.cppm -emit-thin-module-interface \ +// RUN: -o %t/lambdas2.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \ +// RUN: -verify -DUSE_LAMBDA2 //--- lambdas.h auto l1 = []() constexpr -> int { diff --git a/clang/test/Modules/merge-concepts-cxx-modules.cpp b/clang/test/Modules/merge-concepts-cxx-modules.cpp index 3d4f8435531a8..94a66a4bb0e9d 100644 --- a/clang/test/Modules/merge-concepts-cxx-modules.cpp +++ b/clang/test/Modules/merge-concepts-cxx-modules.cpp @@ -8,6 +8,18 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/conflicting.cppm -o %t/conflicting.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cppm -fsyntax-only -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/same_as.cppm -o %t/same_as.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/concepts.cppm -o %t/concepts.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/format.cppm -o %t/format.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/conflicting.cppm -o %t/conflicting.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cppm -fsyntax-only -verify + + //--- same_as.cppm export module same_as; export template diff --git a/clang/test/Modules/merge-constrained-friends.cpp b/clang/test/Modules/merge-constrained-friends.cpp index 8f0e9ed83cf29..ba482355f1c13 100644 --- a/clang/test/Modules/merge-constrained-friends.cpp +++ b/clang/test/Modules/merge-constrained-friends.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++23 %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++23 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++23 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++23 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + //--- A.cppm module; export module A; diff --git a/clang/test/Modules/merge-lambdas.cppm b/clang/test/Modules/merge-lambdas.cppm index a1d04ab4e234d..2225d50f4005f 100644 --- a/clang/test/Modules/merge-lambdas.cppm +++ b/clang/test/Modules/merge-lambdas.cppm @@ -6,6 +6,10 @@ // RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm // RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/B.pcm +// RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -fsyntax-only -verify + //--- lambda.h inline auto cmp = [](auto l, auto r) { return l < r; diff --git a/clang/test/Modules/merge-requires-with-lambdas.cppm b/clang/test/Modules/merge-requires-with-lambdas.cppm index 5767492047684..038b8e2f42d5d 100644 --- a/clang/test/Modules/merge-requires-with-lambdas.cppm +++ b/clang/test/Modules/merge-requires-with-lambdas.cppm @@ -17,6 +17,25 @@ // RUN: %clang_cc1 -std=c++20 %t/A3.cppm -emit-module-interface -o %t/A3.pcm // RUN: %clang_cc1 -std=c++20 %t/TestA3.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/A0.cppm -emit-thin-module-interface -o %t/A0.pcm +// RUN: %clang_cc1 -std=c++20 %t/TestA.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 %t/A1.cppm -emit-thin-module-interface -o %t/A1.pcm +// RUN: %clang_cc1 -std=c++20 %t/TestA1.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 %t/A2.cppm -emit-thin-module-interface -o %t/A2.pcm +// RUN: %clang_cc1 -std=c++20 %t/TestA2.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 %t/A3.cppm -emit-thin-module-interface -o %t/A3.pcm +// RUN: %clang_cc1 -std=c++20 %t/TestA3.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + + //--- A.h template concept A = requires(const _Tp& __t) { [](const __Up&) {}(__t); }; diff --git a/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm b/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm index a451bfe7804d3..8fd225c894ac9 100644 --- a/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm +++ b/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm @@ -7,6 +7,11 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fprebuilt-module-path=%t %t/reexport2.cppm -o %t/reexport2.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/use.cppm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/var_def.cppm -o %t/var_def.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/reexport1.cppm -o %t/reexport1.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/reexport2.cppm -o %t/reexport2.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/use.cppm -fsyntax-only -verify + //--- use.cppm import reexport1; import reexport2; diff --git a/clang/test/Modules/mismatch-diagnostics.cpp b/clang/test/Modules/mismatch-diagnostics.cpp index f8ce987cfba57..741ecf15680b0 100644 --- a/clang/test/Modules/mismatch-diagnostics.cpp +++ b/clang/test/Modules/mismatch-diagnostics.cpp @@ -13,6 +13,17 @@ // RUN: -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \ // RUN: %t/use.cpp 2>&1 | FileCheck %s +// Test again with thin BMI. +// RUN: %clang_cc1 -triple %itanium_abi_triple \ +// RUN: -std=c++20 -fprebuilt-module-path=%t/prebuilt-modules \ +// RUN: -emit-thin-module-interface -pthread -DBUILD_MODULE \ +// RUN: %t/mismatching_module.cppm -o \ +// RUN: %t/prebuilt_modules/mismatching_module.pcm +// +// RUN: not %clang_cc1 -triple %itanium_abi_triple -std=c++20 \ +// RUN: -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \ +// RUN: %t/use.cpp 2>&1 | FileCheck %s + //--- mismatching_module.cppm export module mismatching_module; diff --git a/clang/test/Modules/module-init-duplicated-import.cppm b/clang/test/Modules/module-init-duplicated-import.cppm index de0ce1962f100..5a5632699ed26 100644 --- a/clang/test/Modules/module-init-duplicated-import.cppm +++ b/clang/test/Modules/module-init-duplicated-import.cppm @@ -9,6 +9,17 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ // RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm +// Test again with thin BMI. +// Note that we can't use thin BMI here for m.cppm since it is required +// to generate the backend code. +// RUN: rm %t/a.pcm %t/m.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \ +// RUN: -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \ +// RUN: -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ +// RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm + //--- a.cppm export module a; export struct A { diff --git a/clang/test/Modules/named-modules-adl-2.cppm b/clang/test/Modules/named-modules-adl-2.cppm index 655acfcd93f69..e1e009199d398 100644 --- a/clang/test/Modules/named-modules-adl-2.cppm +++ b/clang/test/Modules/named-modules-adl-2.cppm @@ -6,6 +6,10 @@ // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-module-interface -o %t/b.pcm // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-thin-module-interface -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify + //--- a.cppm export module a; diff --git a/clang/test/Modules/named-modules-adl-3.cppm b/clang/test/Modules/named-modules-adl-3.cppm index 2fc2962c926b1..37119e3cc742f 100644 --- a/clang/test/Modules/named-modules-adl-3.cppm +++ b/clang/test/Modules/named-modules-adl-3.cppm @@ -14,6 +14,23 @@ // RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \ // RUN: -fmodule-file=b=%t/b.pcm -fsyntax-only -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-thin-module-interface \ +// RUN: -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm \ +// RUN: -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/b.cppm -fmodule-file=a=%t/a.pcm \ +// RUN: -emit-thin-module-interface -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \ +// RUN: -fmodule-file=b=%t/b.pcm -fsyntax-only -verify + //--- foo.h namespace n { diff --git a/clang/test/Modules/named-modules-adl.cppm b/clang/test/Modules/named-modules-adl.cppm index d5133ef367265..655a57374bef5 100644 --- a/clang/test/Modules/named-modules-adl.cppm +++ b/clang/test/Modules/named-modules-adl.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify + //--- a.h namespace n { diff --git a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm index e4d06415fabd4..b088288591bbe 100644 --- a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm +++ b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm @@ -9,6 +9,14 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - | FileCheck %t/B.cppm +// Test again with thin BMI. Note that we need to generate fat BMI for B.cppm +// since it is required to generate backend codes. +// RUN: rm %t/A.pcm %t/B.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.cppm -emit-module-interface -o %t/B.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - | FileCheck %t/B.cppm + //--- foo.h template diff --git a/clang/test/Modules/pair-unambiguous-ctor.cppm b/clang/test/Modules/pair-unambiguous-ctor.cppm index eb242244260cb..3d5269904042d 100644 --- a/clang/test/Modules/pair-unambiguous-ctor.cppm +++ b/clang/test/Modules/pair-unambiguous-ctor.cppm @@ -10,6 +10,15 @@ // RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-module-interface -o %t/std-algorithm.pcm // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify -o %t/Use.pcm +// Test again with thin BMI. +// RUN: rm -fr %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-thin-module-interface -o %t/std-string.pcm +// RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-thin-module-interface -o %t/std-algorithm.pcm +// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-thin-module-interface -verify -o %t/Use.pcm + //--- Use.cppm // expected-no-diagnostics module; diff --git a/clang/test/Modules/partial_specialization.cppm b/clang/test/Modules/partial_specialization.cppm index 3a01857172112..10e766a6bb834 100644 --- a/clang/test/Modules/partial_specialization.cppm +++ b/clang/test/Modules/partial_specialization.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/A.cppm -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/A.cppm -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify +// //--- foo.h template inline constexpr bool IsSame = false; diff --git a/clang/test/Modules/placement-new-reachable.cpp b/clang/test/Modules/placement-new-reachable.cpp index 29263173d78f4..c6f6e264acf45 100644 --- a/clang/test/Modules/placement-new-reachable.cpp +++ b/clang/test/Modules/placement-new-reachable.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + //--- placement.h namespace std { using size_t = decltype(sizeof(0)); diff --git a/clang/test/Modules/polluted-operator.cppm b/clang/test/Modules/polluted-operator.cppm index b24464aa6ad21..fa92a8fb1a684 100644 --- a/clang/test/Modules/polluted-operator.cppm +++ b/clang/test/Modules/polluted-operator.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/b.pcm -verify +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-thin-module-interface -o %t/b.pcm -verify + //--- foo.h namespace std diff --git a/clang/test/Modules/pr54457.cppm b/clang/test/Modules/pr54457.cppm index ed67ec1065376..8a195dbe49586 100644 --- a/clang/test/Modules/pr54457.cppm +++ b/clang/test/Modules/pr54457.cppm @@ -9,6 +9,9 @@ // RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-module-interface -o %t/C.pcm // RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o - +// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-thin-module-interface -o %t/C.pcm +// RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o - + //--- A.cppm // expected-no-diagnostics export module A; diff --git a/clang/test/Modules/pr56916.cppm b/clang/test/Modules/pr56916.cppm index a435b06d5cf15..98299af7c8941 100644 --- a/clang/test/Modules/pr56916.cppm +++ b/clang/test/Modules/pr56916.cppm @@ -8,6 +8,18 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/M-A.pcm +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/M-B.pcm +// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-thin-module-interface -o %t/M.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t -verify + + //--- foo.h template class Templ { diff --git a/clang/test/Modules/pr58532.cppm b/clang/test/Modules/pr58532.cppm index cf530b4ac2ccc..cc584914ef3ca 100644 --- a/clang/test/Modules/pr58532.cppm +++ b/clang/test/Modules/pr58532.cppm @@ -7,6 +7,12 @@ // RUN: %clang_cc1 -std=c++20 %t/implementation.cpp -fmodule-file=m=%t/m.pcm \ // RUN: -fsyntax-only -verify +// Test again with thin BMI. +// RUN: %clang_cc1 -std=c++20 %t/interface.cppm -emit-thin-module-interface \ +// RUN: -o %t/m.pcm +// RUN: %clang_cc1 -std=c++20 %t/implementation.cpp -fmodule-file=m=%t/m.pcm \ +// RUN: -fsyntax-only -verify + //--- invisible.h #pragma once // This breaks things. const int kInvisibleSymbol = 0; diff --git a/clang/test/Modules/pr58716.cppm b/clang/test/Modules/pr58716.cppm index 3f97fca7d5e8a..177802fe3afcb 100644 --- a/clang/test/Modules/pr58716.cppm +++ b/clang/test/Modules/pr58716.cppm @@ -8,7 +8,7 @@ // // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++20 -emit-module-interface %t/m.cppm -o %t/m.pcm // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++20 %t/m.pcm -S -emit-llvm -o - | FileCheck %t/m.cppm -// + //--- m.cppm module; #include "fail.h" diff --git a/clang/test/Modules/pr59719.cppm b/clang/test/Modules/pr59719.cppm index 5aea8992a0ca8..f1ef69dc04d24 100644 --- a/clang/test/Modules/pr59719.cppm +++ b/clang/test/Modules/pr59719.cppm @@ -7,6 +7,9 @@ // RUN: %clang_cc1 -std=c++20 %t/data.cppm -emit-module-interface -o %t/data.pcm // RUN: %clang_cc1 -std=c++20 %t/main.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/data.cppm -emit-thin-module-interface -o %t/data.pcm +// RUN: %clang_cc1 -std=c++20 %t/main.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + //--- foo.h namespace std { diff --git a/clang/test/Modules/pr59780.cppm b/clang/test/Modules/pr59780.cppm index d4bbd52c13f1a..211ed67fccf6a 100644 --- a/clang/test/Modules/pr59780.cppm +++ b/clang/test/Modules/pr59780.cppm @@ -9,6 +9,14 @@ // RUN: -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/use.cpp // RUN: %clang_cc1 -std=c++20 %t/a.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/a.cppm +// Test again with thin BMI. +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -triple %itanium_abi_triple -emit-module-interface \ +// RUN: -fthinBMI-output=%t/a.pcm -o %t/a.full.pcm +// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -S \ +// RUN: -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/use.cpp +// RUN: %clang_cc1 -std=c++20 %t/a.full.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/a.cppm + + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr59999.cppm b/clang/test/Modules/pr59999.cppm index 23710de9fe1c5..da59da4b7c140 100644 --- a/clang/test/Modules/pr59999.cppm +++ b/clang/test/Modules/pr59999.cppm @@ -11,6 +11,19 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.pcm \ // RUN: -fmodule-file=Module=%t/Module.pcm -S -emit-llvm -o - | FileCheck %t/Object.cppm +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Module.cppm \ +// RUN: -emit-thin-module-interface -o %t/Module.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.cppm \ +// RUN: -fmodule-file=Module=%t/Module.pcm -emit-module-interface -o %t/Object.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.pcm \ +// RUN: -fmodule-file=Module=%t/Module.pcm -S -emit-llvm -o - | FileCheck %t/Object.cppm + + //--- Module.cppm export module Module; diff --git a/clang/test/Modules/pr60036.cppm b/clang/test/Modules/pr60036.cppm index 297132cfde60b..02f6e4fb01cfd 100644 --- a/clang/test/Modules/pr60036.cppm +++ b/clang/test/Modules/pr60036.cppm @@ -24,6 +24,20 @@ // RUN: -fmodule-file=c=%t/c.pcm -fmodule-file=d=%t/d.pcm -fmodule-file=e=%t/e.pcm \ // RUN: -fmodule-file=f=%t/f.pcm -verify -fsyntax-only +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/c.pcm +// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/d.pcm +// RUN: %clang_cc1 -std=c++20 %t/e.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/e.pcm +// RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/f.pcm +// RUN: %clang_cc1 -std=c++20 %t/g.cppm -fprebuilt-module-path=%t -verify -fsyntax-only + + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr60085.cppm b/clang/test/Modules/pr60085.cppm index fba6012064047..abe7bab3073ed 100644 --- a/clang/test/Modules/pr60085.cppm +++ b/clang/test/Modules/pr60085.cppm @@ -27,6 +27,23 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.pcm \ // RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/a.cppm +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/d.cppm \ +// RUN: -emit-thin-module-interface -o %t/d.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cppm \ +// RUN: -emit-thin-module-interface -o %t/c.pcm -fmodule-file=%t/d.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \ +// RUN: -emit-thin-module-interface -o %t/b.pcm -fmodule-file=%t/d.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \ +// RUN: -emit-module-interface -o %t/a.pcm -fmodule-file=%t/d.pcm \ +// RUN: -fmodule-file=%t/c.pcm -fmodule-file=%t/b.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.pcm \ +// RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/a.cppm + //--- d.cppm export module d; diff --git a/clang/test/Modules/pr60275.cppm b/clang/test/Modules/pr60275.cppm index 57b31c6952bea..48a199782ec93 100644 --- a/clang/test/Modules/pr60275.cppm +++ b/clang/test/Modules/pr60275.cppm @@ -5,7 +5,12 @@ // RUN: split-file %s %t // // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-module-interface %t/a.cppm -o %t/a.pcm -// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp + +// Test again with thin BMI +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-thin-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp + //--- foo.h consteval void global() {} diff --git a/clang/test/Modules/pr60486.cppm b/clang/test/Modules/pr60486.cppm index 13802a4917e6e..13d37771f2ce8 100644 --- a/clang/test/Modules/pr60486.cppm +++ b/clang/test/Modules/pr60486.cppm @@ -7,6 +7,9 @@ // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 -fmodule-file=a=%t/a.pcm %t/b.cppm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -fmodule-file=a=%t/a.pcm %t/b.cppm -fsyntax-only -verify + //--- foo.h template struct s { diff --git a/clang/test/Modules/pr60693.cppm b/clang/test/Modules/pr60693.cppm index c50791083a5be..08e3e4ab39ec3 100644 --- a/clang/test/Modules/pr60693.cppm +++ b/clang/test/Modules/pr60693.cppm @@ -7,6 +7,10 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-module-interface -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp +// Test again with thin BMI +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr60775.cppm b/clang/test/Modules/pr60775.cppm index 4db027ba3600a..2830b80a21011 100644 --- a/clang/test/Modules/pr60775.cppm +++ b/clang/test/Modules/pr60775.cppm @@ -12,6 +12,19 @@ // RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-module-interface -fmodule-file=c=%t/c.pcm -o %t/f.pcm // RUN: %clang_cc1 -std=c++20 %t/g.cpp -fmodule-file=f=%t/f.pcm -fmodule-file=c=%t/c.pcm -verify -fsyntax-only +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -I%t -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fmodule-file=a=%t/a.pcm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -I%t -emit-thin-module-interface -o %t/c.pcm +// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-thin-module-interface -fmodule-file=c=%t/c.pcm -o %t/d.pcm +// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fmodule-file=d=%t/d.pcm -fmodule-file=c=%t/c.pcm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-thin-module-interface -fmodule-file=c=%t/c.pcm -o %t/f.pcm +// RUN: %clang_cc1 -std=c++20 %t/g.cpp -fmodule-file=f=%t/f.pcm -fmodule-file=c=%t/c.pcm -verify -fsyntax-only + //--- initializer_list.h namespace std { typedef decltype(sizeof(int)) size_t; diff --git a/clang/test/Modules/pr60890.cppm b/clang/test/Modules/pr60890.cppm index 2560bec5b4335..9d3381e4de000 100644 --- a/clang/test/Modules/pr60890.cppm +++ b/clang/test/Modules/pr60890.cppm @@ -9,6 +9,12 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/c.cppm -fprebuilt-module-path=%t -o %t/c.pcm // RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -S -emit-llvm -o - +// Test again with thin BMI +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/b.cppm -fprebuilt-module-path=%t -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/c.cppm -fprebuilt-module-path=%t -o %t/c.pcm +// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -S -emit-llvm -o - + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr61065.cppm b/clang/test/Modules/pr61065.cppm index cf6fcdda78cd4..3437aaa33f4a6 100644 --- a/clang/test/Modules/pr61065.cppm +++ b/clang/test/Modules/pr61065.cppm @@ -10,6 +10,19 @@ // DISABLED: -fprebuilt-module-path=%t // DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fprebuilt-module-path=%t +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/b.pcm \ +// RUN: -fprebuilt-module-path=%t +// DISABLED: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface -o %t/c.pcm \ +// DISABLED: -fprebuilt-module-path=%t +// DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fprebuilt-module-path=%t + + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr61065_2.cppm b/clang/test/Modules/pr61065_2.cppm index 10cc1a06b7e45..9a815f8edf3e0 100644 --- a/clang/test/Modules/pr61065_2.cppm +++ b/clang/test/Modules/pr61065_2.cppm @@ -11,6 +11,21 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/b.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface -o %t/c.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-thin-module-interface -o %t/d.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t + + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr61067.cppm b/clang/test/Modules/pr61067.cppm index 8469a1db1f1c8..9842b0a4f15f3 100644 --- a/clang/test/Modules/pr61067.cppm +++ b/clang/test/Modules/pr61067.cppm @@ -12,6 +12,20 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \ // RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \ +// RUN: -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \ +// RUN: -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.pcm -S \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %t/b.cppm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \ +// RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp + //--- a.cppm export module a; diff --git a/clang/test/Modules/pr61317.cppm b/clang/test/Modules/pr61317.cppm index 4b54d26dc5a63..7b7ec80a6b953 100644 --- a/clang/test/Modules/pr61317.cppm +++ b/clang/test/Modules/pr61317.cppm @@ -8,6 +8,15 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/B.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + //--- foo.h #ifndef _FOO #define _FOO diff --git a/clang/test/Modules/pr61783.cppm b/clang/test/Modules/pr61783.cppm index 9cf773b0b282b..4555787f59173 100644 --- a/clang/test/Modules/pr61783.cppm +++ b/clang/test/Modules/pr61783.cppm @@ -9,6 +9,14 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/user.cpp -fmodule-file=mod=%t/mod.pcm \ // RUN: -S -emit-llvm -o - | FileCheck %t/user.cpp +// Test again with thin BMI +// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/mod.cppm -emit-thin-module-interface \ +// RUN: -o %t/mod.pcm +// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/mod.pcm -S -emit-llvm -o - | \ +// RUN: FileCheck %t/mod.cppm +// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/user.cpp -fmodule-file=mod=%t/mod.pcm \ +// RUN: -S -emit-llvm -o - | FileCheck %t/user.cpp + //--- mod.cppm module; diff --git a/clang/test/Modules/pr61892.cppm b/clang/test/Modules/pr61892.cppm index 99d02f36b2b54..99722543366a6 100644 --- a/clang/test/Modules/pr61892.cppm +++ b/clang/test/Modules/pr61892.cppm @@ -2,11 +2,25 @@ // RUN: mkdir -p %t // RUN: split-file %s %t // +// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ +// RUNX: -emit-module-interface %t/a.cppm -o %t/a.pcm +// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ +// RUNX: %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \ +// RUNX: -emit-llvm -o - | FileCheck %t/b.cpp +// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ +// RUNX: %t/c.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \ +// RUNX: -emit-llvm -o - | FileCheck %t/c.cpp + +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ -// RUN: -emit-module-interface %t/a.cppm -o %t/a.pcm -// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ -// RUN: %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \ -// RUN: -emit-llvm -o - | FileCheck %t/b.cpp +// RUN: -emit-thin-module-interface %t/a.cppm -o %t/a.pcm +// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ +// RUNX: %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \ +// RUNX: -emit-llvm -o - | FileCheck %t/b.cpp // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \ // RUN: %t/c.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \ // RUN: -emit-llvm -o - | FileCheck %t/c.cpp @@ -23,20 +37,10 @@ struct integer { export template int a = static_cast(integer()); -struct s { - ~s(); - operator int() const; -}; - -export template -auto d = s(); - int aa() { - return a + d; + return a; } -int dynamic_func(); -export inline int dynamic_var = dynamic_func(); //--- b.cpp import a; @@ -53,13 +57,9 @@ void b() {} //--- c.cpp import a; int c() { - return a + d + dynamic_var; + return a; } // The used variables are generated normally // CHECK-DAG: @_ZW1a1aIvE = -// CHECK-DAG: @_ZW1a1dIvE = -// CHECK-DAG: @_ZW1a11dynamic_var = linkonce_odr // CHECK-DAG: @_ZGVW1a1aIvE = -// CHECk-DAG: @_ZGVW1a1dIvE = -// CHECK-DAG: @_ZGVW1a11dynamic_var = linkonce_odr diff --git a/clang/test/Modules/pr62158.cppm b/clang/test/Modules/pr62158.cppm index 7a0761df77158..54acd8622dc94 100644 --- a/clang/test/Modules/pr62158.cppm +++ b/clang/test/Modules/pr62158.cppm @@ -6,6 +6,15 @@ // RUN: %clang_cc1 -std=c++20 %t/main.cpp -fmodule-file=lib=%t/lib.pcm \ // RUN: -verify -fsyntax-only +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/lib.cppm -o %t/lib.pcm +// RUN: %clang_cc1 -std=c++20 %t/main.cpp -fmodule-file=lib=%t/lib.pcm \ +// RUN: -verify -fsyntax-only + //--- header.h namespace lib::inline __1 { template diff --git a/clang/test/Modules/pr62359.cppm b/clang/test/Modules/pr62359.cppm index 4632457e57f18..82f7901829095 100644 --- a/clang/test/Modules/pr62359.cppm +++ b/clang/test/Modules/pr62359.cppm @@ -12,6 +12,22 @@ // RUN: %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify // RUN: %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/Hello.cppm -o %t/Hello.pcm +// RUN: not %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only \ +// RUN: 2>&1 | FileCheck %t/use.cpp +// RUN: not %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only \ +// RUN: 2>&1 | FileCheck %t/use2.cpp +// +// RUN: %clang_cc1 -std=c++20 -fopenmp -emit-thin-module-interface %t/Hello.cppm -o %t/Hello.pcm +// RUN: %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify + + //--- Hello.cppm export module hello; export void hello() { diff --git a/clang/test/Modules/pr62589.cppm b/clang/test/Modules/pr62589.cppm index 4164c3405ac0e..98296575188fb 100644 --- a/clang/test/Modules/pr62589.cppm +++ b/clang/test/Modules/pr62589.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++23 -emit-module-interface %t/a.cppm -o %t/a.pcm // RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++23 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify + //--- foo.h class TypeA {}; diff --git a/clang/test/Modules/pr62705.cppm b/clang/test/Modules/pr62705.cppm index a09bdf2563e84..587d5bc3942f2 100644 --- a/clang/test/Modules/pr62705.cppm +++ b/clang/test/Modules/pr62705.cppm @@ -10,6 +10,14 @@ // RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \ // RUN: -emit-llvm -o - | FileCheck %t/b.cppm +// RUN: %clang_cc1 %t/a.cppm -std=c++20 -triple %itanium_abi_triple \ +// RUN: -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 %t/b.cppm -std=c++20 -triple %itanium_abi_triple \ +// RUN: -emit-module-interface -o %t/b.pcm \ +// RUN: -fmodule-file=a=%t/a.pcm +// RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \ +// RUN: -emit-llvm -o - | FileCheck %t/b.cppm + //--- foo.h namespace n { diff --git a/clang/test/Modules/pr62796.cppm b/clang/test/Modules/pr62796.cppm index f96e54bc6aded..0efd558c97c1e 100644 --- a/clang/test/Modules/pr62796.cppm +++ b/clang/test/Modules/pr62796.cppm @@ -6,6 +6,10 @@ // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=Fibonacci.Cache=%t/Cache.pcm \ // RUN: -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/Cache.cppm -o %t/Cache.pcm +// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=Fibonacci.Cache=%t/Cache.pcm \ +// RUN: -fsyntax-only -verify + //--- Cache.cppm export module Fibonacci.Cache; diff --git a/clang/test/Modules/pr62943.cppm b/clang/test/Modules/pr62943.cppm index 27868b78220f5..6da25d1e6a066 100644 --- a/clang/test/Modules/pr62943.cppm +++ b/clang/test/Modules/pr62943.cppm @@ -9,6 +9,18 @@ // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \ // RUN: -fsyntax-only -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface \ +// RUN: -fprebuilt-module-path=%t -o %t/c.pcm +// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \ +// RUN: -fsyntax-only -verify + //--- foo.h #ifndef FOO_H #define FOO_H diff --git a/clang/test/Modules/pr63544.cppm b/clang/test/Modules/pr63544.cppm index 16224cfd01094..16b9cd9580d04 100644 --- a/clang/test/Modules/pr63544.cppm +++ b/clang/test/Modules/pr63544.cppm @@ -8,6 +8,18 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++23 %t/pr63544.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++23 %t/a.cppm -emit-thin-module-interface -o %t/m-a.pcm +// RUN: %clang_cc1 -std=c++23 %t/b.cppm -emit-thin-module-interface -o %t/m-b.pcm +// RUN: %clang_cc1 -std=c++23 %t/m.cppm -emit-thin-module-interface -o %t/m.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++23 %t/pr63544.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + + //--- foo.h namespace std { diff --git a/clang/test/Modules/pr63595.cppm b/clang/test/Modules/pr63595.cppm index 13a5f84a3e71f..604553ab2ad16 100644 --- a/clang/test/Modules/pr63595.cppm +++ b/clang/test/Modules/pr63595.cppm @@ -6,6 +6,16 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/module2.cppm -o %t/module2.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -I%t %t/module1.cppm -o %t/module1.pcm +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -I%t %t/module2.cppm -o %t/module2.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only + + //--- header.h namespace NS { template diff --git a/clang/test/Modules/pr67627.cppm b/clang/test/Modules/pr67627.cppm index 3d4410229080a..c59ca8ed90331 100644 --- a/clang/test/Modules/pr67627.cppm +++ b/clang/test/Modules/pr67627.cppm @@ -5,6 +5,10 @@ // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -fsyntax-only -verify +// RUN: rm %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -fsyntax-only -verify + //--- A.cppm export module A; diff --git a/clang/test/Modules/pr67893.cppm b/clang/test/Modules/pr67893.cppm index 7d4e4c1dc5d84..1ecf367a3217b 100644 --- a/clang/test/Modules/pr67893.cppm +++ b/clang/test/Modules/pr67893.cppm @@ -9,6 +9,18 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ // RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \ +// RUN: -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \ +// RUN: -emit-thin-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ +// RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm + //--- a.cppm export module a; export struct A { diff --git a/clang/test/Modules/predefined.cpp b/clang/test/Modules/predefined.cpp index fbe0c4e23ca59..5d755adff76aa 100644 --- a/clang/test/Modules/predefined.cpp +++ b/clang/test/Modules/predefined.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -x c++ -std=c++20 -emit-module-interface a.h -o a.pcm -fms-extensions -verify // RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify +// RUN: %clang_cc1 -x c++ -std=c++20 -emit-thin-module-interface a.h -o a.pcm -fms-extensions -verify +// RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify + //--- a.h // expected-no-diagnostics diff --git a/clang/test/Modules/preferred_name.cppm b/clang/test/Modules/preferred_name.cppm index 46ad96cb1abc3..734c0d0b15b4c 100644 --- a/clang/test/Modules/preferred_name.cppm +++ b/clang/test/Modules/preferred_name.cppm @@ -8,6 +8,16 @@ // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only + +// Test again with thin BMI. +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only // //--- foo.h template diff --git a/clang/test/Modules/redefinition-merges.cppm b/clang/test/Modules/redefinition-merges.cppm index 9ab4006f985fa..71f49c31689dd 100644 --- a/clang/test/Modules/redefinition-merges.cppm +++ b/clang/test/Modules/redefinition-merges.cppm @@ -12,6 +12,12 @@ // RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-module-interface -o %t/M.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only + +// / Test again with thin BMI. +// RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-thin-module-interface -o %t/M.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only + // //--- foo.h #ifndef FOO diff --git a/clang/test/Modules/redundant-template-default-arg.cpp b/clang/test/Modules/redundant-template-default-arg.cpp index 6807b45e51395..2ed47336ebc81 100644 --- a/clang/test/Modules/redundant-template-default-arg.cpp +++ b/clang/test/Modules/redundant-template-default-arg.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm // RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-thin-module-interface -o %t/foo.pcm +// RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t -fsyntax-only -verify + //--- foo.h template T u; diff --git a/clang/test/Modules/redundant-template-default-arg2.cpp b/clang/test/Modules/redundant-template-default-arg2.cpp index 41deb112cfa6e..7ceece1ac9775 100644 --- a/clang/test/Modules/redundant-template-default-arg2.cpp +++ b/clang/test/Modules/redundant-template-default-arg2.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm // RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-thin-module-interface -o %t/foo.pcm +// RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -fsyntax-only -verify + //--- foo.cppm export module foo; export template diff --git a/clang/test/Modules/redundant-template-default-arg3.cpp b/clang/test/Modules/redundant-template-default-arg3.cpp index 8bb222ac91ffc..71414e526d2c8 100644 --- a/clang/test/Modules/redundant-template-default-arg3.cpp +++ b/clang/test/Modules/redundant-template-default-arg3.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm // RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t/. -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-thin-module-interface -o %t/foo.pcm +// RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t/. -fsyntax-only -verify + //--- foo.h template T v; diff --git a/clang/test/Modules/search-partitions.cpp b/clang/test/Modules/search-partitions.cpp index 571160def7e9b..8b69e5b0a9ae9 100644 --- a/clang/test/Modules/search-partitions.cpp +++ b/clang/test/Modules/search-partitions.cpp @@ -14,6 +14,22 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/moduleA.cpp \ // RUN: -fprebuilt-module-path=%t +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/partition1.cpp \ +// RUN: -o %t/A-Part1.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/partition2.cpp \ +// RUN: -o %t/A-Part2.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/partition3.cpp \ +// RUN: -o %t/A-Part3.pcm + +// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/moduleA.cpp -fprebuilt-module-path=%t + // expected-no-diagnostics //--- partition1.cpp diff --git a/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm b/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm index e32da39d9df1a..658c73cc78e84 100644 --- a/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm +++ b/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm @@ -12,6 +12,18 @@ // RUN: -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fprebuilt-module-path=%t +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/base.cppm -emit-thin-module-interface -o %t/package-base.pcm +// RUN: %clang_cc1 -std=c++20 %t/child.cppm -emit-thin-module-interface -o %t/package-child.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/package.cppm -emit-thin-module-interface -o %t/package.pcm \ +// RUN: -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fprebuilt-module-path=%t + //--- base.cppm export module package:base; diff --git a/clang/test/Modules/template-function-specialization.cpp b/clang/test/Modules/template-function-specialization.cpp index 3eac92e7edb94..204c8bad5e454 100644 --- a/clang/test/Modules/template-function-specialization.cpp +++ b/clang/test/Modules/template-function-specialization.cpp @@ -4,7 +4,10 @@ // // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/foo.cppm -o %t/foo.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only -// + +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/foo.cppm -o %t/foo.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only + //--- foo.cppm module; # 3 __FILE__ 1 // use the next physical line number here (and below) diff --git a/clang/test/Modules/template-lambdas.cppm b/clang/test/Modules/template-lambdas.cppm index 69117a1a04fc7..4f223e4567741 100644 --- a/clang/test/Modules/template-lambdas.cppm +++ b/clang/test/Modules/template-lambdas.cppm @@ -12,6 +12,21 @@ // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \ // RUN: -verify -DUSE_LAMBDA2 +// Test again with thin BMI +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/template_lambdas.cppm -emit-thin-module-interface \ +// RUN: -o %t/lambdas.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \ +// RUN: -verify +// +// RUN: %clang_cc1 -std=c++20 %t/template_lambdas2.cppm -emit-thin-module-interface \ +// RUN: -o %t/lambdas2.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \ +// RUN: -verify -DUSE_LAMBDA2 + //--- lambdas.h auto l1 = []() constexpr -> int { return I; diff --git a/clang/test/Modules/template-pack.cppm b/clang/test/Modules/template-pack.cppm index eca17f31f015e..e46901a9ee405 100644 --- a/clang/test/Modules/template-pack.cppm +++ b/clang/test/Modules/template-pack.cppm @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -fsyntax-only -verify + //--- foo.h namespace std diff --git a/clang/test/Modules/template_default_argument.cpp b/clang/test/Modules/template_default_argument.cpp index 5a7d1c04cf181..00af7ca9687c6 100644 --- a/clang/test/Modules/template_default_argument.cpp +++ b/clang/test/Modules/template_default_argument.cpp @@ -4,6 +4,9 @@ // // RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify + +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/B.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify // //--- templ.h template diff --git a/clang/unittests/Sema/SemaNoloadLookupTest.cpp b/clang/unittests/Sema/SemaNoloadLookupTest.cpp index b24c72cba407f..aa259cda4a84c 100644 --- a/clang/unittests/Sema/SemaNoloadLookupTest.cpp +++ b/clang/unittests/Sema/SemaNoloadLookupTest.cpp @@ -64,7 +64,7 @@ class NoloadLookupTest : public ::testing::Test { CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); std::string CacheBMIPath = - llvm::Twine(TestDir + "/" + ModuleName + " .pcm").str(); + llvm::Twine(TestDir + "/" + ModuleName + ".pcm").str(); std::string PrebuiltModulePath = "-fprebuilt-module-path=" + TestDir.str().str(); const char *Args[] = {"clang++", @@ -75,9 +75,7 @@ class NoloadLookupTest : public ::testing::Test { TestDir.c_str(), "-I", TestDir.c_str(), - FileName.c_str(), - "-o", - CacheBMIPath.c_str()}; + FileName.c_str()}; std::shared_ptr Invocation = createInvocation(Args, CIOpts); EXPECT_TRUE(Invocation); @@ -85,7 +83,8 @@ class NoloadLookupTest : public ::testing::Test { CompilerInstance Instance; Instance.setDiagnostics(Diags.get()); Instance.setInvocation(Invocation); - GenerateModuleInterfaceAction Action; + Instance.getFrontendOpts().OutputFile = CacheBMIPath; + GenerateThinModuleInterfaceAction Action; EXPECT_TRUE(Instance.ExecuteAction(Action)); EXPECT_FALSE(Diags->hasErrorOccurred()); diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp index ed0daa43436eb..15a0aa78d2169 100644 --- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp +++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp @@ -69,9 +69,9 @@ export int aa = 43; CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); - const char *Args[] = { - "clang++", "-std=c++20", "--precompile", "-working-directory", - TestDir.c_str(), "a.cppm", "-o", BMIPath.c_str()}; + const char *Args[] = {"clang++", "-std=c++20", + "--precompile", "-working-directory", + TestDir.c_str(), "a.cppm"}; std::shared_ptr Invocation = createInvocation(Args, CIOpts); EXPECT_TRUE(Invocation); @@ -88,6 +88,8 @@ export int aa = 43; Instance.setDiagnostics(Diags.get()); Instance.setInvocation(Invocation); + Instance.getFrontendOpts().OutputFile = BMIPath; + if (auto VFSWithRemapping = createVFSFromCompilerInvocation( Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS)) CIOpts.VFS = VFSWithRemapping; @@ -95,7 +97,7 @@ export int aa = 43; Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true; - GenerateModuleInterfaceAction Action; + GenerateThinModuleInterfaceAction Action; EXPECT_TRUE(Instance.ExecuteAction(Action)); EXPECT_FALSE(Diags->hasErrorOccurred()); } diff --git a/clang/unittests/Serialization/NoCommentsTest.cpp b/clang/unittests/Serialization/NoCommentsTest.cpp index 2632a6337807a..6a5b9251303d3 100644 --- a/clang/unittests/Serialization/NoCommentsTest.cpp +++ b/clang/unittests/Serialization/NoCommentsTest.cpp @@ -90,9 +90,9 @@ void foo() {} CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); std::string CacheBMIPath = llvm::Twine(TestDir + "/Comments.pcm").str(); - const char *Args[] = { - "clang++", "-std=c++20", "--precompile", "-working-directory", - TestDir.c_str(), "Comments.cppm", "-o", CacheBMIPath.c_str()}; + const char *Args[] = {"clang++", "-std=c++20", + "--precompile", "-working-directory", + TestDir.c_str(), "Comments.cppm"}; std::shared_ptr Invocation = createInvocation(Args, CIOpts); ASSERT_TRUE(Invocation); @@ -100,7 +100,8 @@ void foo() {} CompilerInstance Instance; Instance.setDiagnostics(Diags.get()); Instance.setInvocation(Invocation); - GenerateModuleInterfaceAction Action; + Instance.getFrontendOpts().OutputFile = CacheBMIPath; + GenerateThinModuleInterfaceAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); ASSERT_FALSE(Diags->hasErrorOccurred()); diff --git a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp index 86ae929e7f17e..a6db2b0ac9068 100644 --- a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp +++ b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp @@ -96,10 +96,9 @@ export namespace Fibonacci CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); - std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str(); - const char *Args[] = { - "clang++", "-std=c++20", "--precompile", "-working-directory", - TestDir.c_str(), "Cached.cppm", "-o", CacheBMIPath.c_str()}; + const char *Args[] = {"clang++", "-std=c++20", + "--precompile", "-working-directory", + TestDir.c_str(), "Cached.cppm"}; std::shared_ptr Invocation = createInvocation(Args, CIOpts); ASSERT_TRUE(Invocation); @@ -107,7 +106,11 @@ export namespace Fibonacci CompilerInstance Instance; Instance.setDiagnostics(Diags.get()); Instance.setInvocation(Invocation); - GenerateModuleInterfaceAction Action; + + std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str(); + Instance.getFrontendOpts().OutputFile = CacheBMIPath; + + GenerateThinModuleInterfaceAction Action; ASSERT_TRUE(Instance.ExecuteAction(Action)); ASSERT_FALSE(Diags->hasErrorOccurred()); From 387f312012ed04cb579e04c1f729e9cdaa0e4d1f Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Wed, 8 Nov 2023 10:51:55 +0800 Subject: [PATCH 2/3] fmt --- clang/lib/Serialization/ASTWriterDecl.cpp | 2 +- clang/lib/Serialization/GeneratePCH.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 00a04ee2fa730..ca7794b8c5f97 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -283,7 +283,7 @@ bool clang::MayDefAffectABI(const Decl *D) { // use, no matter whether they've been explicitly instantiated etc. if (!FD->isUserProvided()) return true; - + if (FD->isDependentContext()) return true; diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index a51047a148c93..4bceb986a1e58 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -82,10 +82,11 @@ ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { return &Writer; } -ThinBMIGenerator::ThinBMIGenerator( - const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, std::shared_ptr Buffer, - bool IncludeTimestamps) +ThinBMIGenerator::ThinBMIGenerator(const Preprocessor &PP, + InMemoryModuleCache &ModuleCache, + StringRef OutputFile, + std::shared_ptr Buffer, + bool IncludeTimestamps) : PCHGenerator( PP, ModuleCache, OutputFile, llvm::StringRef(), Buffer, /*Extensions=*/ArrayRef>(), From 561b8a1ac2a94761a9bf190c6ad2b8785ce9e072 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Thu, 2 Nov 2023 18:36:57 +0800 Subject: [PATCH 3/3] [C++20] [Modules] Introduce Decls Hash in BMI --- clang/include/clang/AST/ODRHash.h | 3 + clang/include/clang/Driver/Options.td | 3 + .../include/clang/Frontend/FrontendActions.h | 34 +- .../include/clang/Frontend/FrontendOptions.h | 3 + .../include/clang/Serialization/ASTBitCodes.h | 3 + clang/include/clang/Serialization/ASTReader.h | 10 + clang/include/clang/Serialization/ASTWriter.h | 5 + clang/lib/AST/ODRHash.cpp | 2 + clang/lib/Driver/Driver.cpp | 7 +- clang/lib/Driver/ToolChains/Clang.cpp | 5 +- clang/lib/Frontend/CompilerInvocation.cpp | 2 + clang/lib/Frontend/FrontendActions.cpp | 49 +- .../ExecuteCompilerInvocation.cpp | 2 + clang/lib/Serialization/ASTReader.cpp | 75 ++ clang/lib/Serialization/ASTWriter.cpp | 10 + clang/lib/Serialization/ASTWriterDecl.cpp | 121 +++ clang/test/Modules/cxx20-module-file-info.cpp | 3 + .../decls-hash-get-bmi-decls-hash.cppm | 35 + .../Modules/decls-hash-module-file-info.cppm | 35 + .../Serialization/BMIDeclsHashTest.cpp | 952 ++++++++++++++++++ clang/unittests/Serialization/CMakeLists.txt | 1 + 21 files changed, 1340 insertions(+), 20 deletions(-) create mode 100644 clang/test/Modules/decls-hash-get-bmi-decls-hash.cppm create mode 100644 clang/test/Modules/decls-hash-module-file-info.cppm create mode 100644 clang/unittests/Serialization/BMIDeclsHashTest.cpp diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index cedf644520fc3..5f5d8f99402ed 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -101,6 +101,9 @@ class ODRHash { // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); + // Add intergeers to ID. + void AddInteger(unsigned value); + static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent); private: diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 12785f280183e..1294b3ae1be29 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5093,6 +5093,9 @@ def muclibc : Flag<["-"], "muclibc">, Group, Flags<[HelpHidden]>; def module_file_info : Flag<["-"], "module-file-info">, Flags<[]>, Visibility<[ClangOption, CC1Option]>, Group, HelpText<"Provide information about a particular module file">; +def get_bmi_decls_hash : Flag<["-"], "get-bmi-decls-hash">, Flags<[]>, + Visibility<[ClangOption, CC1Option]>, Group, + HelpText<"Get the BMI Decls hash value for a particular module file">; def mthumb : Flag<["-"], "mthumb">, Group; def mtune_EQ : Joined<["-"], "mtune=">, Group, HelpText<"Only supported on AArch64, PowerPC, RISC-V, SystemZ, and X86">; diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index c419deb80034f..d4ff4f8f6c57d 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -190,9 +190,8 @@ class SyntaxOnlyAction : public ASTFrontendAction { bool hasCodeCompletionSupport() const override { return true; } }; -/// Dump information about the given module file, to be used for -/// basic debugging and discovery. -class DumpModuleInfoAction : public ASTFrontendAction { +// Base action for dumping module informations. +class DumpModuleInfoActionBase : public ASTFrontendAction { // Allow other tools (ex lldb) to direct output for their use. std::shared_ptr OutputStream; @@ -200,11 +199,12 @@ class DumpModuleInfoAction : public ASTFrontendAction { std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; bool BeginInvocation(CompilerInstance &CI) override; - void ExecuteAction() override; + // Setup the output file. + llvm::raw_ostream &getOutputStream(); public: - DumpModuleInfoAction() = default; - explicit DumpModuleInfoAction(std::shared_ptr Out) + DumpModuleInfoActionBase() = default; + explicit DumpModuleInfoActionBase(std::shared_ptr Out) : OutputStream(Out) {} bool hasPCHSupport() const override { return false; } bool hasASTFileSupport() const override { return true; } @@ -212,6 +212,28 @@ class DumpModuleInfoAction : public ASTFrontendAction { bool hasCodeCompletionSupport() const override { return false; } }; +/// Dump information about the given module file, to be used for +/// basic debugging and discovery. +class DumpModuleInfoAction : public DumpModuleInfoActionBase { + void ExecuteAction() override; + +public: + DumpModuleInfoAction() = default; + explicit DumpModuleInfoAction(std::shared_ptr Out) + : DumpModuleInfoActionBase(Out) {} +}; + +/// Get the modules decl hash value action. The information is contained by +/// DumpModuleInfoAction too. But this should be much faster. +class GetModuleDeclsHashAction : public DumpModuleInfoActionBase { + void ExecuteAction() override; + +public: + GetModuleDeclsHashAction() = default; + explicit GetModuleDeclsHashAction(std::shared_ptr Out) + : DumpModuleInfoActionBase(Out) {} +}; + class VerifyPCHAction : public ASTFrontendAction { protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 719d4ca813361..a4a23f3ca03f5 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -107,6 +107,9 @@ enum ActionKind { /// Dump information about a module file. ModuleFileInfo, + /// Get BMI Decls Hash about a module file. + GetBMIDeclsHash, + /// Load and verify that a PCH file is usable. VerifyPCH, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 5c32fbc079c9a..72a93bbb2ebd8 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -695,6 +695,9 @@ enum ASTRecordTypes { /// Record code for an unterminated \#pragma clang assume_nonnull begin /// recorded in a preamble. PP_ASSUME_NONNULL_LOC = 67, + + /// Record code for the decls hash in the thin BMI. + BMI_DECLS_HASH = 68, }; /// Record types used within a source manager block. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 7eefdca6815cd..a46ed6a95aae9 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -937,6 +937,9 @@ class ASTReader /// Sema tracks these to emit deferred diags. llvm::SmallSetVector DeclsToCheckForDeferredDiags; + /// The hash value of read C++20 thin BMI. + std::optional ReadedBMIDeclsHash; + private: struct ImportedSubmodule { serialization::SubmoduleID ID; @@ -1794,6 +1797,13 @@ class ASTReader StringRef ExistingModuleCachePath, bool RequireStrictOptionMatches = false); + static std::optional getBMIHash(StringRef Filename, + FileManager &FileMgr); + + std::optional getReadedBMIDeclsHash() const { + return ReadedBMIDeclsHash; + } + /// Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines /// build prior to including the precompiled header. diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 3ccb35aa72f9b..5dfeaf9d6c62b 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -170,6 +170,11 @@ class ASTWriter : public ASTDeserializationListener, /// named modules. bool GeneratingThinBMI = false; + /// The hash for recorded decls for C++20 named modules. The parts of decls + /// which not affecting the ABI may not be recorded. e.g., + /// the function body of a non-inline function. + llvm::hash_code BMIDeclsHash = 0; + /// Mapping from input file entries to the index into the /// offset table where information about that input file is stored. llvm::DenseMap InputFileIDs; diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index aea1a93ae1fa8..ace24eb4d29d8 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -1249,3 +1249,5 @@ void ODRHash::AddQualType(QualType T) { void ODRHash::AddBoolean(bool Value) { Bools.push_back(Value); } + +void ODRHash::AddInteger(unsigned Value) { ID.AddInteger(Value); } diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 76def412d1255..42bd241f1ff70 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -354,6 +354,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || + (PhaseArg = DAL.getLastArg(options::OPT_get_bmi_decls_hash)) || (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) || (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || @@ -4736,7 +4737,8 @@ Action *Driver::ConstructPhaseAction( return C.MakeAction(Input, types::TY_Remap); if (Args.hasArg(options::OPT_emit_ast)) return C.MakeAction(Input, types::TY_AST); - if (Args.hasArg(options::OPT_module_file_info)) + if (Args.hasArg(options::OPT_module_file_info) || + Args.hasArg(options::OPT_get_bmi_decls_hash)) return C.MakeAction(Input, types::TY_ModuleFile); if (Args.hasArg(options::OPT_verify_pch)) return C.MakeAction(Input, types::TY_Nothing); @@ -5818,7 +5820,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, } if (JA.getType() == types::TY_ModuleFile && - C.getArgs().getLastArg(options::OPT_module_file_info)) { + (C.getArgs().getLastArg(options::OPT_module_file_info) || + C.getArgs().getLastArg(options::OPT_get_bmi_decls_hash))) { return "-"; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5bb945be78dcb..c091a94ea0d78 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4960,7 +4960,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (JA.getType() == types::TY_AST) { CmdArgs.push_back("-emit-pch"); } else if (JA.getType() == types::TY_ModuleFile) { - CmdArgs.push_back("-module-file-info"); + if (Args.hasArg(options::OPT_get_bmi_decls_hash)) + CmdArgs.push_back("-get-bmi-decls-hash"); + else + CmdArgs.push_back("-module-file-info"); } else if (JA.getType() == types::TY_RewrittenObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_NonFragile; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index b6245d0dddb10..177b40a985789 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2561,6 +2561,7 @@ static const auto &getFrontendActionTable() { {frontend::InitOnly, OPT_init_only}, {frontend::ParseSyntaxOnly, OPT_fsyntax_only}, {frontend::ModuleFileInfo, OPT_module_file_info}, + {frontend::GetBMIDeclsHash, OPT_get_bmi_decls_hash}, {frontend::VerifyPCH, OPT_verify_pch}, {frontend::PrintPreamble, OPT_print_preamble}, {frontend::PrintPreprocessedInput, OPT_E}, @@ -4243,6 +4244,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::GenerateInterfaceStubs: case frontend::ParseSyntaxOnly: case frontend::ModuleFileInfo: + case frontend::GetBMIDeclsHash: case frontend::VerifyPCH: case frontend::PluginAction: case frontend::RewriteObjC: diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 1aaebd1602016..06b15079887c7 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -328,8 +328,8 @@ SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { } std::unique_ptr -DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { +DumpModuleInfoActionBase::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { return std::make_unique(); } @@ -809,13 +809,23 @@ namespace { }; } -bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) { +bool DumpModuleInfoActionBase::BeginInvocation(CompilerInstance &CI) { // The Object file reader also supports raw ast files and there is no point in // being strict about the module file format in -module-file-info mode. CI.getHeaderSearchOpts().ModuleFormat = "obj"; return true; } +llvm::raw_ostream &DumpModuleInfoActionBase::getOutputStream() { + StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile; + if (!OutputFileName.empty() && OutputFileName != "-") { + std::error_code EC; + OutputStream.reset(new llvm::raw_fd_ostream( + OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF)); + } + return OutputStream ? *OutputStream : llvm::outs(); +} + static StringRef ModuleKindName(Module::ModuleKind MK) { switch (MK) { case Module::ModuleMapModule: @@ -842,15 +852,9 @@ static StringRef ModuleKindName(Module::ModuleKind MK) { void DumpModuleInfoAction::ExecuteAction() { assert(isCurrentFileAST() && "dumping non-AST?"); - // Set up the output file. + CompilerInstance &CI = getCompilerInstance(); - StringRef OutputFileName = CI.getFrontendOpts().OutputFile; - if (!OutputFileName.empty() && OutputFileName != "-") { - std::error_code EC; - OutputStream.reset(new llvm::raw_fd_ostream( - OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF)); - } - llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs(); + llvm::raw_ostream &Out = getOutputStream(); Out << "Information for module file '" << getCurrentFile() << "':\n"; auto &FileMgr = CI.getFileManager(); @@ -875,6 +879,12 @@ void DumpModuleInfoAction::ExecuteAction() { serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule(); Out << " ====== C++20 Module structure ======\n"; + std::optional DeclsHash = R->getReadedBMIDeclsHash(); + if (DeclsHash) { + Out << " Decls Hash: "; + Out.write_hex(*DeclsHash) << "\n"; + } + if (MF.ModuleName != LO.CurrentModule) Out << " Mismatched module names : " << MF.ModuleName << " and " << LO.CurrentModule << "\n"; @@ -963,6 +973,23 @@ void DumpModuleInfoAction::ExecuteAction() { HSOpts.ModulesValidateDiagnosticOptions); } +void GetModuleDeclsHashAction::ExecuteAction() { + llvm::raw_ostream &Out = getOutputStream(); + + if (!isCurrentFileAST()) { + Out << "We should only trying to get Decls hash from a module file.\n"; + return; + } + + ASTReader *R = getCurrentASTUnit().getASTReader().get(); + std::optional DeclsHash = R->getReadedBMIDeclsHash(); + if (DeclsHash) { + Out << "Decls Hash: "; + Out.write_hex(*DeclsHash) << "\n"; + } else + Out << "Failed to read Decls Hash.\n"; +} + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 59f7f955db509..1f594d093fcb6 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -75,6 +75,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { case InitOnly: return std::make_unique(); case ParseSyntaxOnly: return std::make_unique(); case ModuleFileInfo: return std::make_unique(); + case GetBMIDeclsHash: + return std::make_unique(); case VerifyPCH: return std::make_unique(); case TemplightDump: return std::make_unique(); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e91d1c65e0f6a..4d458d419f48a 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3385,6 +3385,13 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; } + case BMI_DECLS_HASH: + if (!ReadedBMIDeclsHash) + ReadedBMIDeclsHash = Record[0]; + else + ReadedBMIDeclsHash = llvm::hash_combine(ReadedBMIDeclsHash, Record[0]); + break; + case TU_UPDATE_LEXICAL: { DeclContext *TU = ContextObj->getTranslationUnitDecl(); LexicalContents Contents( @@ -5681,6 +5688,74 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, /*ValidateDiagnosticOptions=*/true); } +std::optional ASTReader::getBMIHash(StringRef Filename, + FileManager &FileMgr) { + // Open the AST file. + std::unique_ptr OwnedBuffer; + + // FIXME: This allows use of the VFS; we do not allow use of the + // VFS when actually loading a module. + auto BufferOrErr = FileMgr.getBufferForFile(Filename); + if (!BufferOrErr) + return std::nullopt; + + OwnedBuffer = std::move(*BufferOrErr); + llvm::MemoryBuffer *Buffer = OwnedBuffer.get(); + + // Initialize the stream + // FIXME: Should we consider other format? + PCHContainerOperations PCHOperations; + StringRef Bytes = PCHOperations.getRawReader().ExtractPCH(*Buffer); + BitstreamCursor Stream(Bytes); + + // Sniff for the signature. + if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) { + consumeError(std::move(Err)); // FIXME this drops errors on the floor. + return std::nullopt; + } + + if (SkipCursorToBlock(Stream, AST_BLOCK_ID)) + return std::nullopt; + + while (true) { + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + consumeError(MaybeEntry.takeError()); + return std::nullopt; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + + switch (Entry.Kind) { + case llvm::BitstreamEntry::Error: + case llvm::BitstreamEntry::EndBlock: + return std::nullopt; + + case llvm::BitstreamEntry::Record: { + RecordData Record; + StringRef Blob; + Expected MaybeRecCode = + Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecCode) { + consumeError(MaybeRecCode.takeError()); + return std::nullopt; + } + if (MaybeRecCode.get() == BMI_DECLS_HASH) + return Record[0]; + + continue; + } + + case llvm::BitstreamEntry::SubBlock: + if (llvm::Error Err = Stream.SkipBlock()) + consumeError(std::move(Err)); + + continue; + } + } + + return std::nullopt; +} + llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // Enter the submodule block. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ee8ba8a6874b5..cb919650499e0 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -826,6 +826,7 @@ void ASTWriter::WriteBlockInfoBlock() { // AST Top-Level Block. BLOCK(AST_BLOCK); + RECORD(BMI_DECLS_HASH); RECORD(TYPE_OFFSET); RECORD(DECL_OFFSET); RECORD(IDENTIFIER_OFFSET); @@ -5093,6 +5094,15 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, DoneWritingDeclsAndTypes = true; + if (isWritingStdCXXNamedModules()) { + if (Chain && Chain->getReadedBMIDeclsHash()) + BMIDeclsHash = + llvm::hash_combine(BMIDeclsHash, *Chain->getReadedBMIDeclsHash()); + + RecordData Record = {BMIDeclsHash}; + Stream.EmitRecord(BMI_DECLS_HASH, Record); + } + // These things can only be done once we've written out decls and types. WriteTypeDeclOffsets(); if (!DeclUpdatesOffsetsRecord.empty()) diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ca7794b8c5f97..02f6b18edff0f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2509,6 +2509,124 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context, return Context.DeclMustBeEmitted(D); } +/// Get the hash value of D for the part which contributes to the +/// BMI (built module interface). +/// +/// Return std::nullopt in case we are confident the Declaration won't +/// contribute to the BMI completely. +/// +/// Note that, for the safety consideration, we can/should return the hash +/// value if we are not confident that D may contribute to the interface or +/// not. +static std::optional getBMICompatibleHash(Decl *D) { + ODRHash Hasher; + + if (auto *FD = dyn_cast(D)) { + if (!MayDefAffectABI(FD)) { + // For non-exported non-inline function, we can skip recording its hash + // value in the BMI. + if (FD->isInvisibleOutsideTheOwningModule()) + return std::nullopt; + + // For exported non-inline function, it should be fine enough to record + // the signature only. + Hasher.AddFunctionDecl(FD, /*SkipBody=*/true); + return Hasher.CalculateHash(); + } + + // For inlined functions, actually there are cases the BMI should keep the + // same after we touch the inlined functions, e.g., + // + // export module a; + // inline int f() { return 43; } + // export int a() { return f(); } + // + // Since all the uses of `f()` is in an non-inline function, it should be + // fine to keep the module interface unchanged if we change the definition + // of `f()`. + // + // However, to make the general cases work, we have to perform a context + // sensitive reachable analysis to get whether the inline funciton may be + // used by an exported inline function transitively. Maybe it is not so hard + // or maybe there are simple cases we can cover easily, but we leave the + // oppotunities to the future. + + // Otherwise we can try to use the cached ODR Hash. + return FD->getODRHash(); + } + + if (auto *VD = dyn_cast(D)) { + if (!MayDefAffectABI(VD) && VD->isInvisibleOutsideTheOwningModule()) + return std::nullopt; + + Hasher.AddDecl(VD); + Hasher.AddQualType(VD->getType()); + // ODRHash::AddDecl won't add the definition for variables by default. + if (MayDefAffectABI(VD) && VD->hasInit()) + Hasher.AddStmt(VD->getInit()); + + return Hasher.CalculateHash(); + } + + if (auto *CXXRD = dyn_cast(D)) { + if (!CXXRD->hasDefinition()) + return std::nullopt; + + // We can't filter the case if the class is not exported since the + // non-exported class may be reachable to users: + // + // export module a; + // class A{}; + // export A a() { ... } + // + // The users of 'a' can get `A` by: + // + // auto v = a(); + + // We can't use CXXRecordDecl::getODRHash since it'll use the ODR + // hash for all member functions and all member variables. + // + // The member function and field variables will be recorded seperately. + // + // TODO: We should try to merge these logics to ODRHash and StmtProfiler. + Hasher.AddDecl(CXXRD); + Hasher.AddInteger(CXXRD->getNumBases()); + auto Bases = CXXRD->bases(); + for (const auto &Base : Bases) { + Hasher.AddQualType(Base.getTypeSourceInfo()->getType()); + Hasher.AddBoolean(Base.isVirtual()); + Hasher.AddInteger(Base.getAccessSpecifierAsWritten()); + } + + return Hasher.CalculateHash(); + } + + if (auto *ED = dyn_cast(D)) { + if (ED->isInvisibleOutsideTheOwningModule()) + return std::nullopt; + + // Try to use the cached ODR Hash Value. + return ED->getODRHash(); + } + + if (auto *FD = dyn_cast(D)) { + Hasher.AddDecl(D); + Hasher.AddSubDecl(FD); + Hasher.CalculateHash(); + } + + Hasher.AddDecl(D); + return Hasher.CalculateHash(); +} + +static void conditionaly_hash_combine(llvm::hash_code &HashValue, Decl *D) { + std::optional ODRHashD = getBMICompatibleHash(D); + if (!ODRHashD) + return; + + HashValue = llvm::hash_combine(HashValue, *ODRHashD); +} + void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(), "serializing"); @@ -2530,6 +2648,9 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Build a record for this declaration W.Visit(D); + if (isWritingStdCXXNamedModules()) + conditionaly_hash_combine(BMIDeclsHash, D); + // Emit this declaration to the bitstream. uint64_t Offset = W.Emit(D); diff --git a/clang/test/Modules/cxx20-module-file-info.cpp b/clang/test/Modules/cxx20-module-file-info.cpp index 99a215645e8fe..6ee8ada7d6b8f 100644 --- a/clang/test/Modules/cxx20-module-file-info.cpp +++ b/clang/test/Modules/cxx20-module-file-info.cpp @@ -30,6 +30,7 @@ export module A; void a(); // CHECK-A: ====== C++20 +// CHECK-A-NEXT: Decls Hash // CHECK-A-NEXT: Interface Unit 'A' is the Primary Module at index #1 //--- mod-info-tu2.cpp @@ -38,6 +39,7 @@ export module B; void b(); // CHECK-B: ====== C++20 +// CHECK-B-NEXT: Decls Hash // CHECK-B-NEXT: Interface Unit 'B' is the Primary Module at index #1 //--- mod-info-tu3.cpp @@ -55,6 +57,7 @@ export void say(const char *); void foo() {} // CHECK-FOO: ====== C++20 +// CHECK-FOO-NEXT: Decls Hash // CHECK-FOO-NEXT: Interface Unit 'Foo' is the Primary Module at index #3 // CHECK-FOO-NEXT: Sub Modules: // CHECK-FOO-NEXT: Global Module Fragment '' is at index #4 diff --git a/clang/test/Modules/decls-hash-get-bmi-decls-hash.cppm b/clang/test/Modules/decls-hash-get-bmi-decls-hash.cppm new file mode 100644 index 0000000000000..5bc253acce5ff --- /dev/null +++ b/clang/test/Modules/decls-hash-get-bmi-decls-hash.cppm @@ -0,0 +1,35 @@ +// Test that -module-file-info can print the decls hash for thin BMI. +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/a.v1.cppm -emit-thin-module-interface -o %t/a.v1.pcm +// +// RUN: %clang_cc1 -get-bmi-decls-hash %t/a.pcm > %t/a.pcm.hash +// RUN: %clang_cc1 -get-bmi-decls-hash %t/a.v1.pcm > %t/a.v1.pcm.hash +// +// RUN: diff %t/a.pcm.hash %t/a.v1.pcm.hash + +//--- a.cppm +export module a; +export int v = 43; +export int a() { + return 43; +} + +unsigned int non_exported() { + return v; +} + +//--- a.v1.cppm +export module a; +export int v = 45; +export int a() { + return 44; +} + +unsigned int non_exported() { + return v + 43; +} diff --git a/clang/test/Modules/decls-hash-module-file-info.cppm b/clang/test/Modules/decls-hash-module-file-info.cppm new file mode 100644 index 0000000000000..f9a2fa5155ccc --- /dev/null +++ b/clang/test/Modules/decls-hash-module-file-info.cppm @@ -0,0 +1,35 @@ +// Test that -module-file-info can print the decls hash for thin BMI. +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/a.v1.cppm -emit-thin-module-interface -o %t/a.v1.pcm +// +// RUN: %clang_cc1 -module-file-info %t/a.pcm | grep "Decls Hash:" > %t/a.pcm.hash +// RUN: %clang_cc1 -module-file-info %t/a.v1.pcm | grep "Decls Hash:" > %t/a.v1.pcm.hash +// +// RUN: diff %t/a.pcm.hash %t/a.v1.pcm.hash + +//--- a.cppm +export module a; +export int v = 43; +export int a() { + return 43; +} + +unsigned int non_exported() { + return v; +} + +//--- a.v1.cppm +export module a; +export int v = 45; +export int a() { + return 44; +} + +unsigned int non_exported() { + return v + 43; +} diff --git a/clang/unittests/Serialization/BMIDeclsHashTest.cpp b/clang/unittests/Serialization/BMIDeclsHashTest.cpp new file mode 100644 index 0000000000000..9b6333cedcd38 --- /dev/null +++ b/clang/unittests/Serialization/BMIDeclsHashTest.cpp @@ -0,0 +1,952 @@ +//===- unittests/Serialization/ThinBMIDeclsHashTest.cpp - CI tests --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/FileManager.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/Utils.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Serialization/ASTReader.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +#include "gtest/gtest.h" + +using namespace llvm; +using namespace clang; + +namespace { + +class ThinBMIDeclsHashTest : public ::testing::Test { + void SetUp() override { + ASSERT_FALSE(sys::fs::createUniqueDirectory("modules-test", TestDir)); + } + + void TearDown() override { sys::fs::remove_directories(TestDir); } + + using PathType = llvm::SmallString<256>; + + PathType TestDir; + +public: + FileManager FMgr = FileManager{FileSystemOptions()}; + + void addFile(StringRef Path, StringRef Contents) { + ASSERT_TRUE(sys::path::is_absolute(Path)); + ASSERT_TRUE(Path.startswith(TestDir)); + + std::error_code EC; + llvm::raw_fd_ostream OS(Path, EC); + ASSERT_FALSE(EC); + OS << Contents; + } + + PathType getUniquePathInTestDir(StringRef Suffix) { + PathType Pattern("%%-%%-%%-%%-%%-%%"); + Pattern.append(Suffix); + llvm::sys::fs::createUniquePath(Pattern, Pattern, /*MakeAbsolute=*/false); + + PathType Result(TestDir); + llvm::sys::path::append(Result, Pattern); + return Result; + } + + // Map from module name to BMI path. + using ModuleMapTy = llvm::StringMap; + + std::string GenerateModuleInterface(StringRef Contents, + StringRef AdditionalArgs = StringRef()) { + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(new DiagnosticOptions()); + CreateInvocationOptions CIOpts; + CIOpts.Diags = Diags; + CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + + PathType InterfaceSourceName = getUniquePathInTestDir(".cppm"); + addFile(InterfaceSourceName, Contents); + + const char *Args[] = {"clang++", + "-std=c++20", + "--precompile", + AdditionalArgs.data(), + "-working-directory", + TestDir.c_str(), + "-I", + TestDir.c_str(), + InterfaceSourceName.c_str()}; + std::shared_ptr Invocation = + createInvocation(Args, CIOpts); + EXPECT_TRUE(Invocation); + + CompilerInstance Instance; + Instance.setDiagnostics(Diags.get()); + Instance.setInvocation(Invocation); + + PathType CacheBMIPath = getUniquePathInTestDir(".pcm"); + Instance.getFrontendOpts().OutputFile = (std::string)CacheBMIPath; + GenerateThinModuleInterfaceAction Action; + EXPECT_TRUE(Instance.ExecuteAction(Action)); + EXPECT_FALSE(Diags->hasErrorOccurred()); + + return (std::string)CacheBMIPath; + } + + std::optional getBMIHash(StringRef BMIPath) { + return ASTReader::getBMIHash(BMIPath, FMgr); + } + + bool CompareBMIHash(StringRef Contents1, StringRef Contents2) { + auto BMIPath1 = GenerateModuleInterface(Contents1); + auto BMIPath2 = GenerateModuleInterface(Contents2); + + std::optional Hash1 = getBMIHash(BMIPath1); + EXPECT_TRUE(Hash1); + std::optional Hash2 = getBMIHash(BMIPath2); + EXPECT_TRUE(Hash2); + + return *Hash1 == *Hash2; + } +}; + +// Test that: +// - the BMI hash won't change if we only touched the body of a non-inline +// function. +// - the BMI hash will change if we changed the interface of exported non-inline +// function. +// - the BMI hash will change if we add or delete exported functions. +// - the BMI hash won't change if we changed, add and delete non-exported and +// non-inline +// function. +TEST_F(ThinBMIDeclsHashTest, BasicNonInlineFuncTest) { + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export int a() { + return 44; +} + )cpp")); + + // The interface should change if we change the function name. + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export int b() { + return 43; +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export char a() { + return 44; +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export int a(int v = 43) { + return 44 + v; +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a(int v = 44) { + return v; +} + )cpp", + R"cpp( +export module a; +export int a(int v = 43) { + return v; +} + )cpp")); + + // Test that the comment won't change the interface. + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +// New comments here. +export int a() { + return 43; +} + )cpp")); + + // Test that adding new exported functions may change the interface. + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export int a() { + return 43; +} + +export int a2() { + return a() + 43; +} + )cpp")); + + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; + +int non_exported() { return 49; } + +export int a() { + return non_exported(); +} + )cpp")); + + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; + +int non_exported() { return 99; } + +export int a() { + return non_exported(); +} + )cpp")); +} + +// Tests that: +// - The interface shouldn't change if we changed the definition of the +// non-inline variables. +// - The interface shouldn change if we change the interface (type and name) of +// the exported +// non-inline variables. +// - The interface shouldn't change if we change, add or remove non-exported and +// non-inline +// variables. +TEST_F(ThinBMIDeclsHashTest, BasicNonInlineVarTest) { + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +export int a = 45; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +export short a = 43; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +export double a = 43.0; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +export int aa = 43; + )cpp")); + + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +int a_def(); +export int a = a_def(); + )cpp")); + + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +int a_def(); +int a_non_exported = a_def(); +export int a = a_non_exported; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +export int a = 43; +export int another_exported = 44; + )cpp")); +} + +TEST_F(ThinBMIDeclsHashTest, OrderingTests) { + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export int v = 43; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export int a() { + return 43; +} +export int v = 43; + )cpp")); +} + +// Tests that the inerface will change every time we touched, added or delete +// an inline function. +TEST_F(ThinBMIDeclsHashTest, InlineFunctionTests) { + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export inline int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export inline int a() { + return 44; +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export inline int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export inline short a() { + return 43; +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export inline int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +export inline int a(int v = 44) { + return 43; +} + )cpp")); + + // Note that the following cases **can** be fine if the interface didn't + // change. But we choose to change the interface according to our current + // implementation strategies to change the interface every time for every + // change in inline functions. + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp", + R"cpp( +export module a; +inline int inl_a() { + return 44; +} +export int a() { + return inl_a(); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +inline int inl_a() { + return 45; +} +export int a() { + return inl_a(); +} + )cpp", + R"cpp( +export module a; +inline int inl_a() { + return 44; +} +export int a() { + return inl_a(); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +inline int inl_a() { + return 44; +} +export int a() { + return inl_a(); +} + )cpp", + R"cpp( +export module a; +inline int inl_a() { + return 44; +} +inline int new_unused_inline() { + return 43; +} +export int a() { + return inl_a(); +} + )cpp")); + + /// Testing implicitly inline function. + + // Note that the following case **can** be fine if the interface didn't + // change. But we choose to change the interface according to our current + // implementation strategies to change the interface every time for every + // change in inline functions. + EXPECT_FALSE(CompareBMIHash(R"cpp( +module; +class A { +public: + int get() { return 43; } +}; +export module a; +export int a() { + A a; + return a.get(); +} + )cpp", + R"cpp( +module; +class A { +public: + int get() { return 44; } +}; +export module a; +export int a() { + A a; + return a.get(); +} + )cpp")); +} + +// Tests that the inerface will change every time we touched, added or delete +// an inline variables. +TEST_F(ThinBMIDeclsHashTest, InlineVarTests) { + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export inline int a = 43; + )cpp", + R"cpp( +export module a; +export inline int a = 45; + )cpp")); + + // Note that the following case **can** be fine if the interface didn't + // change. But we choose to change the interface according to our current + // implementation strategies to change the interface every time for every + // change in inline functions. + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +inline int a = 43; + )cpp", + R"cpp( +export module a; +inline int a = 45; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export int a = 43; + )cpp", + R"cpp( +export module a; +export int a = 43; +inline int v = 49; + )cpp")); +} + +TEST_F(ThinBMIDeclsHashTest, ClassTests) { + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +export class A { +public: + int get() { return 43; } +}; + )cpp", + R"cpp( +export module a; +export class A { +public: + int get() { return 44; } +}; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export class A { +public: + int get() { return 43; } +}; + )cpp", + R"cpp( +export module a; +export class A { +public: + int get() { return 43; } + + int get_2() { return 44;} +}; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export class A { +public: + int get() { return 43; } +}; + )cpp", + R"cpp( +export module a; +export class A { + int a = 43; +public: + int get() { return a; } +}; + )cpp")); + + /// Testing the use of different classes in inline functions. + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +class A { +public: + int get() { return 43; } +}; +export inline int func() { + A a; + return a.get(); +} + )cpp", + R"cpp( +export module a; +class A { +public: + int get() { return 44; } +}; +export inline int func() { + A a; + return a.get(); +} + )cpp")); + + EXPECT_TRUE(CompareBMIHash(R"cpp( +export module a; +class A { +public: + int get() { return 43; } +}; +export inline int func() { + A a; + return a.get(); +} + )cpp", + R"cpp( +export module a; +class A { +public: + int get() { return 43; } + int get_2() { return 44; } +}; +export inline int func() { + A a; + return a.get(); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class A { +public: + int get() { return 43; } +}; +export inline int func() { + A a; + return a.get(); +} + )cpp", + R"cpp( +export module a; +class A { + int a = 43; +public: + int get() { return a; } +}; +export inline int func() { + A a; + return a.get(); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class A { +public: + int get() { return 43; } +}; +export inline A func() { + return A(); +} + )cpp", + R"cpp( +export module a; +class A { + int a = 43; +public: + int get() { return a; } +}; +export inline A func() { + return A(); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class A { + int a = 44; +public: + int get() { return a; } +}; +export inline A func() { + return A(); +} + )cpp", + R"cpp( +export module a; +class A { + int a = 43; +public: + int get() { return a; } +}; +export inline A func() { + return A(); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class A { + int a = 44; +public: + int get() { return a; } +}; +export inline A func() { + return A(); +} + )cpp", + R"cpp( +export module a; +class A { + short a = 44; +public: + int get() { return a; } +}; +export inline A func() { + return A(); +} + )cpp")); + + // Testing different bases + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export class A {}; + )cpp", + R"cpp( +export module a; +class Base1 {}; +export class A : public Base1 {}; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class Base1 {}; +export class A : public Base1 {}; + )cpp", + R"cpp( +export module a; +class Base1 {}; +export class A : protected Base1 {}; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class Base1 {}; +class Base2 {}; +export class A : public Base1 {}; + )cpp", + R"cpp( +export module a; +class Base1 {}; +class Base2 {}; +export class A : public Base1, public Base2 {}; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +class Base1 {}; +class Base2 {}; +export class A : public Base1, public Base2 {}; + )cpp", + R"cpp( +export module a; +class Base1 {}; +class Base2 {}; +export class A : virtual public Base1, virtual public Base2 {}; + )cpp")); +} + +TEST_F(ThinBMIDeclsHashTest, ExportUsingTests) { + EXPECT_TRUE(CompareBMIHash(R"cpp( +module; +int a() { return 43; } +export module a; +export using ::a; + )cpp", + R"cpp( +module; +int a() { return 44; } +export module a; +export using ::a; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +module; +inline int a() { return 43; } +export module a; +export using ::a; + )cpp", + R"cpp( +module; +inline int a() { return 44; } +export module a; +export using ::a; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +module; +class A { +public: + int get() { return 43; } +}; +export module a; +export using ::A; + )cpp", + R"cpp( +module; +class A { +public: + int get() { return 44; } +}; +export module a; +export using ::A; + )cpp")); +} + +TEST_F(ThinBMIDeclsHashTest, ConstExprTests) { + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export constexpr int a = 43; + )cpp", + R"cpp( +export module a; +export constexpr int a = 44; + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export constexpr int a() { + return 44; +} + )cpp", + R"cpp( +export module a; +export constexpr int a() { + return 45; +} + )cpp")); +} + +TEST_F(ThinBMIDeclsHashTest, TemplateTests) { + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export template +int get(C c) { return 43 + c; } + )cpp", + R"cpp( +export module a; +export template +int get(C c) { return 44 + c; } + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +template +int get(C c) { return 43 + c; } +export int a() { + return get(43); +} + )cpp", + R"cpp( +export module a; +template +int get(C c) { return 44 + c; } +export int a() { + return get(43); +} + )cpp")); + + EXPECT_FALSE(CompareBMIHash(R"cpp( +export module a; +export template +class Templ { +public: + // get is a non-template function inside a template class. + int get() { return 43; } +}; + )cpp", + R"cpp( +export module a; +export template +class Templ { +public: + int get() { return 44; } +}; + )cpp")); +} + +static std::string get_module_map_flag(StringRef ModuleName, + StringRef BMIPath) { + return std::string("-fmodule-file=") + ModuleName.str() + "=" + BMIPath.str(); +} + +// Test that if the decls hash of any import module changes, change +// the decls hash of the current module. +TEST_F(ThinBMIDeclsHashTest, ImportTests) { + auto BMIPathA = GenerateModuleInterface(R"cpp( +export module a; +export int a() { + return 43; +} + )cpp"); + + auto BMIPathB = GenerateModuleInterface(R"cpp( +export module b; +import a; + )cpp", + get_module_map_flag("a", BMIPathA)); + + std::optional Hash1 = getBMIHash(BMIPathB); + EXPECT_TRUE(Hash1); + + // Test that if the decls hash of the imported doesn't change, + // the decls hash of the current module shouldn't change. + BMIPathA = GenerateModuleInterface(R"cpp( +export module a; +export int a() { + return 44; +} + )cpp"); + + BMIPathB = GenerateModuleInterface(R"cpp( +export module b; +import a; + )cpp", + get_module_map_flag("a", BMIPathA)); + + std::optional Hash2 = getBMIHash(BMIPathB); + EXPECT_TRUE(Hash2); + + EXPECT_EQ(*Hash1, *Hash2); + + // Test that if the decls hash of the imported changes, + // the decls hash of the current module shouldn't change. + BMIPathA = GenerateModuleInterface(R"cpp( +export module a; +export long long a(int x = 43) { + return 43; +} + )cpp"); + + BMIPathB = GenerateModuleInterface(R"cpp( +export module b; +import a; + )cpp", + get_module_map_flag("a", BMIPathA)); + + std::optional Hash3 = getBMIHash(BMIPathB); + EXPECT_TRUE(Hash2); + + EXPECT_NE(*Hash1, *Hash3); +} + +} // namespace diff --git a/clang/unittests/Serialization/CMakeLists.txt b/clang/unittests/Serialization/CMakeLists.txt index 10d7de970c643..a34e0b4c5d7dc 100644 --- a/clang/unittests/Serialization/CMakeLists.txt +++ b/clang/unittests/Serialization/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS ) add_clang_unittest(SerializationTests + BMIDeclsHashTest.cpp ForceCheckFileInputTest.cpp InMemoryModuleCacheTest.cpp ModuleCacheTest.cpp