void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override;
- void mangleModuleInitializer(const Module *Module, raw_ostream &) override;
-
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
void mangleType(QualType T);
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
void mangleLambdaSig(const CXXRecordDecl *Lambda);
- void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
private:
void mangleNameWithAbiTags(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
- void mangleModuleName(const NamedDecl *ND);
+ void mangleModuleName(const Module *M);
+ void mangleModuleNamePrefix(StringRef Name);
void mangleTemplateName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
- void mangleUnqualifiedName(GlobalDecl GD, const DeclContext *DC,
+ void mangleUnqualifiedName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
- mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName(), DC,
- UnknownArity, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, cast<NamedDecl>(GD.getDecl())->getDeclName(), UnknownArity,
+ AdditionalAbiTags);
}
void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name,
- const DeclContext *DC, unsigned KnownArity,
+ unsigned KnownArity,
const AbiTagList *AdditionalAbiTags);
- void mangleUnscopedName(GlobalDecl GD, const DeclContext *DC,
+ void mangleUnscopedName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
- void mangleUnscopedTemplateName(GlobalDecl GD, const DeclContext *DC,
+ void mangleUnscopedTemplateName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags);
void mangleSourceName(const IdentifierInfo *II);
void mangleRegCallName(const IdentifierInfo *II);
if (VD->isExternC())
return false;
- // Variables at global scope are not mangled unless they have internal
- // linkage or are specializations or are attached to a named module.
+ // Variables at global scope with non-internal linkage are not mangled.
const DeclContext *DC = getEffectiveDeclContext(D);
// Check for extern variable declared locally.
if (DC->isFunctionOrMethod() && D->hasLinkage())
DC = getEffectiveParentContext(DC);
if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage &&
!CXXNameMangler::shouldHaveAbiTags(*this, VD) &&
- !isa<VarTemplateSpecializationDecl>(VD) &&
- !VD->getOwningModuleForLinkage())
+ !isa<VarTemplateSpecializationDecl>(VD))
return false;
}
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)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
- mangleUnscopedTemplateName(TD, DC, AdditionalAbiTags);
+ mangleUnscopedTemplateName(TD, AdditionalAbiTags);
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
return;
}
- mangleUnscopedName(GD, DC, AdditionalAbiTags);
+ mangleUnscopedName(GD, AdditionalAbiTags);
return;
}
mangleNestedName(GD, DC, AdditionalAbiTags);
}
-void CXXNameMangler::mangleModuleName(const NamedDecl *ND) {
- if (ND->isExternallyVisible())
- if (Module *M = ND->getOwningModuleForLinkage())
- mangleModuleNamePrefix(M->getPrimaryModuleInterfaceName());
+void CXXNameMangler::mangleModuleName(const Module *M) {
+ // Implement the C++ Modules TS name mangling proposal; see
+ // https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile
+ //
+ // <module-name> ::= W <unscoped-name>+ E
+ // ::= W <module-subst> <unscoped-name>* E
+ Out << 'W';
+ mangleModuleNamePrefix(M->Name);
+ Out << 'E';
}
-// <module-name> ::= <module-subname>
-// ::= <module-name> <module-subname>
-// ::= <substitution>
-// <module-subname> ::= W <source-name>
-// ::= W P <source-name>
-void CXXNameMangler::mangleModuleNamePrefix(StringRef Name, bool IsPartition) {
- // <substitution> ::= S <seq-id> _
+void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
+ // <module-subst> ::= _ <seq-id> # 0 < seq-id < 10
+ // ::= W <seq-id - 10> _ # otherwise
auto It = ModuleSubstitutions.find(Name);
if (It != ModuleSubstitutions.end()) {
- Out << 'S';
- mangleSeqID(It->second);
+ if (It->second < 10)
+ Out << '_' << static_cast<char>('0' + It->second);
+ else
+ Out << 'W' << (It->second - 10) << '_';
return;
}
auto Parts = Name.rsplit('.');
if (Parts.second.empty())
Parts.second = Parts.first;
- else {
- mangleModuleNamePrefix(Parts.first, IsPartition);
- IsPartition = false;
- }
+ else
+ mangleModuleNamePrefix(Parts.first);
- Out << 'W';
- if (IsPartition)
- Out << 'P';
Out << Parts.second.size() << Parts.second;
- ModuleSubstitutions.insert({Name, SeqID++});
+ ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()});
}
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
const DeclContext *DC = Context.getEffectiveDeclContext(TD);
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
- mangleUnscopedTemplateName(TD, DC, nullptr);
+ mangleUnscopedTemplateName(TD, nullptr);
mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs);
} else {
mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
}
}
-void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC,
+void CXXNameMangler::mangleUnscopedName(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
+ const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
- assert(!isa<LinkageSpecDecl>(DC) && "unskipped LinkageSpecDecl");
- if (isStdNamespace(DC))
+ if (isStdNamespace(Context.getEffectiveDeclContext(ND)))
Out << "St";
- mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
}
void CXXNameMangler::mangleUnscopedTemplateName(
- GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) {
+ GlobalDecl GD, const AbiTagList *AdditionalAbiTags) {
const TemplateDecl *ND = cast<TemplateDecl>(GD.getDecl());
// <unscoped-template-name> ::= <unscoped-name>
// ::= <substitution>
"template template param cannot have abi tags");
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
} else if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND)) {
- mangleUnscopedName(GD, DC, AdditionalAbiTags);
+ mangleUnscopedName(GD, AdditionalAbiTags);
} else {
- mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), DC,
- AdditionalAbiTags);
+ mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), AdditionalAbiTags);
}
addSubstitution(ND);
mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs);
}
-void CXXNameMangler::mangleUnqualifiedName(
- GlobalDecl GD, DeclarationName Name, const DeclContext *DC,
- unsigned KnownArity, const AbiTagList *AdditionalAbiTags) {
+void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
+ DeclarationName Name,
+ unsigned KnownArity,
+ const AbiTagList *AdditionalAbiTags) {
const NamedDecl *ND = cast_or_null<NamedDecl>(GD.getDecl());
- // <unqualified-name> ::= [<module-name>] <operator-name>
- // ::= <ctor-dtor-name>
- // ::= [<module-name>] <source-name>
- // ::= [<module-name>] DC <source-name>* E
-
- if (ND && DC && DC->isFileContext())
- mangleModuleName(ND);
-
unsigned Arity = KnownArity;
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
const IdentifierInfo *II = Name.getAsIdentifierInfo();
//
// <unqualified-name> ::= DC <source-name>* 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())
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
} else {
manglePrefix(DC, NoFunction);
- mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
}
Out << 'E';
Out << 'N';
mangleClosurePrefix(PrefixND);
- mangleUnqualifiedName(GD, nullptr, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
Out << 'E';
}
// Mangle the name relative to the closest enclosing function.
// equality ok because RD derived from ND above
if (D == RD) {
- mangleUnqualifiedName(RD, DC, AdditionalAbiTags);
+ mangleUnqualifiedName(RD, AdditionalAbiTags);
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
if (const NamedDecl *PrefixND = getClosurePrefix(BD))
mangleClosurePrefix(PrefixND, true /*NoFunction*/);
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
mangleUnqualifiedBlock(BD);
} else {
- mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
}
if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) {
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
} else if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
mangleClosurePrefix(PrefixND, NoFunction);
- mangleUnqualifiedName(ND, nullptr, nullptr);
+ mangleUnqualifiedName(ND, nullptr);
} else {
- const DeclContext *DC = Context.getEffectiveDeclContext(ND);
- manglePrefix(DC, NoFunction);
- mangleUnqualifiedName(ND, DC, nullptr);
+ manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
+ mangleUnqualifiedName(ND, nullptr);
}
addSubstitution(ND);
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
} else {
- const DeclContext *DC = Context.getEffectiveDeclContext(ND);
- manglePrefix(DC, NoFunction);
+ manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
- mangleUnqualifiedName(GD, DC, nullptr);
+ mangleUnqualifiedName(GD, nullptr);
else
- mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), DC,
- nullptr);
+ mangleUnqualifiedName(GD.getWithDecl(ND->getTemplatedDecl()), nullptr);
}
addSubstitution(ND);
mangleTemplatePrefix(TD, NoFunction);
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
} else {
- const auto *DC = Context.getEffectiveDeclContext(ND);
- manglePrefix(DC, NoFunction);
- mangleUnqualifiedName(ND, DC, nullptr);
+ manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
+ mangleUnqualifiedName(ND, nullptr);
}
Out << 'M';
if (TemplateArgs[0].getAsType() != A)
return false;
- if (SD->getSpecializedTemplate()->getOwningModuleForLinkage())
- return false;
-
return true;
}
!isSpecializedAs(TemplateArgs[2].getAsType(), "allocator", A))
return false;
- if (SD->getSpecializedTemplate()->getOwningModuleForLinkage())
- return false;
-
return true;
}
if (!isStdNamespace(Context.getEffectiveDeclContext(TD)))
return false;
- if (TD->getOwningModuleForLinkage())
- return false;
-
// <substitution> ::= Sa # ::std::allocator
if (TD->getIdentifier()->isStr("allocator")) {
Out << "Sa";
if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
return false;
- if (SD->getSpecializedTemplate()->getOwningModuleForLinkage())
- return false;
-
// <substitution> ::= Ss # ::std::basic_string<char,
// ::std::char_traits<char>,
// ::std::allocator<char> >
Mangler.mangleLambdaSig(Lambda);
}
-void ItaniumMangleContextImpl::mangleModuleInitializer(const Module *M,
- raw_ostream &Out) {
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZGI";
- Mangler.mangleModuleNamePrefix(M->getPrimaryModuleInterfaceName());
- if (M->isModulePartition()) {
- auto Partition = M->Name.find(':');
- Mangler.mangleModuleNamePrefix(
- StringRef(&M->Name[Partition + 1], M->Name.size() - Partition - 1),
- /*IsPartition*/ true);
- }
-}
-
ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
DiagnosticsEngine &Diags) {
return new ItaniumMangleContextImpl(
// CHECK-DAG: @_ZL23const_var_global_module = internal constant
//
// For ABI compatibility, these symbols do not include the module name.
-// CHECK-DAG: @_ZW6Module19extern_var_exported = external {{(dso_local )?}}global
+// CHECK-DAG: @extern_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: @_ZW6Module19inline_var_exported = linkonce_odr {{(dso_local )?}}global
-// CHECK-DAG: @_ZW6Module18const_var_exported = {{(dso_local )?}}constant
+// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @const_var_exported = {{(dso_local )?}}constant
//
-// CHECK-DAG: @_ZW6Module25extern_var_module_linkage = external {{(dso_local )?}}global
+// CHECK-DAG: @_ZW6ModuleE25extern_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: @_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: @_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: @_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
+// 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
static void unused_static_global_module() {}
static void used_static_global_module() {}
inline int inline_var_exported;
const int const_var_exported = 3;
- // CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module18noninline_exportedv
+ // CHECK: define {{(dso_local )?}}void {{.*}}@_Z18noninline_exportedv
void noninline_exported() {
(void)&extern_var_exported;
(void)&inline_var_exported;
// 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 {{.*}}@_ZW6Module28unused_static_module_linkagev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE28unused_static_module_linkagev
static void unused_static_module_linkage() {}
-// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module26used_static_module_linkagev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE26used_static_module_linkagev
static void used_static_module_linkage() {}
inline void unused_inline_module_linkage() {}
static int static_var_module_linkage;
const int const_var_module_linkage = 3;
-// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6Module24noninline_module_linkagev
+// CHECK: define {{(dso_local )?}}void {{.*}}@_ZW6ModuleE24noninline_module_linkagev
void noninline_module_linkage() {
used_static_module_linkage();
- // CHECK: define linkonce_odr {{.*}}@_ZW6Module26used_inline_module_linkagev
+ // CHECK: define linkonce_odr {{.*}}@_ZW6ModuleE26used_inline_module_linkagev
used_inline_module_linkage();
(void)&extern_var_module_linkage;
struct b {};
struct c {};
};
-// CHECK: define {{(dso_local )?}}void @_ZW6Module1fNS_1a1bENS0_1cE(
+// CHECK: define {{(dso_local )?}}void @_ZW6ModuleE1fW_0EN1a1bEW_0ENS_1cE(
void f(a::b, a::c) {}