forked from OSchip/llvm-project
Implement Itanium name mangling support for C++ Modules TS.
This follows the scheme agreed with Nathan Sidwell, which can be found here: https://gcc.gnu.org/wiki/cxx-modules?action=AttachFile This will be proposed to the itanium-cxx-abi list once we have some experience with how well it works; the ABI for this TS should be considered unstable until it is part of the Itanium C++ ABI. llvm-svn: 312467
This commit is contained in:
parent
ebc1659016
commit
dd8b5337e9
|
@ -372,6 +372,10 @@ public:
|
|||
return hasCachedLinkage();
|
||||
}
|
||||
|
||||
/// Get the module that owns this declaration for linkage purposes.
|
||||
/// There only ever is such a module under the C++ Modules TS.
|
||||
Module *getOwningModuleForLinkage() const;
|
||||
|
||||
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
|
||||
/// the underlying named decl.
|
||||
NamedDecl *getUnderlyingDecl() {
|
||||
|
|
|
@ -733,7 +733,7 @@ public:
|
|||
return getModuleOwnershipKind() != ModuleOwnershipKind::Unowned;
|
||||
}
|
||||
|
||||
/// Get the module that owns this declaration.
|
||||
/// Get the module that owns this declaration (for visibility purposes).
|
||||
Module *getOwningModule() const {
|
||||
return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
|
||||
}
|
||||
|
|
|
@ -68,7 +68,11 @@ public:
|
|||
ModuleMapModule,
|
||||
|
||||
/// \brief This is a C++ Modules TS module interface unit.
|
||||
ModuleInterfaceUnit
|
||||
ModuleInterfaceUnit,
|
||||
|
||||
/// \brief This is a fragment of the global module within some C++ Modules
|
||||
/// TS module.
|
||||
GlobalModuleFragment,
|
||||
};
|
||||
|
||||
/// \brief The kind of this module.
|
||||
|
@ -391,6 +395,15 @@ public:
|
|||
return IsFramework && Parent && Parent->isPartOfFramework();
|
||||
}
|
||||
|
||||
/// Set the parent of this module. This should only be used if the parent
|
||||
/// could not be set during module creation.
|
||||
void setParent(Module *M) {
|
||||
assert(!Parent);
|
||||
Parent = M;
|
||||
Parent->SubModuleIndex[Name] = Parent->SubModules.size();
|
||||
Parent->SubModules.push_back(this);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the full name of this module, including the path from
|
||||
/// its top-level module.
|
||||
/// \param AllowStringLiterals If \c true, components that might not be
|
||||
|
|
|
@ -472,6 +472,14 @@ public:
|
|||
bool IsFramework,
|
||||
bool IsExplicit);
|
||||
|
||||
/// \brief Create a 'global module' for a C++ Modules TS module interface
|
||||
/// unit.
|
||||
///
|
||||
/// We model the global module as a submodule of the module interface unit.
|
||||
/// Unfortunately, we can't create the module interface unit's Module until
|
||||
/// later, because we don't know what it will be called.
|
||||
Module *createGlobalModuleForInterfaceUnit(SourceLocation Loc);
|
||||
|
||||
/// \brief Create a new module for a C++ Modules TS module interface unit.
|
||||
/// The module must not already exist, and will be configured for the current
|
||||
/// compilation.
|
||||
|
@ -479,7 +487,8 @@ public:
|
|||
/// Note that this also sets the current module to the newly-created module.
|
||||
///
|
||||
/// \returns The newly-created module.
|
||||
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
|
||||
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
|
||||
Module *GlobalModule);
|
||||
|
||||
/// \brief Infer the contents of a framework module map from the given
|
||||
/// framework directory.
|
||||
|
|
|
@ -652,7 +652,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|||
// If the declaration of an identifier for an object has file
|
||||
// scope and no storage-class specifier, its linkage is
|
||||
// external.
|
||||
LinkageInfo LV;
|
||||
LinkageInfo LV = getExternalLinkageFor(D);
|
||||
|
||||
if (!hasExplicitVisibilityAlready(computation)) {
|
||||
if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
|
||||
|
@ -1399,6 +1399,30 @@ LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
|
|||
return getLVForDecl(D, usesTypeVisibility(D) ? LVForType : LVForValue);
|
||||
}
|
||||
|
||||
Module *NamedDecl::getOwningModuleForLinkage() const {
|
||||
Module *M = getOwningModule();
|
||||
if (!M)
|
||||
return nullptr;
|
||||
|
||||
switch (M->Kind) {
|
||||
case Module::ModuleMapModule:
|
||||
// Module map modules have no special linkage semantics.
|
||||
return nullptr;
|
||||
|
||||
case Module::ModuleInterfaceUnit:
|
||||
return M;
|
||||
|
||||
case Module::GlobalModuleFragment:
|
||||
// External linkage declarations in the global module have no owning module
|
||||
// for linkage purposes. But internal linkage declarations in the global
|
||||
// module fragment of a particular module are owned by that module for
|
||||
// linkage purposes.
|
||||
return hasExternalFormalLinkage() ? nullptr : M->Parent;
|
||||
}
|
||||
|
||||
llvm_unreachable("unknown module kind");
|
||||
}
|
||||
|
||||
void NamedDecl::printName(raw_ostream &os) const {
|
||||
os << Name;
|
||||
}
|
||||
|
|
|
@ -381,6 +381,7 @@ class CXXNameMangler {
|
|||
AbiTagState AbiTagsRoot;
|
||||
|
||||
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
|
||||
llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions;
|
||||
|
||||
ASTContext &getASTContext() const { return Context.getASTContext(); }
|
||||
|
||||
|
@ -475,6 +476,8 @@ private:
|
|||
|
||||
void mangleNameWithAbiTags(const NamedDecl *ND,
|
||||
const AbiTagList *AdditionalAbiTags);
|
||||
void mangleModuleName(const Module *M);
|
||||
void mangleModuleNamePrefix(StringRef Name);
|
||||
void mangleTemplateName(const TemplateDecl *TD,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs);
|
||||
|
@ -845,9 +848,9 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
|
|||
|
||||
void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
|
||||
const AbiTagList *AdditionalAbiTags) {
|
||||
// <name> ::= <nested-name>
|
||||
// ::= <unscoped-name>
|
||||
// ::= <unscoped-template-name> <template-args>
|
||||
// <name> ::= [<module-name>] <nested-name>
|
||||
// ::= [<module-name>] <unscoped-name>
|
||||
// ::= [<module-name>] <unscoped-template-name> <template-args>
|
||||
// ::= <local-name>
|
||||
//
|
||||
const DeclContext *DC = getEffectiveDeclContext(ND);
|
||||
|
@ -866,6 +869,19 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
|
|||
|
||||
DC = IgnoreLinkageSpecDecls(DC);
|
||||
|
||||
if (isLocalContainerContext(DC)) {
|
||||
mangleLocalName(ND, AdditionalAbiTags);
|
||||
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);
|
||||
|
||||
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
|
||||
// Check if we have a template.
|
||||
const TemplateArgumentList *TemplateArgs = nullptr;
|
||||
|
@ -879,12 +895,42 @@ void CXXNameMangler::mangleNameWithAbiTags(const NamedDecl *ND,
|
|||
return;
|
||||
}
|
||||
|
||||
if (isLocalContainerContext(DC)) {
|
||||
mangleLocalName(ND, AdditionalAbiTags);
|
||||
mangleNestedName(ND, 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
|
||||
//
|
||||
// <module-name> ::= W <unscoped-name>+ E
|
||||
// ::= W <module-subst> <unscoped-name>* E
|
||||
Out << 'W';
|
||||
mangleModuleNamePrefix(M->Name);
|
||||
Out << 'E';
|
||||
}
|
||||
|
||||
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()) {
|
||||
if (It->second < 10)
|
||||
Out << '_' << static_cast<char>('0' + It->second);
|
||||
else
|
||||
Out << 'W' << (It->second - 10) << '_';
|
||||
return;
|
||||
}
|
||||
|
||||
mangleNestedName(ND, DC, AdditionalAbiTags);
|
||||
// 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);
|
||||
|
||||
Out << Parts.second.size() << Parts.second;
|
||||
ModuleSubstitutions.insert({Name, ModuleSubstitutions.size()});
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
|
||||
|
@ -1233,13 +1279,16 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
|
|||
}
|
||||
|
||||
if (II) {
|
||||
// We must avoid conflicts between internally- and externally-
|
||||
// linked variable and function declaration names in the same TU:
|
||||
// Match GCC's naming convention for internal linkage symbols, for
|
||||
// symbols that are not actually visible outside of this TU. GCC
|
||||
// distinguishes between internal and external linkage symbols in
|
||||
// its mangling, to support cases like this that were valid C++ prior
|
||||
// to DR426:
|
||||
//
|
||||
// void test() { extern void foo(); }
|
||||
// static void foo();
|
||||
// This naming convention is the same as that followed by GCC,
|
||||
// though it shouldn't actually matter.
|
||||
if (ND && ND->getFormalLinkage() == InternalLinkage &&
|
||||
!ND->isExternallyVisible() &&
|
||||
getEffectiveDeclContext(ND)->isFileContext())
|
||||
Out << 'L';
|
||||
|
||||
|
|
|
@ -746,8 +746,16 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
|
|||
return std::make_pair(Result, true);
|
||||
}
|
||||
|
||||
Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
|
||||
auto *Result = new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
|
||||
/*IsExplicit*/ true, NumCreatedModules++);
|
||||
Result->Kind = Module::GlobalModuleFragment;
|
||||
return Result;
|
||||
}
|
||||
|
||||
Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
|
||||
StringRef Name) {
|
||||
StringRef Name,
|
||||
Module *GlobalModule) {
|
||||
assert(LangOpts.CurrentModule == Name && "module name mismatch");
|
||||
assert(!Modules[Name] && "redefining existing module");
|
||||
|
||||
|
@ -757,6 +765,9 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
|
|||
Result->Kind = Module::ModuleInterfaceUnit;
|
||||
Modules[Name] = SourceModule = Result;
|
||||
|
||||
// Reparent the current global module fragment as a submodule of this module.
|
||||
GlobalModule->setParent(Result);
|
||||
|
||||
// Mark the main source file as being within the newly-created module so that
|
||||
// declarations and macros are properly visibility-restricted to it.
|
||||
auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
|
||||
|
|
|
@ -766,10 +766,24 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() {
|
|||
/// declarations.
|
||||
void Sema::ActOnStartOfTranslationUnit() {
|
||||
if (getLangOpts().ModulesTS) {
|
||||
SourceLocation StartOfTU =
|
||||
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
|
||||
|
||||
// We start in the global module; all those declarations are implicitly
|
||||
// module-private (though they do not have module linkage).
|
||||
Context.getTranslationUnitDecl()->setModuleOwnershipKind(
|
||||
Decl::ModuleOwnershipKind::ModulePrivate);
|
||||
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
|
||||
auto *GlobalModule = Map.createGlobalModuleForInterfaceUnit(StartOfTU);
|
||||
assert(GlobalModule && "module creation should not fail");
|
||||
|
||||
// Enter the scope of the global module.
|
||||
ModuleScopes.push_back({});
|
||||
ModuleScopes.back().Module = GlobalModule;
|
||||
VisibleModules.setVisible(GlobalModule, StartOfTU);
|
||||
|
||||
// All declarations created from now on are owned by the global module.
|
||||
auto *TU = Context.getTranslationUnitDecl();
|
||||
TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);
|
||||
TU->setLocalOwningModule(GlobalModule);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16052,6 +16052,9 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
|
|||
SourceLocation ModuleLoc,
|
||||
ModuleDeclKind MDK,
|
||||
ModuleIdPath Path) {
|
||||
assert(getLangOpts().ModulesTS &&
|
||||
"should only have module decl in modules TS");
|
||||
|
||||
// A module implementation unit requires that we are not compiling a module
|
||||
// of any kind. A module interface unit requires that we are not compiling a
|
||||
// module map.
|
||||
|
@ -16104,10 +16107,10 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
|
|||
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
|
||||
Module *Mod;
|
||||
|
||||
assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
|
||||
|
||||
switch (MDK) {
|
||||
case ModuleDeclKind::Module: {
|
||||
// FIXME: Check we're not in a submodule.
|
||||
|
||||
// We can't have parsed or imported a definition of this module or parsed a
|
||||
// module map defining it already.
|
||||
if (auto *M = Map.findModule(ModuleName)) {
|
||||
|
@ -16121,7 +16124,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
|
|||
}
|
||||
|
||||
// Create a Module for the module that we're defining.
|
||||
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
|
||||
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
|
||||
ModuleScopes.front().Module);
|
||||
assert(Mod && "module creation should not fail");
|
||||
break;
|
||||
}
|
||||
|
@ -16140,16 +16144,16 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
|
|||
break;
|
||||
}
|
||||
|
||||
// Enter the semantic scope of the module.
|
||||
ModuleScopes.push_back({});
|
||||
// Switch from the global module to the named module.
|
||||
ModuleScopes.back().Module = Mod;
|
||||
ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
|
||||
VisibleModules.setVisible(Mod, ModuleLoc);
|
||||
|
||||
// From now on, we have an owning module for all declarations we see.
|
||||
// However, those declarations are module-private unless explicitly
|
||||
// exported.
|
||||
Context.getTranslationUnitDecl()->setLocalOwningModule(Mod);
|
||||
auto *TU = Context.getTranslationUnitDecl();
|
||||
TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
|
||||
TU->setLocalOwningModule(Mod);
|
||||
|
||||
// FIXME: Create a ModuleDecl.
|
||||
return nullptr;
|
||||
|
@ -16327,7 +16331,7 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
|
|||
// C++ Modules TS draft:
|
||||
// An export-declaration shall appear in the purview of a module other than
|
||||
// the global module.
|
||||
if (ModuleScopes.empty() || !ModuleScopes.back().Module ||
|
||||
if (ModuleScopes.empty() ||
|
||||
ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)
|
||||
Diag(ExportLoc, diag::err_export_not_in_module_interface);
|
||||
|
||||
|
|
|
@ -4871,7 +4871,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
|||
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
|
||||
bool First = true;
|
||||
Module *CurrentModule = nullptr;
|
||||
Module::ModuleKind ModuleKind = Module::ModuleMapModule;
|
||||
RecordData Record;
|
||||
while (true) {
|
||||
llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
|
||||
|
@ -4919,6 +4918,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
|||
unsigned Idx = 0;
|
||||
SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]);
|
||||
SubmoduleID Parent = getGlobalSubmoduleID(F, Record[Idx++]);
|
||||
Module::ModuleKind Kind = (Module::ModuleKind)Record[Idx++];
|
||||
bool IsFramework = Record[Idx++];
|
||||
bool IsExplicit = Record[Idx++];
|
||||
bool IsSystem = Record[Idx++];
|
||||
|
@ -4965,7 +4965,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
|||
CurrentModule->PresumedModuleMapFile = F.ModuleMapPath;
|
||||
}
|
||||
|
||||
CurrentModule->Kind = ModuleKind;
|
||||
CurrentModule->Kind = Kind;
|
||||
CurrentModule->Signature = F.Signature;
|
||||
CurrentModule->IsFromModuleFile = true;
|
||||
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
|
||||
|
@ -5064,7 +5064,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
|||
|
||||
SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
|
||||
}
|
||||
ModuleKind = (Module::ModuleKind)Record[2];
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -2716,6 +2716,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Kind
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
|
||||
|
@ -2793,8 +2794,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
// Write the submodule metadata block.
|
||||
RecordData::value_type Record[] = {
|
||||
getNumberOfModules(WritingModule),
|
||||
FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS,
|
||||
(unsigned)WritingModule->Kind};
|
||||
FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS};
|
||||
Stream.EmitRecord(SUBMODULE_METADATA, Record);
|
||||
|
||||
// Write all of the submodules.
|
||||
|
@ -2816,6 +2816,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
RecordData::value_type Record[] = {SUBMODULE_DEFINITION,
|
||||
ID,
|
||||
ParentID,
|
||||
Mod->Kind,
|
||||
Mod->IsFramework,
|
||||
Mod->IsExplicit,
|
||||
Mod->IsSystem,
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
// CHECK-DAG: @extern_var_exported = external global
|
||||
// FIXME: Should this be 'external global'?
|
||||
// CHECK-DAG: @inline_var_exported = linkonce_odr global
|
||||
// CHECK-DAG: @_ZL19static_var_exported = external global
|
||||
// CHECK-DAG: @_ZW6ModuleE19static_var_exported = external global
|
||||
// CHECK-DAG: @const_var_exported = external constant
|
||||
//
|
||||
// FIXME: The module name should be mangled into all of these.
|
||||
// CHECK-DAG: @extern_var_module_linkage = external global
|
||||
// FIXME: Should this be 'external global'?
|
||||
// CHECK-DAG: @inline_var_module_linkage = linkonce_odr global
|
||||
// CHECK-DAG: @_ZL25static_var_module_linkage = external global
|
||||
// CHECK-DAG: @_ZL24const_var_module_linkage = external constant
|
||||
// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = external global
|
||||
// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = external constant
|
||||
|
||||
module Module;
|
||||
|
||||
|
@ -28,15 +28,13 @@ void use() {
|
|||
(void)&const_var_exported;
|
||||
|
||||
// FIXME: This symbol should not be visible here.
|
||||
// CHECK: declare {{.*}}@_ZL26used_static_module_linkagev
|
||||
// CHECK: declare {{.*}}@_ZW6ModuleE26used_static_module_linkagev
|
||||
used_static_module_linkage();
|
||||
|
||||
// FIXME: The module name should be mangled into the name of this function.
|
||||
// CHECK: define linkonce_odr {{.*}}@_Z26used_inline_module_linkagev
|
||||
// CHECK: define linkonce_odr {{.*}}@_ZW6ModuleE26used_inline_module_linkagev
|
||||
used_inline_module_linkage();
|
||||
|
||||
// FIXME: The module name should be mangled into the name of this function.
|
||||
// CHECK: declare {{.*}}@_Z24noninline_module_linkagev
|
||||
// CHECK: declare {{.*}}@_ZW6ModuleE24noninline_module_linkagev
|
||||
noninline_module_linkage();
|
||||
|
||||
(void)&extern_var_module_linkage;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// 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 global
|
||||
// CHECK-DAG: @_ZL19static_var_exported = global
|
||||
// CHECK-DAG: @_ZW6ModuleE19static_var_exported = global
|
||||
// CHECK-DAG: @const_var_exported = constant
|
||||
//
|
||||
// FIXME: The module name should be mangled into all of these.
|
||||
|
@ -20,8 +20,8 @@
|
|||
// 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_module_linkage = linkonce_odr global
|
||||
// CHECK-DAG: @_ZL25static_var_module_linkage = global
|
||||
// CHECK-DAG: @_ZL24const_var_module_linkage = constant
|
||||
// CHECK-DAG: @_ZW6ModuleE25static_var_module_linkage = global
|
||||
// CHECK-DAG: @_ZW6ModuleE24const_var_module_linkage = constant
|
||||
|
||||
static void unused_static_global_module() {}
|
||||
static void used_static_global_module() {}
|
||||
|
@ -57,9 +57,9 @@ export module Module;
|
|||
export {
|
||||
// FIXME: These should be ill-formed: you can't export an internal linkage
|
||||
// symbol, per [dcl.module.interface]p2.
|
||||
// CHECK: define void {{.*}}@_ZL22unused_static_exportedv
|
||||
// CHECK: define void {{.*}}@_ZW6ModuleE22unused_static_exportedv
|
||||
static void unused_static_exported() {}
|
||||
// CHECK: define void {{.*}}@_ZL20used_static_exportedv
|
||||
// CHECK: define void {{.*}}@_ZW6ModuleE20used_static_exportedv
|
||||
static void used_static_exported() {}
|
||||
|
||||
inline void unused_inline_exported() {}
|
||||
|
@ -88,11 +88,9 @@ export {
|
|||
// 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.
|
||||
// FIXME: The module name should be mangled into the name of this function.
|
||||
// CHECK: define void {{.*}}@_ZL28unused_static_module_linkagev
|
||||
// CHECK: define void {{.*}}@_ZW6ModuleE28unused_static_module_linkagev
|
||||
static void unused_static_module_linkage() {}
|
||||
// FIXME: The module name should be mangled into the name of this function.
|
||||
// CHECK: define void {{.*}}@_ZL26used_static_module_linkagev
|
||||
// CHECK: define void {{.*}}@_ZW6ModuleE26used_static_module_linkagev
|
||||
static void used_static_module_linkage() {}
|
||||
|
||||
inline void unused_inline_module_linkage() {}
|
||||
|
@ -103,12 +101,10 @@ inline int inline_var_module_linkage;
|
|||
static int static_var_module_linkage;
|
||||
const int const_var_module_linkage = 3;
|
||||
|
||||
// FIXME: The module name should be mangled into the name of this function.
|
||||
// CHECK: define void {{.*}}@_Z24noninline_module_linkagev
|
||||
// CHECK: define void {{.*}}@_ZW6ModuleE24noninline_module_linkagev
|
||||
void noninline_module_linkage() {
|
||||
used_static_module_linkage();
|
||||
// FIXME: The module name should be mangled into the name of this function.
|
||||
// CHECK: define linkonce_odr {{.*}}@_Z26used_inline_module_linkagev
|
||||
// CHECK: define linkonce_odr {{.*}}@_ZW6ModuleE26used_inline_module_linkagev
|
||||
used_inline_module_linkage();
|
||||
|
||||
(void)&extern_var_module_linkage;
|
||||
|
@ -116,3 +112,10 @@ void noninline_module_linkage() {
|
|||
(void)&static_var_module_linkage;
|
||||
(void)&const_var_module_linkage;
|
||||
}
|
||||
|
||||
struct a {
|
||||
struct b {};
|
||||
struct c {};
|
||||
};
|
||||
// CHECK: define void @_ZW6ModuleE1fW_0EN1a1bEW_0ENS_1cE(
|
||||
void f(a::b, a::c) {}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// FIXME: Should this be 'external global'?
|
||||
// CHECK-DAG: @inline_var_exported = linkonce_odr global
|
||||
// FIXME: These should be 'extern global' and 'extern constant'.
|
||||
// CHECK-DAG: @_ZL19static_var_exported = global
|
||||
// CHECK-DAG: @_ZW6ModuleE19static_var_exported = global
|
||||
// CHECK-DAG: @const_var_exported = constant
|
||||
|
||||
import Module;
|
||||
|
|
|
@ -4,20 +4,18 @@
|
|||
export module FooBar;
|
||||
|
||||
export {
|
||||
// CHECK-LABEL: define i32 @_Z1fv(
|
||||
// CHECK-DAG: define i32 @_Z1fv(
|
||||
int f() { return 0; }
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define weak_odr void @_Z2f2v(
|
||||
// CHECK-DAG: define weak_odr void @_ZW6FooBarE2f2v(
|
||||
inline void f2() { }
|
||||
|
||||
// CHECK-DAG: define void @_ZW6FooBarE2f3v(
|
||||
static void f3() {}
|
||||
export void use_f3() { f3(); }
|
||||
|
||||
// FIXME: Emit global variables and their initializers with this TU.
|
||||
// Emit an initialization function that other TUs can call, with guard variable.
|
||||
|
||||
// FIXME: Mangle non-exported symbols so they don't collide with
|
||||
// non-exported symbols from other modules?
|
||||
|
||||
// FIXME: Formally-internal-linkage symbols that are used from an exported
|
||||
// symbol need a mangled name and external linkage.
|
||||
// Emit an initialization function that other TUs can call, with guard variable?
|
||||
|
||||
// FIXME: const-qualified variables don't have implicit internal linkage when owned by a module.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=0
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=1
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -DTEST=2
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -Dfoo=bar -DTEST=3
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.0.pcm -verify -DTEST=0
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.1.pcm -verify -DTEST=1
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.0.pcm -o %t.2.pcm -verify -DTEST=2
|
||||
// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.0.pcm -o %t.3.pcm -verify -Dfoo=bar -DTEST=3
|
||||
|
||||
#if TEST == 0
|
||||
// expected-no-diagnostics
|
||||
|
@ -21,7 +21,7 @@ static int m;
|
|||
// expected-note-re@modules-ts.cppm:1 {{'{{.*}}modules-ts.cppm' included multiple times, additional include site in header from module 'foo'}}
|
||||
#endif
|
||||
int n;
|
||||
#if TEST >= 2
|
||||
#if TEST == 2
|
||||
// expected-error@-2 {{redefinition of '}}
|
||||
// expected-note@-3 {{unguarded header; consider using #ifdef guards or #pragma once}}
|
||||
// FIXME: We should drop the "header from" in this diagnostic.
|
||||
|
@ -60,7 +60,7 @@ int use_b = b;
|
|||
int use_n = n; // FIXME: this should not be visible, because it is not exported
|
||||
|
||||
extern int n;
|
||||
static_assert(&n == p); // FIXME: these are not the same entity
|
||||
static_assert(&n != p);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue