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/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..1294b3ae1be29 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">, @@ -5088,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">; @@ -7223,7 +7231,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..d4ff4f8f6c57d 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: @@ -174,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; @@ -184,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; } @@ -196,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 53a8681cfdbba..a4a23f3ca03f5 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, @@ -103,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, @@ -549,6 +556,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/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 3019bbc2ddc9c..5dfeaf9d6c62b 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -166,6 +166,15 @@ 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; + + /// 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; @@ -582,7 +591,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 +823,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 +837,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 +848,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/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 6f5ff81410326..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)) || @@ -4086,6 +4087,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 = @@ -4729,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); @@ -5811,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 22f992166ded6..c091a94ea0d78 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; } @@ -4958,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 637c6a35af653..177b40a985789 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2554,12 +2554,14 @@ 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}, {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}, @@ -4236,11 +4238,13 @@ 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: 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 2afcf1cf9f68c..06b15079887c7 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); @@ -288,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(); } @@ -769,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: @@ -802,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(); @@ -830,12 +874,17 @@ 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(); 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"; @@ -924,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 b280a1359d2f2..1f594d093fcb6 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(); @@ -73,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 0d347d86cb2eb..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); @@ -4593,10 +4594,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)); @@ -5091,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()) @@ -5403,18 +5415,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..02f6b18edff0f 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 @@ -2470,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"); @@ -2486,11 +2643,14 @@ 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); + if (isWritingStdCXXNamedModules()) + conditionaly_hash_combine(BMIDeclsHash, D); + // Emit this declaration to the bitstream. uint64_t Offset = W.Emit(D); diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index cf8084333811f..4bceb986a1e58 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,33 @@ 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/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/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/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 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());