Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -1540,6 +1540,11 @@ } Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { + if (isa(this)) + // Namespaces never have module linkage. It is the entities within them + // that [may] do. + return nullptr; + Module *M = getOwningModule(); if (!M) return nullptr; Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -508,22 +508,22 @@ void mangleNameWithAbiTags(GlobalDecl GD, const AbiTagList *AdditionalAbiTags); - void mangleModuleName(const Module *M); + void mangleModuleName(const NamedDecl *ND); void mangleModuleNamePrefix(StringRef Name); void mangleTemplateName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void mangleUnqualifiedName(GlobalDecl GD, + void mangleUnqualifiedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { - mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName(), UnknownArity, - AdditionalAbiTags); + mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName(), DC, + UnknownArity, AdditionalAbiTags); } void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name, - unsigned KnownArity, + const DeclContext *DC, unsigned KnownArity, const AbiTagList *AdditionalAbiTags); - void mangleUnscopedName(GlobalDecl GD, + void mangleUnscopedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); - void mangleUnscopedTemplateName(GlobalDecl GD, + void mangleUnscopedTemplateName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); void mangleRegCallName(const IdentifierInfo *II); @@ -704,7 +704,8 @@ if (VD->isExternC()) return false; - // Variables at global scope with non-internal linkage are not mangled. + // Variables at global scope are not mangled unless they have internal + // linkage or are specializations or are attached to a named module. const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) @@ -712,7 +713,8 @@ DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage && !CXXNameMangler::shouldHaveAbiTags(*this, VD) && - !isa(VD)) + !isa(VD) && + !VD->getOwningModuleForLinkage()) return false; } @@ -976,14 +978,6 @@ return; } - // Do not mangle the owning module for an external linkage declaration. - // This enables backwards-compatibility with non-modular code, and is - // a valid choice since conflicts are not permitted by C++ Modules TS - // [basic.def.odr]/6.2. - if (!ND->hasExternalFormalLinkage()) - if (Module *M = ND->getOwningModuleForLinkage()) - mangleModuleName(M); - // Closures can require a nested-name mangling even if they're semantically // in the global namespace. if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { @@ -995,51 +989,56 @@ // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) { - mangleUnscopedTemplateName(TD, AdditionalAbiTags); + mangleUnscopedTemplateName(TD, DC, AdditionalAbiTags); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); return; } - mangleUnscopedName(GD, AdditionalAbiTags); + mangleUnscopedName(GD, DC, AdditionalAbiTags); return; } mangleNestedName(GD, DC, AdditionalAbiTags); } -void CXXNameMangler::mangleModuleName(const Module *M) { - // Implement the C++ Modules TS name mangling proposal; see - // https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile - // - // ::= W + E - // ::= W * E - Out << 'W'; - mangleModuleNamePrefix(M->Name); - Out << 'E'; +void CXXNameMangler::mangleModuleName(const NamedDecl *ND) { + if (ND->isExternallyVisible()) + if (Module *M = ND->getOwningModuleForLinkage()) + mangleModuleNamePrefix(M->Name); } +// ::= +// ::= +// ::= +// ::= W +// ::= W P +// FIXME: Verify partitions are handled correctly once they are available. void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) { - // ::= _ # 0 < seq-id < 10 - // ::= W _ # otherwise + // ::= S _ auto It = ModuleSubstitutions.find(Name); if (It != ModuleSubstitutions.end()) { - if (It->second < 10) - Out << '_' << static_cast('0' + It->second); - else - Out << 'W' << (It->second - 10) << '_'; + Out << 'S'; + mangleSeqID(It->second); return; } // FIXME: Preserve hierarchy in module names rather than flattening // them to strings; use Module*s as substitution keys. - auto Parts = Name.rsplit('.'); - if (Parts.second.empty()) - Parts.second = Parts.first; - else - mangleModuleNamePrefix(Parts.first); + bool IsPartition = false; + auto Sub = Name; + for (auto Split = Name.size(); Split--;) + if (Name[Split] == '.' || Name[Split] == ':') { + IsPartition = Name[Split] == ':'; + mangleModuleNamePrefix(Name.take_front(Split)); + Sub = Name.substr(Split + 1); + break; + } - Out << Parts.second.size() << Parts.second; - ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()}); + Out << 'W'; + if (IsPartition) + Out << 'P'; + Out << Sub.size() << Sub; + ModuleSubstitutions.insert({Name, SeqID++}); } void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, @@ -1048,27 +1047,27 @@ const DeclContext *DC = getEffectiveDeclContext(TD); if (DC->isTranslationUnit() || isStdNamespace(DC)) { - mangleUnscopedTemplateName(TD, nullptr); + mangleUnscopedTemplateName(TD, DC, nullptr); mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs); } else { mangleNestedName(TD, TemplateArgs, NumTemplateArgs); } } -void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, +void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { - const NamedDecl *ND = cast(GD.getDecl()); // ::= // ::= St # ::std:: - if (isStdNamespace(getEffectiveDeclContext(ND))) + assert(!isa(DC) && "unskipped LinkageSpecDecl"); + if (isStdNamespace(DC)) Out << "St"; - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } void CXXNameMangler::mangleUnscopedTemplateName( - GlobalDecl GD, const AbiTagList *AdditionalAbiTags) { + GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { const TemplateDecl *ND = cast(GD.getDecl()); // ::= // ::= @@ -1081,9 +1080,10 @@ "template template param cannot have abi tags"); mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else if (isa(ND) || isa(ND)) { - mangleUnscopedName(GD, AdditionalAbiTags); + mangleUnscopedName(GD, DC, AdditionalAbiTags); } else { - mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), AdditionalAbiTags); + mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), DC, + AdditionalAbiTags); } addSubstitution(ND); @@ -1359,15 +1359,19 @@ mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs); } -void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, - DeclarationName Name, - unsigned KnownArity, - const AbiTagList *AdditionalAbiTags) { +void CXXNameMangler::mangleUnqualifiedName( + GlobalDecl GD, DeclarationName Name, const DeclContext *DC, + unsigned KnownArity, const AbiTagList *AdditionalAbiTags) { const NamedDecl *ND = cast_or_null(GD.getDecl()); - unsigned Arity = KnownArity; - // ::= + // ::= [] // ::= - // ::= + // ::= [] + // ::= [] DC * E + + if (ND && DC && DC->isFileContext()) + mangleModuleName(ND); + + unsigned Arity = KnownArity; switch (Name.getNameKind()) { case DeclarationName::Identifier: { const IdentifierInfo *II = Name.getAsIdentifierInfo(); @@ -1378,8 +1382,6 @@ // // ::= DC * E // - // These can never be referenced across translation units, so we do - // not need a cross-vendor mangling for anything other than demanglers. // Proposed on cxx-abi-dev on 2016-08-12 Out << "DC"; for (auto *BD : DD->bindings()) @@ -1676,7 +1678,7 @@ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { manglePrefix(DC, NoFunction); - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } Out << 'E'; @@ -1706,7 +1708,7 @@ Out << 'N'; mangleClosurePrefix(PrefixND); - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, nullptr, AdditionalAbiTags); Out << 'E'; } @@ -1784,7 +1786,7 @@ // Mangle the name relative to the closest enclosing function. // equality ok because RD derived from ND above if (D == RD) { - mangleUnqualifiedName(RD, AdditionalAbiTags); + mangleUnqualifiedName(RD, DC, AdditionalAbiTags); } else if (const BlockDecl *BD = dyn_cast(D)) { if (const NamedDecl *PrefixND = getClosurePrefix(BD)) mangleClosurePrefix(PrefixND, true /*NoFunction*/); @@ -1815,7 +1817,7 @@ assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { - mangleUnqualifiedName(GD, AdditionalAbiTags); + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } if (const NamedDecl *ND = dyn_cast(RD ? RD : D)) { @@ -2042,10 +2044,11 @@ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { mangleClosurePrefix(PrefixND, NoFunction); - mangleUnqualifiedName(ND, nullptr); + mangleUnqualifiedName(ND, nullptr, nullptr); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND, nullptr); + const DeclContext *DC = getEffectiveDeclContext(ND); + manglePrefix(DC, NoFunction); + mangleUnqualifiedName(ND, DC, nullptr); } addSubstitution(ND); @@ -2098,11 +2101,13 @@ if (const auto *TTP = dyn_cast(ND)) { mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); + const DeclContext *DC = getEffectiveDeclContext(ND); + manglePrefix(DC, NoFunction); if (isa(ND) || isa(ND)) - mangleUnqualifiedName(GD, nullptr); + mangleUnqualifiedName(GD, DC, nullptr); else - mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), nullptr); + mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), DC, + nullptr); } addSubstitution(ND); @@ -2143,8 +2148,9 @@ mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); - mangleUnqualifiedName(ND, nullptr); + const auto *DC = getEffectiveDeclContext(ND); + manglePrefix(DC, NoFunction); + mangleUnqualifiedName(ND, DC, nullptr); } Out << 'M'; @@ -5985,6 +5991,9 @@ if (TemplateArgs[0].getAsType() != A) return false; + if (SD->getSpecializedTemplate()->getOwningModuleForLinkage()) + return false; + return true; } @@ -6015,6 +6024,9 @@ !isSpecializedAs(TemplateArgs[2].getAsType(), "allocator", A)) return false; + if (SD->getSpecializedTemplate()->getOwningModuleForLinkage()) + return false; + return true; } @@ -6032,6 +6044,9 @@ if (!isStdNamespace(getEffectiveDeclContext(TD))) return false; + if (TD->getOwningModuleForLinkage()) + return false; + // ::= Sa # ::std::allocator if (TD->getIdentifier()->isStr("allocator")) { Out << "Sa"; @@ -6051,6 +6066,9 @@ if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; + if (SD->getSpecializedTemplate()->getOwningModuleForLinkage()) + return false; + // ::= Ss # ::std::basic_string, // ::std::allocator > Index: clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp =================================================================== --- clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp +++ clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp @@ -1,21 +1,21 @@ // RUN: %clang_cc1 -fmodules-ts %S/module.cppm -triple %itanium_abi_triple -emit-module-interface -o %t // RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s --implicit-check-not=unused --implicit-check-not=global_module -// CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global -// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3, +// CHECK-DAG: @_ZW6Module19extern_var_exported = external {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module19inline_var_exported = linkonce_odr {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module18const_var_exported = available_externally {{(dso_local )?}}constant i32 3, // -// CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = available_externally {{(dso_local )?}}global i32 0, -// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = available_externally {{(dso_local )?}}constant i32 3, +// CHECK-DAG: @_ZW6Module25extern_var_module_linkage = external {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module25static_var_module_linkage = available_externally {{(dso_local )?}}global i32 0, +// CHECK-DAG: @_ZW6Module24const_var_module_linkage = available_externally {{(dso_local )?}}constant i32 3, module Module; void use() { - // CHECK: define linkonce_odr {{.*}}@_Z20used_inline_exportedv + // CHECK: define linkonce_odr {{.*}}@_ZW6Module20used_inline_exportedv used_inline_exported(); - // CHECK: declare {{.*}}@_Z18noninline_exportedv + // CHECK: declare {{.*}}@_ZW6Module18noninline_exportedv noninline_exported(); (void)&extern_var_exported; @@ -23,13 +23,13 @@ (void)&const_var_exported; // FIXME: This symbol should not be visible here. - // CHECK: declare {{.*}}@_ZW6ModuleE26used_static_module_linkagev + // CHECK: declare {{.*}}@_ZW6Module26used_static_module_linkagev used_static_module_linkage(); - // CHECK: define linkonce_odr {{.*}}@_ZW6ModuleE26used_inline_module_linkagev + // CHECK: define linkonce_odr {{.*}}@_ZW6Module26used_inline_module_linkagev used_inline_module_linkage(); - // CHECK: declare {{.*}}@_ZW6ModuleE24noninline_module_linkagev + // CHECK: declare {{.*}}@_ZW6Module24noninline_module_linkagev noninline_module_linkage(); (void)&extern_var_module_linkage; Index: clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm =================================================================== --- clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm +++ clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm @@ -6,24 +6,24 @@ // CHECK-DAG: @_ZL23const_var_global_module = internal constant // // For ABI compatibility, these symbols do not include the module name. -// CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module19extern_var_exported = external {{(dso_local )?}}global // FIXME: Should this be 'weak_odr global'? Presumably it must be, since we // can discard this global and its initializer (if any), and other TUs are not // permitted to run the initializer for this variable. -// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @const_var_exported = {{(dso_local )?}}constant +// CHECK-DAG: @_ZW6Module19inline_var_exported = linkonce_odr {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module18const_var_exported = {{(dso_local )?}}constant // -// CHECK-DAG: @_ZW6ModuleE25extern_var_module_linkage = external {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module25extern_var_module_linkage = external {{(dso_local )?}}global // FIXME: Should this be 'weak_odr global'? Presumably it must be, since we // can discard this global and its initializer (if any), and other TUs are not // permitted to run the initializer for this variable. -// CHECK-DAG: @_ZW6ModuleE25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = {{(dso_local )?}}global -// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = {{(dso_local )?}}constant +// CHECK-DAG: @_ZW6Module25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module25static_var_module_linkage = {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module24const_var_module_linkage = {{(dso_local )?}}constant // -// CHECK-DAG: @_ZW6ModuleE25unused_var_module_linkage = {{(dso_local )?}}global i32 4 -// CHECK-DAG: @_ZW6ModuleE32unused_static_var_module_linkage = {{(dso_local )?}}global i32 5 -// CHECK-DAG: @_ZW6ModuleE31unused_const_var_module_linkage = {{(dso_local )?}}constant i32 7 +// CHECK-DAG: @_ZW6Module25unused_var_module_linkage = {{(dso_local )?}}global i32 4 +// CHECK-DAG: @_ZW6Module32unused_static_var_module_linkage = {{(dso_local )?}}global i32 5 +// CHECK-DAG: @_ZW6Module31unused_const_var_module_linkage = {{(dso_local )?}}constant i32 7 static void unused_static_global_module() {} static void used_static_global_module() {} @@ -64,7 +64,7 @@ inline int inline_var_exported; const int const_var_exported = 3; - // CHECK: define {{(dso_local )?}}void {{.*}}@_Z18noninline_exportedv + // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module18noninline_exportedv void noninline_exported() { (void)&extern_var_exported; (void)&inline_var_exported; @@ -75,9 +75,9 @@ // FIXME: Ideally we wouldn't emit this as its name is not visible outside this // TU, but this module interface might contain a template that can use this // function so we conservatively emit it for now. -// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE28unused_static_module_linkagev +// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module28unused_static_module_linkagev static void unused_static_module_linkage() {} -// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE26used_static_module_linkagev +// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module26used_static_module_linkagev static void used_static_module_linkage() {} inline void unused_inline_module_linkage() {} @@ -88,10 +88,10 @@ static int static_var_module_linkage; const int const_var_module_linkage = 3; -// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE24noninline_module_linkagev +// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module24noninline_module_linkagev void noninline_module_linkage() { used_static_module_linkage(); - // CHECK: define linkonce_odr {{.*}}@_ZW6ModuleE26used_inline_module_linkagev + // CHECK: define linkonce_odr {{.*}}@_ZW6Module26used_inline_module_linkagev used_inline_module_linkage(); (void)&extern_var_module_linkage; @@ -109,5 +109,5 @@ struct b {}; struct c {}; }; -// CHECK: define {{(dso_local )?}}void @_ZW6ModuleE1fW_0EN1a1bEW_0ENS_1cE( +// CHECK: define {{(dso_local )?}}void @_ZW6Module1fNS_1a1bENS0_1cE( void f(a::b, a::c) {} Index: clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp =================================================================== --- clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp +++ clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp @@ -1,16 +1,16 @@ // RUN: %clang_cc1 -fmodules-ts %S/module.cppm -triple %itanium_abi_triple -emit-module-interface -o %t // RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s --implicit-check-not=unused --implicit-check-not=global_module -// CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global -// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @const_var_exported = available_externally {{(dso_local )?}}constant i32 3 +// CHECK-DAG: @_ZW6Module19extern_var_exported = external {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module19inline_var_exported = linkonce_odr {{(dso_local )?}}global +// CHECK-DAG: @_ZW6Module18const_var_exported = available_externally {{(dso_local )?}}constant i32 3 import Module; void use() { - // CHECK: define linkonce_odr {{.*}}@_Z20used_inline_exportedv + // CHECK: define linkonce_odr {{.*}}@_ZW6Module20used_inline_exportedv used_inline_exported(); - // CHECK: declare {{.*}}@_Z18noninline_exportedv + // CHECK: declare {{.*}}@_ZW6Module18noninline_exportedv noninline_exported(); (void)&extern_var_exported; Index: clang/test/CXX/modules-ts/basic/basic.link/p3.cppm =================================================================== --- clang/test/CXX/modules-ts/basic/basic.link/p3.cppm +++ clang/test/CXX/modules-ts/basic/basic.link/p3.cppm @@ -3,9 +3,9 @@ export module M; -// CHECK-DAG: @_ZW1ME1a ={{.*}} constant i32 1 +// CHECK-DAG: @_ZW1M1a ={{.*}} constant i32 1 const int a = 1; -// CHECK-DAG: @b ={{.*}} constant i32 2 +// CHECK-DAG: @_ZW1M1b ={{.*}} constant i32 2 export const int b = 2; export int f() { return a + b; } Index: clang/test/CXX/modules-ts/codegen-basics.cppm =================================================================== --- clang/test/CXX/modules-ts/codegen-basics.cppm +++ clang/test/CXX/modules-ts/codegen-basics.cppm @@ -4,14 +4,14 @@ export module FooBar; export { - // CHECK-DAG: define{{.*}} i32 @_Z1fv( + // CHECK-DAG: define{{.*}} i32 @_ZW6FooBar1fv( int f() { return 0; } } -// CHECK-DAG: define weak_odr void @_ZW6FooBarE2f2v( +// CHECK-DAG: define weak_odr void @_ZW6FooBar2f2v( inline void f2() {} -// CHECK-DAG: define{{.*}} void @_ZW6FooBarE2f3v( +// CHECK-DAG: define{{.*}} void @_ZW6FooBar2f3v( static void f3() {} export void use_f3() { f3(); } Index: clang/test/CodeGenCXX/Inputs/cxx20-module-impl-1a.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/Inputs/cxx20-module-impl-1a.cpp @@ -0,0 +1,3 @@ +export module Foo; +export void Exported(); +void Module(); Index: clang/test/CodeGenCXX/Inputs/cxx20-module-std-subst-2a.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/Inputs/cxx20-module-std-subst-2a.cpp @@ -0,0 +1,11 @@ +module; +# 5 __FILE__ 1 +namespace std { +template struct allocator {}; +template +class basic_string; +} // namespace std +# 12 "" 2 +export module RenameString; +export template +using str = std::basic_string>; Index: clang/test/CodeGenCXX/cxx20-module-decomp-1.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-decomp-1.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +export module Foo; + +// CHECK-DAG: @_ZW3Foo3ary = +int ary[2]; + +// CHECK-DAG: @_ZW3FooDC1a1bE = +export auto &[a, b] = ary; + +namespace N { +// CHECK-DAG: @_ZN1NW3FooDC1a1bEE = +export auto &[a, b] = ary; +// CHECK-DAG: @_ZN1NW3FooDC1c1dEE = +auto &[c, d] = ary; +// FIXME: We mangle the module name here, as we give this ModuleInternalLinkage +// That's no longer needed. +// CHECK DAG: @_ZN1MDC1e1fEE = +static auto &__attribute__((used))[e, f] = ary; +} // namespace N Index: clang/test/CodeGenCXX/cxx20-module-extern-1.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-extern-1.cppm @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +// module-purview extern "C++" semantics not implemented +// XFAIL: * + +export module FOO; +extern "C++" export class A; +export class B; + +// CHECK-DAG: void @_ZW3FOO3FooP1APNS_1B( +export void Foo (A *, B*) { +} + +extern "C++" { +// CHECK-DAG: void @_Z3BarP1APW3FOO1B( +export void Bar (A *, B*) { +} +} Index: clang/test/CodeGenCXX/cxx20-module-impl-1a.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-impl-1a.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++20 %S/Inputs/cxx20-module-impl-1a.cpp -triple %itanium_abi_triple -emit-module-interface -o %t +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s + +module Foo; + +// CHECK-DAG: @_ZW3Foo8Exportedv( +void Exported() { +} + +// CHECK-DAG: @_ZW3Foo6Modulev( +void Module() { +} + +// CHECK-DAG: @_ZW3Foo7Module2v( +void Module2() { +} + Index: clang/test/CodeGenCXX/cxx20-module-nested-1.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-nested-1.cppm @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++20 -fmodules-ts %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s +module; +# 4 __FILE__ 1 +namespace Outer::Inner { +class X; +// CHECK-DAG: define dso_local void @_ZN5Outer5Inner3BarERNS0_1XE( +void Bar (X &) {} +} // namespace Outer::Inner +# 10 "" 2 +export module FOO; +namespace Outer { +class Y; +namespace Inner { +// CHECK-DAG: define dso_local void @_ZN5Outer5InnerW3FOO2FnERNS0_1XERNS_S1_1YE( +void Fn (X &, Y &){} // #1 +} // namespace Inner +} // namespace Outer Index: clang/test/CodeGenCXX/cxx20-module-nested-2.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-nested-2.cppm @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s +export module FOO; +namespace Outer { +class Y; +class Inner { + class X; + void Fn (X &, Y &); // #2 +}; +// CHECK-DAG: define dso_local void @_ZN5OuterW3FOO5Inner2FnERNS1_1XERNS_S0_1YE( +void Inner::Fn (X &, Y &) {} +} + Index: clang/test/CodeGenCXX/cxx20-module-std-subst-1.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-std-subst-1.cppm @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +module; +# 5 __FILE__ 1 +class Pooh; +class Piglet; +# 8 "" 2 + +export module std; // might happen, you can't say it won't! + +namespace std { +export template class allocator { +// just for testing, not real! +void M (T *); +template U *N (T *); +}; + +template void allocator::M (T *) {} +template template U *allocator::N (T *) { +return nullptr; +} + +// CHECK-DAG: void @_ZNStW3std9allocatorIiE1MEPi( +template void allocator::M (int *); +// CHECK-DAG: @_ZNStW3std9allocatorIiE1NIfEEPT_Pi( +template float *allocator::N (int *); +} + +// CHECK-DAG: @_ZNStW3std9allocatorI4PoohE1MEPS1_( +template void std::allocator::M (Pooh *); +// CHECK-DAG: @_ZNStW3std9allocatorI4PoohE1NI6PigletEEPT_PS1_( +template Piglet *std::allocator::N (Pooh *); Index: clang/test/CodeGenCXX/cxx20-module-std-subst-2b.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-std-subst-2b.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++20 %S/Inputs/cxx20-module-std-subst-2a.cpp -triple %itanium_abi_triple -emit-module-interface -o %t +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s + +export module Foo; +import RenameString; + +namespace std { +template struct char_traits {}; +} // namespace std + +// use Sb mangling, not Ss as this is not global-module std::char_traits +// std::char_traits. +// CHECK-DAG: void @_ZW3Foo1fRSbIcStS_11char_traitsIcESaIcEE( +void f(str> &s) { +} Index: clang/test/CodeGenCXX/cxx20-module-std-subst-2c.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-std-subst-2c.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++20 %S/Inputs/cxx20-module-std-subst-2a.cpp -triple %itanium_abi_triple -emit-module-interface -o %t +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s +module; +# 5 __FILE__ 1 +namespace std { +template struct char_traits {}; +} // namespace std +# 9 "" 2 +export module Bar; +import RenameString; + +// Use Sb as this is global-module std::char_traits +// CHECK-DAG: void @_ZW3Bar1gRSs( +void g(str> &s) { +} Index: clang/test/CodeGenCXX/cxx20-module-sub-1a.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-sub-1a.cppm @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +export module FOO.BAR; +export class A; +namespace Bob { +export class B; + +// CHECK-DAG: void @_ZN3BobW3FOOW3BAR3BarEPS1_1APNS_S1_1BE( +export void Bar (A *, B*) { +} +} + +// CHECK-DAG: void @_ZW3FOOW3BAR3FooPS0_1APN3BobS0_1BE( +export void Foo (A *, Bob::B*) { +} Index: clang/test/CodeGenCXX/cxx20-module-sub-1b.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-sub-1b.cppm @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++20 %S/cxx20-module-sub-1a.cppm -triple %itanium_abi_triple -emit-module-interface -o %t +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -fmodule-file=%t -emit-llvm -o - | FileCheck %s + +export module FOO.BAZ; +import FOO.BAR; + +namespace Bob { + +// CHECK-DAG: void @_ZN3BobW3FOOW3BAZ3FooEPS0_W3BAR1APNS_S2_1BE( +void Foo (A *, B*) { +} +} + +// CHECK-DAG: void @_ZW3FOOW3BAZ3BarPS_W3BAR1APN3BobS1_1BE( +void Bar (A *, Bob::B*) { +} Index: clang/test/CodeGenCXX/cxx20-module-tmpl-1.cppm =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/cxx20-module-tmpl-1.cppm @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++20 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +export module FOO; + +class One; +class Two; + +export template struct TPL +{ +void M (T *); +template void N (T *, U*); +}; + +template +void TPL::M (T *) {} + +template template void TPL::N (T *, U*) {} + +// CHECK-DAG: void @_ZNW3FOO3TPLIS_3OneE1MEPS1_( +template void TPL::M (One *); +// CHECK-DAG: void @_ZNW3FOO3TPLIS_3OneE1NIS_3TwoEEvPS1_PT_( +template void TPL::N (One *, Two *); + +namespace NMS { +class One; +class Two; + +export template struct TPL +{ +void M (T *); +template void N (T *, U*); +}; + +template +void TPL::M (T *) {} + +template template void TPL::N (T *, U*) {} + +// CHECK-DAG: void @_ZN3NMSW3FOO3TPLINS_S0_3OneEE1MEPS2_( +template void TPL::M (One *); +// CHECK-DAG: void @_ZN3NMSW3FOO3TPLINS_S0_3OneEE1NINS_S0_3TwoEEEvPS2_PT_ +template void TPL::N (One *, Two *); +}