Index: clang/include/clang/AST/DeclBase.h =================================================================== --- clang/include/clang/AST/DeclBase.h +++ clang/include/clang/AST/DeclBase.h @@ -232,9 +232,12 @@ /// This declaration has an owning module, but is only visible to /// lookups that occur within that module. - /// The discarded declarations in global module fragment belongs - /// to this group too. - ModulePrivate + ModulePrivate, + + /// This declaration is part of a Global Module Fragment, it is permitted + /// to discard it and therefore it is not reachable or visible to importers + /// of the named module of which the GMF is part. + ModuleDiscardable }; protected: @@ -647,9 +650,10 @@ /// Whether this declaration comes from another module unit. bool isInAnotherModuleUnit() const; - /// FIXME: Implement discarding declarations actually in global module - /// fragment. See [module.global.frag]p3,4 for details. - bool isDiscardedInGlobalModuleFragment() const { return false; } + /// See [module.global.frag]p3,4 for details. + bool isDiscardedInGlobalModuleFragment() const { + return getModuleOwnershipKind() == ModuleOwnershipKind::ModuleDiscardable; + } /// Return true if this declaration has an attribute which acts as /// definition of the entity, such as 'alias' or 'ifunc'. Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -176,6 +176,7 @@ BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 3, CMK_None, "compiling a module interface") BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch") +LANGOPT(DiscardGMFDecls , 1, 1, "Discard unreachable decls in GMF") BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a corresponding object file") BENIGN_LANGOPT(CacheGeneratedPCH, 1, 0, "cache generated PCH files in memory") BENIGN_LANGOPT(PCHInstantiateTemplates, 1, 0, "instantiate templates while building a PCH") Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2449,6 +2449,12 @@ PosFlag, NegFlag, BothFlags<[NoXarchOption, CC1Option]>>; +defm discarding_gmf_decls : BoolFOption<"discarding-gmf-decls", + LangOpts<"DiscardGMFDecls">, DefaultTrue, + PosFlag, + NegFlag, + BothFlags<[NoDriverOption, CC1Option]>>; + def fmodule_output_EQ : Joined<["-"], "fmodule-output=">, Flags<[NoXarchOption, CC1Option]>, HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">; def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption, CC1Option]>, Index: clang/include/clang/Serialization/ASTWriter.h =================================================================== --- clang/include/clang/Serialization/ASTWriter.h +++ clang/include/clang/Serialization/ASTWriter.h @@ -455,6 +455,22 @@ std::vector NonAffectingRanges; std::vector NonAffectingOffsetAdjustments; + /// Mark ModuleDiscardable Decl D and its file scope top level declaration D + /// as reachable. This is a no-op if D is not ModuleDiscardable. We'll mark + /// the file scope top level declaration D as reachable too. Otherwise, it is + /// problematic if some parts of a decl is discarded in some TU and these + /// parts are not discarded in other TUs. This is an ODR violation. So if a + /// sub-decl is reachable, the top level decl and all of its children should + /// be reachable too. + void MarkDeclReachable(const Decl *D); + /// A helper to IsDeclModuleDiscardable. There are special declarations which + /// may not be referenced directly. But they can't be discarded if their + /// correspond decls are reachable. e.g., the deduction guides decls. + bool IsSpecialDeclNotDiscardable(Decl *D); + /// Callbacks to mark special decls as reachable once their corresponding + /// decls become reachable. + llvm::DenseMap> ReachableMarkerCallbacks; + /// Collects input files that didn't affect compilation of the current module, /// and initializes data structures necessary for leaving those files out /// during \c SourceManager serialization. @@ -740,6 +756,14 @@ return WritingModule && WritingModule->isModulePurview(); } + /// Whether or not D is module discardable. Besides the case that D is marked + /// not module discardable explicitly, `IsDeclModuleDiscardable` will return + /// false if: + /// - The file scope top level declaration of D is not module discardable. + /// - D is a deduction guide for another template declaration TD and TD is not + /// module discardable. + bool IsDeclModuleDiscardable(const Decl *D); + private: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader) override; Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -592,6 +592,7 @@ case Decl::ModuleOwnershipKind::Unowned: case Decl::ModuleOwnershipKind::ReachableWhenImported: case Decl::ModuleOwnershipKind::ModulePrivate: + case Decl::ModuleOwnershipKind::ModuleDiscardable: return false; case Decl::ModuleOwnershipKind::Visible: case Decl::ModuleOwnershipKind::VisibleWhenImported: Index: clang/lib/Sema/SemaModule.cpp =================================================================== --- clang/lib/Sema/SemaModule.cpp +++ clang/lib/Sema/SemaModule.cpp @@ -88,7 +88,11 @@ // within the module unit. // // So the declations in the global module shouldn't be visible by default. - TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported); + if (getLangOpts().DiscardGMFDecls) + TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModuleDiscardable); + else + TU->setModuleOwnershipKind( + Decl::ModuleOwnershipKind::ReachableWhenImported); TU->setLocalOwningModule(GlobalModule); // FIXME: Consider creating an explicit representation of this declaration. Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -638,6 +638,9 @@ case Decl::ModuleOwnershipKind::ReachableWhenImported: case Decl::ModuleOwnershipKind::ModulePrivate: break; + + case Decl::ModuleOwnershipKind::ModuleDiscardable: + llvm_unreachable("We should never read module discardable decls"); } D->setModuleOwnershipKind(ModuleOwnership); Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -2946,7 +2946,8 @@ // Emit the initializers, if any. RecordData Inits; for (Decl *D : Context->getModuleInitializers(Mod)) - Inits.push_back(GetDeclRef(D)); + if (!IsDeclModuleDiscardable(D)) + Inits.push_back(GetDeclRef(D)); if (!Inits.empty()) Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits); @@ -3123,8 +3124,10 @@ uint64_t Offset = Stream.GetCurrentBitNo(); SmallVector KindDeclPairs; for (const auto *D : DC->decls()) { - KindDeclPairs.push_back(D->getKind()); - KindDeclPairs.push_back(GetDeclRef(D)); + if (!IsDeclModuleDiscardable(D)) { + KindDeclPairs.push_back(D->getKind()); + KindDeclPairs.push_back(GetDeclRef(D)); + } } ++NumLexicalDeclContexts; @@ -3770,9 +3773,12 @@ template data_type getData(const Coll &Decls) { unsigned Start = DeclIDs.size(); - for (NamedDecl *D : Decls) { - DeclIDs.push_back( - Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); + for (NamedDecl *ND : Decls) { + auto *D = getDeclForLocalLookup(Writer.getLangOpts(), ND); + if (Writer.IsDeclModuleDiscardable(D)) + continue; + + DeclIDs.push_back(Writer.GetDeclRef(D)); } return std::make_pair(Start, DeclIDs.size()); } @@ -3926,6 +3932,11 @@ isLookupResultEntirelyExternal(Result, DC)) continue; + if (llvm::all_of(Result.getLookupResult(), [this](NamedDecl *D) { + return IsDeclModuleDiscardable(D); + })) + continue; + // We also skip empty results. If any of the results could be external and // the currently available results are empty, then all of the results are // external and we skip it above. So the only way we get here with an empty @@ -4115,7 +4126,7 @@ } for (NamedDecl *ND : Result) - if (!ND->isFromASTFile()) + if (!ND->isFromASTFile() && !IsDeclModuleDiscardable(ND)) GetDeclRef(ND); } @@ -4845,7 +4856,7 @@ const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); SmallVector NewGlobalKindDeclPairs; for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { + if (!D->isFromASTFile() && !IsDeclModuleDiscardable(D)) { NewGlobalKindDeclPairs.push_back(D->getKind()); NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); } @@ -4897,9 +4908,9 @@ // Make sure visible decls, added to DeclContexts previously loaded from // an AST file, are registered for serialization. Likewise for template // specializations added to imported templates. - for (const auto *I : DeclsToEmitEvenIfUnreferenced) { - GetDeclRef(I); - } + for (const auto *I : DeclsToEmitEvenIfUnreferenced) + if (!IsDeclModuleDiscardable(I)) + GetDeclRef(I); // Make sure all decls associated with an identifier are registered for // serialization, if we're storing decls with identifiers. @@ -5222,6 +5233,7 @@ case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: assert(Update.getDecl() && "no decl to add?"); + MarkDeclReachable(Update.getDecl()); Record.push_back(GetDeclRef(Update.getDecl())); break; @@ -5361,6 +5373,7 @@ Record.AddVarDeclInit(VD); } + MarkDeclReachable(D); OffsetsRecord.push_back(GetDeclRef(D)); OffsetsRecord.push_back(Record.Emit(DECL_UPDATES)); } @@ -5621,7 +5634,88 @@ }); } +bool ASTWriter::IsSpecialDeclNotDiscardable(Decl *D) { + assert(D->isDiscardedInGlobalModuleFragment()); + + /// Currently, the only special decl is the deduction guide. + if (auto *ND = dyn_cast(D)) { + DeclarationName Name = ND->getDeclName(); + if (TemplateDecl *TD = Name.getCXXDeductionGuideTemplate()) { + if (!IsDeclModuleDiscardable(TD)) { + MarkDeclReachable(D); + return true; + } + + ReachableMarkerCallbacks[TD].push_back(D); + } + } + + return false; +} + +bool ASTWriter::IsDeclModuleDiscardable(const Decl *ConstD) { + Decl *D = const_cast(ConstD); + + if (!D->isDiscardedInGlobalModuleFragment()) + return false; + + // The Translation Unit should never be module discardable. + if (!D->getDeclContext()) + return false; + + if (IsSpecialDeclNotDiscardable(D)) + return false; + + const DeclContext *DC = D->getNonTransparentDeclContext(); + while (DC && DC->getParent() && + !DC->getParent()->getNonTransparentContext()->isFileContext()) + DC = DC->getParent()->getNonTransparentContext(); + + assert(DC && "Why is the decl not covered by file context?"); + if (DC->isFileContext()) + return true; + + if (!cast(DC)->isDiscardedInGlobalModuleFragment()) { + MarkDeclReachable(D); + return false; + } + + return true; +} + +void ASTWriter::MarkDeclReachable(const Decl *ConstD) { + Decl *D = const_cast(ConstD); + + if (!D || !D->isDiscardedInGlobalModuleFragment()) + return; + + D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported); + if (D->getNonTransparentDeclContext()->isFileContext()) { + // After we convert a module discardable decl to reachable, try to emit it. + GetDeclRef(D); + // Update the decl contexts so that we can still find the decl with name + // lookup. + UpdatedDeclContexts.insert(D->getNonTransparentDeclContext()); + } + + auto Iter = ReachableMarkerCallbacks.find(D); + if (Iter != ReachableMarkerCallbacks.end()) { + for (Decl *ToBeMarked : Iter->second) + MarkDeclReachable(ToBeMarked); + ReachableMarkerCallbacks.erase(D); + } + + DeclContext *DC = D->getNonTransparentDeclContext(); + while (DC && DC->getParent() && + !DC->getParent()->getNonTransparentContext()->isFileContext()) + DC = DC->getParent()->getNonTransparentContext(); + + if (DC && !DC->isFileContext()) + MarkDeclReachable(cast(DC)); +} + void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { + MarkDeclReachable(D); Record.push_back(GetDeclRef(D)); } @@ -5637,6 +5731,8 @@ if (D->isFromASTFile()) return D->getGlobalID(); + assert(!D->isDiscardedInGlobalModuleFragment() && "We shouldn't write discarded decl.\n"); + assert(!(reinterpret_cast(D) & 0x01) && "Invalid decl pointer"); DeclID &ID = DeclIDs[D]; if (ID == 0) { Index: clang/lib/Serialization/ASTWriterDecl.cpp =================================================================== --- clang/lib/Serialization/ASTWriterDecl.cpp +++ clang/lib/Serialization/ASTWriterDecl.cpp @@ -1951,6 +1951,8 @@ // // FIXME: This is not correct; when we reach an imported declaration we // won't emit its previous declaration. + Writer.MarkDeclReachable(D->getPreviousDecl()); + Writer.MarkDeclReachable(MostRecent); (void)Writer.GetDeclRef(D->getPreviousDecl()); (void)Writer.GetDeclRef(MostRecent); } else { Index: clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp =================================================================== --- clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp +++ clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp @@ -30,7 +30,6 @@ void test_early() { in_header = 1; // expected-error {{use of undeclared identifier 'in_header'}} - // expected-note@* {{not visible}} global_module_fragment = 1; // expected-error {{use of undeclared identifier 'global_module_fragment'}} @@ -53,10 +52,9 @@ #endif void test_late() { - in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}} - // expected-note@* {{not visible}} + in_header = 1; // expected-error {{use of undeclared identifier 'in_header'}} - global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}} + global_module_fragment = 1; // expected-error {{use of undeclared identifier 'global_module_fragment'}} exported = 1; Index: clang/test/CXX/module/module.glob.frag/cxx20-10-4-ex2.cppm =================================================================== --- /dev/null +++ clang/test/CXX/module/module.glob.frag/cxx20-10-4-ex2.cppm @@ -0,0 +1,72 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 %t/std-10-4-ex2-interface.cppm -emit-module-interface \ +// RUN: -o %t/M.pcm -Wno-unused-value +// RUN: %clang_cc1 -std=c++20 %t/std-10-4-ex2-implementation.cpp -fmodule-file=M=%t/M.pcm \ +// RUN: -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 %t/std-10-4-ex2-interface.cppm -emit-module-interface \ +// RUN: -o %t/M.pcm -Wno-unused-value -fno-discarding-gmf-decls +// RUN: %clang_cc1 -std=c++20 %t/std-10-4-ex2-implementation.cpp -fmodule-file=M=%t/M.pcm \ +// RUN: -fsyntax-only -verify -fno-discarding-gmf-decls -DNO_DISCARD + +//--- std-10-4-ex2.h + +namespace N { +struct X {}; +int d(); +int e(); +inline int f(X, int = d()) { return e(); } +int g(X); +int h(X); +} // namespace N + +//--- std-10-4-ex2-interface.cppm + +module; + +#include "std-10-4-ex2.h" + +export module M; + +template int use_f() { + N::X x; // N::X, N, and :: are decl-reachable from use_f + return f(x, 123); // N::f is decl-reachable from use_f, + // N::e is indirectly decl-reachable from use_f + // because it is decl-reachable from N::f, and + // N::d is decl-reachable from use_f + // because it is decl-reachable from N::f + // even though it is not used in this call +} + +template int use_g() { + N::X x; // N::X, N, and :: are decl-reachable from use_g + return g((T(), x)); // N::g is not decl-reachable from use_g +} + +template int use_h() { + N::X x; // N::X, N, and :: are decl-reachable from use_h + return h((T(), x)); // N::h is not decl-reachable from use_h, but + // N::h is decl-reachable from use_h +} + +int k = use_h(); +// use_h is decl-reachable from k, so +// N::h is decl-reachable from k + +//--- std-10-4-ex2-implementation.cpp +#ifdef NO_DISCARD +// expected-no-diagnostics +#endif + +module M; + +int a = use_f(); +int b = use_g(); +#ifndef NO_DISCARD +// expected-error@std-10-4-ex2-interface.cppm:20 {{use of undeclared identifier 'g'}} +// expected-note@-3 {{in instantiation of function template specialization 'use_g' requested here}} +#endif +int c = use_h(); Index: clang/test/CXX/module/module.import/p2.cpp =================================================================== --- clang/test/CXX/module/module.import/p2.cpp +++ clang/test/CXX/module/module.import/p2.cpp @@ -67,13 +67,14 @@ module; class A{}; export module C; -void test() { +export void C() { A a; } //--- UseGlobal.cpp import C; void test() { - A a; // expected-error {{'A' must be declared before it is used}} - // expected-note@Global.cppm:2 {{declaration here is not visible}} + A a; // expected-error {{missing '#include'; 'A' must be declared before it is used}} + // expected-note@* {{declaration here is not visible}} + C(); } Index: clang/test/CodeGenCXX/module-intializer-pmf.cpp =================================================================== --- clang/test/CodeGenCXX/module-intializer-pmf.cpp +++ clang/test/CodeGenCXX/module-intializer-pmf.cpp @@ -20,6 +20,8 @@ export InMod IM; +export using ::G; + module :private; struct InPMF { @@ -28,12 +30,12 @@ InPMF P; -// CHECK: define internal void @__cxx_global_var_init -// CHECK: call {{.*}} @_ZN4GlobC1Ev // CHECK: define internal void @__cxx_global_var_init // CHECK: call {{.*}} @_ZNW6HasPMF5InPMFC1Ev // CHECK: define internal void @__cxx_global_var_init // CHECK: call {{.*}} @_ZNW6HasPMF5InModC1Ev +// CHECK: define internal void @__cxx_global_var_init +// CHECK: call {{.*}} @_ZN4GlobC1Ev // CHECK: define void @_ZGIW6HasPMF // CHECK: store i8 1, ptr @_ZGIW6HasPMF__in_chrg // CHECK: call void @__cxx_global_var_init Index: clang/test/CodeGenCXX/module-intializer.cpp =================================================================== --- clang/test/CodeGenCXX/module-intializer.cpp +++ clang/test/CodeGenCXX/module-intializer.cpp @@ -31,19 +31,6 @@ // RUN: -fmodule-file=M=M.pcm -S -emit-llvm -o - \ // RUN: | FileCheck %s --check-prefix=CHECK-IMPL -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.cpp -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-N - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-O - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.cpp -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-P - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.cpp \ -// RUN: -fmodule-file=N.pcm -fmodule-file=O=O.pcm -fmodule-file=M:Part=M-part.pcm \ -// RUN: -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-M - //--- N-h.h struct Oink { @@ -59,16 +46,18 @@ export module N; +export using ::Hog; + export struct Quack { Quack(){}; }; export Quack Duck; -// CHECK-N: define internal void @__cxx_global_var_init -// CHECK-N: call {{.*}} @_ZN4OinkC1Ev // CHECK-N: define internal void @__cxx_global_var_init // CHECK-N: call {{.*}} @_ZNW1N5QuackC1Ev +// CHECK-N: define internal void @__cxx_global_var_init +// CHECK-N: call {{.*}} @_ZN4OinkC1Ev // CHECK-N: define void @_ZGIW1N // CHECK-N: store i8 1, ptr @_ZGIW1N__in_chrg // CHECK-N: call void @__cxx_global_var_init @@ -89,16 +78,19 @@ export module O; +export using ::Cat; + export struct Bark { Bark(){}; }; export Bark Dog; -// CHECK-O: define internal void @__cxx_global_var_init -// CHECK-O: call {{.*}} @_ZN4MeowC2Ev + // CHECK-O: define internal void @__cxx_global_var_init // CHECK-O: call {{.*}} @_ZNW1O4BarkC1Ev +// CHECK-O: define internal void @__cxx_global_var_init +// CHECK-O: call {{.*}} @_ZN4MeowC2Ev // CHECK-O: define void @_ZGIW1O // CHECK-O: store i8 1, ptr @_ZGIW1O__in_chrg // CHECK-O: call void @__cxx_global_var_init @@ -119,16 +111,18 @@ module M:Part; +using ::Frog; + struct Squawk { Squawk(){}; }; Squawk parrot; -// CHECK-P: define internal void @__cxx_global_var_init -// CHECK-P: call {{.*}} @_ZN5CroakC1Ev // CHECK-P: define internal void @__cxx_global_var_init // CHECK-P: call {{.*}} @_ZNW1M6SquawkC1Ev +// CHECK-P: define internal void @__cxx_global_var_init +// CHECK-P: call {{.*}} @_ZN5CroakC1Ev // CHECK-P: define void @_ZGIW1MWP4Part // CHECK-P: store i8 1, ptr @_ZGIW1MWP4Part__in_chrg // CHECK-P: call void @__cxx_global_var_init @@ -152,6 +146,8 @@ export import O; import :Part; +using ::Cow; + export struct Baa { int x; Baa(){}; @@ -161,10 +157,11 @@ export Baa Sheep(10); -// CHECK-M: define internal void @__cxx_global_var_init -// CHECK-M: call {{.*}} @_ZN3MooC1Ev + // CHECK-M: define internal void @__cxx_global_var_init // CHECK-M: call {{.*}} @_ZNW1M3BaaC1Ei +// CHECK-M: define internal void @__cxx_global_var_init +// CHECK-M: call {{.*}} @_ZN3MooC1Ev // CHECK-M: declare void @_ZGIW1O() // CHECK-M: declare void @_ZGIW1N() // CHECK-M: declare void @_ZGIW1MWP4Part() Index: clang/test/Modules/concept.cppm =================================================================== --- clang/test/Modules/concept.cppm +++ clang/test/Modules/concept.cppm @@ -63,12 +63,14 @@ module; #include "foo.h" export module A; +export using ::__fn; //--- B.cppm module; #include "foo.h" export module B; import A; +export using ::__fn; #ifdef DIFFERENT // expected-error@foo.h:41 {{'__fn::operator()' from module 'A.' is not present in definition of '__fn' provided earlier}} Index: clang/test/Modules/explicitly-specialized-template.cpp =================================================================== --- clang/test/Modules/explicitly-specialized-template.cpp +++ clang/test/Modules/explicitly-specialized-template.cpp @@ -39,7 +39,7 @@ //--- Use.cpp import X; -foo f; // expected-error {{'foo' must be declared before it is used}} +foo f; // expected-error {{missing '#include "foo.h"'; 'foo' must be declared before it is used}} // expected-note@* {{declaration here is not visible}} int bar() { X x; Index: clang/test/Modules/inconsistent-deduction-guide-linkage.cppm =================================================================== --- clang/test/Modules/inconsistent-deduction-guide-linkage.cppm +++ clang/test/Modules/inconsistent-deduction-guide-linkage.cppm @@ -19,6 +19,9 @@ #include "C.h" export module B; +export namespace foo { + using foo::bar; +} //--- C.h namespace foo { @@ -33,6 +36,9 @@ module; #include "E.h" export module D; +export namespace foo { + using foo::bar; +} //--- D-part.cppm export module D:part; Index: clang/test/Modules/named-modules-adl-2.cppm =================================================================== --- clang/test/Modules/named-modules-adl-2.cppm +++ clang/test/Modules/named-modules-adl-2.cppm @@ -31,6 +31,8 @@ a(s()); } +export using ::operator+; + //--- c.cppm // expected-no-diagnostics export module c; Index: clang/test/Modules/named-modules-adl.cppm =================================================================== --- clang/test/Modules/named-modules-adl.cppm +++ clang/test/Modules/named-modules-adl.cppm @@ -25,6 +25,8 @@ n::s() + x; } +export using n::operator+; + //--- b.cppm // expected-no-diagnostics export module b; Index: clang/test/Modules/polluted-operator.cppm =================================================================== --- clang/test/Modules/polluted-operator.cppm +++ clang/test/Modules/polluted-operator.cppm @@ -44,6 +44,10 @@ #include "foo.h" #include "bar.h" export module a; +export namespace std { + using std::variant; + using std::_Traits; +} //--- b.cppm module; @@ -51,7 +55,10 @@ export module b; import a; +export namespace std { + using std::variant; + using std::_Traits; +} + // expected-error@* {{has different definitions in different modules; first difference is defined here found data member '_S_copy_ctor' with an initializer}} // expected-note@* {{but in 'a.' found data member '_S_copy_ctor' with a different initializer}} -// expected-error@* {{from module 'a.' is not present in definition of 'variant<_Types...>' provided earlier}} -// expected-note@* {{declaration of 'swap' does not match}} Index: clang/test/Modules/pr58716.cppm =================================================================== --- clang/test/Modules/pr58716.cppm +++ clang/test/Modules/pr58716.cppm @@ -14,6 +14,8 @@ #include "fail.h" export module mymodule; +export using ::this_fails; + // CHECK: @.str = {{.*}}"{}\00" // CHECK: store{{.*}}ptr @.str Index: clang/test/Modules/pr60775.cppm =================================================================== --- clang/test/Modules/pr60775.cppm +++ clang/test/Modules/pr60775.cppm @@ -32,6 +32,10 @@ } } +export namespace std { + using std::initializer_list; +} + //--- b.cpp // expected-no-diagnostics import a; Index: clang/test/Modules/pr62589.cppm =================================================================== --- clang/test/Modules/pr62589.cppm +++ clang/test/Modules/pr62589.cppm @@ -70,6 +70,9 @@ export using ::a; export using ::a_view; +// Otherwise the operator== would be discarded. +using ::operator==; + //--- b.cpp // expected-no-diagnostics import a; Index: clang/test/Modules/preferred_name.cppm =================================================================== --- clang/test/Modules/preferred_name.cppm +++ clang/test/Modules/preferred_name.cppm @@ -32,6 +32,8 @@ module; #include "foo.h" export module A; +export using ::foo_templ; +export using ::bar; //--- Use.cppm // expected-no-diagnostics Index: clang/test/Modules/redundant-template-default-arg3.cpp =================================================================== --- clang/test/Modules/redundant-template-default-arg3.cpp +++ clang/test/Modules/redundant-template-default-arg3.cpp @@ -88,6 +88,15 @@ module; #include "foo.h" export module foo; +export using ::v; +export using ::v2; +export using ::v3; +export using ::v4; +export using ::v5; +export using ::v6; +export using ::v7; +export using ::v8; +export using ::v9; //--- use.cpp import foo; Index: clang/test/Modules/template-function-specialization.cpp =================================================================== --- clang/test/Modules/template-function-specialization.cpp +++ clang/test/Modules/template-function-specialization.cpp @@ -48,10 +48,8 @@ void use() { foo(); foo(); - foo2(); // expected-error {{missing '#include'; 'foo2' must be declared before it is used}} - // expected-note@* {{declaration here is not visible}} - foo2(); // expected-error {{missing '#include'; 'foo2' must be declared before it is used}} - // expected-note@* {{declaration here is not visible}} + foo2(); // expected-error {{use of undeclared identifier 'foo2'}} + foo2(); // expected-error {{use of undeclared identifier 'foo2'}} foo3(); foo3();