Skip to content

Commit 1283e98

Browse files
committed
[modules ts] Basic for module linkage.
In addition to the formal linkage rules, the Modules TS includes cases where internal-linkage symbols within a module interface unit can be referenced from outside the module via exported inline functions / templates. We give such declarations "module-internal linkage", which is formally internal linkage, but results in an externally-visible symbol. llvm-svn: 307434
1 parent 77235d3 commit 1283e98

File tree

9 files changed

+198
-27
lines changed

9 files changed

+198
-27
lines changed

clang/include/clang/Basic/Linkage.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ enum Linkage : unsigned char {
4545
/// translation units because of types defined in a inline function.
4646
VisibleNoLinkage,
4747

48+
/// \brief Internal linkage according to the Modules TS, but can be referred
49+
/// to from other translation units indirectly through inline functions and
50+
/// templates in the module interface.
51+
ModuleInternalLinkage,
52+
53+
/// \brief Module linkage, which indicates that the entity can be referred
54+
/// to from other translation units within the same module, and indirectly
55+
/// from arbitrary other translation units through inline functions and
56+
/// templates in the module interface.
57+
ModuleLinkage,
58+
4859
/// \brief External linkage, which indicates that the entity can
4960
/// be referred to from other translation units.
5061
ExternalLinkage
@@ -74,15 +85,20 @@ inline bool isDiscardableGVALinkage(GVALinkage L) {
7485
}
7586

7687
inline bool isExternallyVisible(Linkage L) {
77-
return L == ExternalLinkage || L == VisibleNoLinkage;
88+
return L >= VisibleNoLinkage;
7889
}
7990

8091
inline Linkage getFormalLinkage(Linkage L) {
81-
if (L == UniqueExternalLinkage)
92+
switch (L) {
93+
case UniqueExternalLinkage:
8294
return ExternalLinkage;
83-
if (L == VisibleNoLinkage)
95+
case VisibleNoLinkage:
8496
return NoLinkage;
85-
return L;
97+
case ModuleInternalLinkage:
98+
return InternalLinkage;
99+
default:
100+
return L;
101+
}
86102
}
87103

88104
inline bool isExternalFormalLinkage(Linkage L) {

clang/lib/AST/Decl.cpp

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,44 @@ static bool isSingleLineLanguageLinkage(const Decl &D) {
573573
return false;
574574
}
575575

576+
static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) {
577+
switch (D->getModuleOwnershipKind()) {
578+
case Decl::ModuleOwnershipKind::Unowned:
579+
case Decl::ModuleOwnershipKind::ModulePrivate:
580+
return false;
581+
case Decl::ModuleOwnershipKind::Visible:
582+
case Decl::ModuleOwnershipKind::VisibleWhenImported:
583+
if (auto *M = D->getOwningModule())
584+
return M->Kind == Module::ModuleInterfaceUnit;
585+
}
586+
llvm_unreachable("unexpected module ownership kind");
587+
}
588+
589+
static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
590+
// Internal linkage declarations within a module interface unit are modeled
591+
// as "module-internal linkage", which means that they have internal linkage
592+
// formally but can be indirectly accessed from outside the module via inline
593+
// functions and templates defined within the module.
594+
if (auto *M = D->getOwningModule())
595+
if (M->Kind == Module::ModuleInterfaceUnit)
596+
return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);
597+
598+
return LinkageInfo::internal();
599+
}
600+
601+
static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
602+
// C++ Modules TS [basic.link]/6.8:
603+
// - A name declared at namespace scope that does not have internal linkage
604+
// by the previous rules and that is introduced by a non-exported
605+
// declaration has module linkage.
606+
if (auto *M = D->getOwningModule())
607+
if (M->Kind == Module::ModuleInterfaceUnit)
608+
if (!isExportedFromModuleIntefaceUnit(D))
609+
return LinkageInfo(ModuleLinkage, DefaultVisibility, false);
610+
611+
return LinkageInfo::external();
612+
}
613+
576614
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
577615
LVComputationKind computation) {
578616
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
@@ -588,24 +626,26 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
588626
if (const auto *Var = dyn_cast<VarDecl>(D)) {
589627
// Explicitly declared static.
590628
if (Var->getStorageClass() == SC_Static)
591-
return LinkageInfo::internal();
629+
return getInternalLinkageFor(Var);
592630

593631
// - a non-inline, non-volatile object or reference that is explicitly
594632
// declared const or constexpr and neither explicitly declared extern
595633
// nor previously declared to have external linkage; or (there is no
596634
// equivalent in C99)
635+
// The C++ modules TS adds "non-exported" to this list.
597636
if (Context.getLangOpts().CPlusPlus &&
598637
Var->getType().isConstQualified() &&
599638
!Var->getType().isVolatileQualified() &&
600-
!Var->isInline()) {
639+
!Var->isInline() &&
640+
!isExportedFromModuleIntefaceUnit(Var)) {
601641
const VarDecl *PrevVar = Var->getPreviousDecl();
602642
if (PrevVar)
603643
return getLVForDecl(PrevVar, computation);
604644

605645
if (Var->getStorageClass() != SC_Extern &&
606646
Var->getStorageClass() != SC_PrivateExtern &&
607647
!isSingleLineLanguageLinkage(*Var))
608-
return LinkageInfo::internal();
648+
return getInternalLinkageFor(Var);
609649
}
610650

611651
for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
@@ -615,7 +655,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
615655
return PrevVar->getLinkageAndVisibility();
616656
// Explicitly declared static.
617657
if (PrevVar->getStorageClass() == SC_Static)
618-
return LinkageInfo::internal();
658+
return getInternalLinkageFor(Var);
619659
}
620660
} else if (const FunctionDecl *Function = D->getAsFunction()) {
621661
// C++ [temp]p4:
@@ -624,7 +664,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
624664

625665
// Explicitly declared static.
626666
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
627-
return LinkageInfo(InternalLinkage, DefaultVisibility, false);
667+
return getInternalLinkageFor(Function);
628668
} else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
629669
// - a data member of an anonymous union.
630670
const VarDecl *VD = IFD->getVarDecl();
@@ -637,7 +677,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
637677
const auto *Var = dyn_cast<VarDecl>(D);
638678
const auto *Func = dyn_cast<FunctionDecl>(D);
639679
// FIXME: In C++11 onwards, anonymous namespaces should give decls
640-
// within them internal linkage, not unique external linkage.
680+
// within them (including those inside extern "C" contexts) internal
681+
// linkage, not unique external linkage:
682+
//
683+
// C++11 [basic.link]p4:
684+
// An unnamed namespace or a namespace declared directly or indirectly
685+
// within an unnamed namespace has internal linkage.
641686
if ((!Var || !isFirstInExternCContext(Var)) &&
642687
(!Func || !isFirstInExternCContext(Func)))
643688
return LinkageInfo::uniqueExternal();
@@ -718,7 +763,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
718763
// because of this, but unique-external linkage suits us.
719764
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
720765
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
721-
if (TypeLV.getLinkage() != ExternalLinkage)
766+
if (TypeLV.getLinkage() != ExternalLinkage &&
767+
TypeLV.getLinkage() != ModuleLinkage)
722768
return LinkageInfo::uniqueExternal();
723769
if (!LV.isVisibilityExplicit())
724770
LV.mergeVisibility(TypeLV);
@@ -816,7 +862,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
816862

817863
// - a namespace (7.3), unless it is declared within an unnamed
818864
// namespace.
819-
} else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
865+
//
866+
// We handled names in anonymous namespaces above.
867+
} else if (isa<NamespaceDecl>(D)) {
820868
return LV;
821869

822870
// By extension, we assign external linkage to Objective-C
@@ -1125,6 +1173,8 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
11251173
if (const auto *ND = dyn_cast<NamedDecl>(DC))
11261174
return getLVForDecl(ND, computation);
11271175

1176+
// FIXME: We have a closure at TU scope with no context declaration. This
1177+
// should probably have no linkage.
11281178
return LinkageInfo::external();
11291179
}
11301180

@@ -1137,7 +1187,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
11371187

11381188
// This is a "void f();" which got merged with a file static.
11391189
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
1140-
return LinkageInfo::internal();
1190+
return getInternalLinkageFor(Function);
11411191

11421192
LinkageInfo LV;
11431193
if (!hasExplicitVisibilityAlready(computation)) {
@@ -1226,7 +1276,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
12261276
LVComputationKind computation) {
12271277
// Internal_linkage attribute overrides other considerations.
12281278
if (D->hasAttr<InternalLinkageAttr>())
1229-
return LinkageInfo::internal();
1279+
return getInternalLinkageFor(D);
12301280

12311281
// Objective-C: treat all Objective-C declarations as having external
12321282
// linkage.
@@ -1275,14 +1325,14 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
12751325
case Decl::ObjCProperty:
12761326
case Decl::ObjCPropertyImpl:
12771327
case Decl::ObjCProtocol:
1278-
return LinkageInfo::external();
1328+
return getExternalLinkageFor(D);
12791329

12801330
case Decl::CXXRecord: {
12811331
const auto *Record = cast<CXXRecordDecl>(D);
12821332
if (Record->isLambda()) {
12831333
if (!Record->getLambdaManglingNumber()) {
12841334
// This lambda has no mangling number, so it's internal.
1285-
return LinkageInfo::internal();
1335+
return getInternalLinkageFor(D);
12861336
}
12871337

12881338
// This lambda has its linkage/visibility determined:
@@ -1298,7 +1348,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
12981348
const CXXRecordDecl *OuterMostLambda =
12991349
getOutermostEnclosingLambda(Record);
13001350
if (!OuterMostLambda->getLambdaManglingNumber())
1301-
return LinkageInfo::internal();
1351+
return getInternalLinkageFor(D);
13021352

13031353
return getLVForClosure(
13041354
OuterMostLambda->getDeclContext()->getRedeclContext(),
@@ -1349,7 +1399,7 @@ class LinkageComputer {
13491399
LVComputationKind computation) {
13501400
// Internal_linkage attribute overrides other considerations.
13511401
if (D->hasAttr<InternalLinkageAttr>())
1352-
return LinkageInfo::internal();
1402+
return getInternalLinkageFor(D);
13531403

13541404
if (computation == LVForLinkageOnly && D->hasCachedLinkage())
13551405
return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
10981098
const NamedDecl *ND) {
10991099
// Set linkage and visibility in case we never see a definition.
11001100
LinkageInfo LV = ND->getLinkageAndVisibility();
1101-
if (LV.getLinkage() != ExternalLinkage) {
1101+
if (!isExternallyVisible(LV.getLinkage())) {
11021102
// Don't set internal linkage on declarations.
11031103
} else {
11041104
if (ND->hasAttr<DLLImportAttr>()) {

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
29592959
return llvm::GlobalValue::InternalLinkage;
29602960

29612961
case VisibleNoLinkage:
2962+
case ModuleInternalLinkage:
2963+
case ModuleLinkage:
29622964
case ExternalLinkage:
29632965
// RTTI is not enabled, which means that this type info struct is going
29642966
// to be used for exception handling. Give it linkonce_odr linkage.

clang/lib/CodeGen/MicrosoftCXXABI.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3425,6 +3425,8 @@ static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
34253425
return llvm::GlobalValue::InternalLinkage;
34263426

34273427
case VisibleNoLinkage:
3428+
case ModuleInternalLinkage:
3429+
case ModuleLinkage:
34283430
case ExternalLinkage:
34293431
return llvm::GlobalValue::LinkOnceODRLinkage;
34303432
}

clang/lib/Index/IndexSymbol.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ bool index::isFunctionLocalSymbol(const Decl *D) {
6969
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
7070
switch (ND->getFormalLinkage()) {
7171
case NoLinkage:
72-
case VisibleNoLinkage:
7372
case InternalLinkage:
7473
return true;
74+
case VisibleNoLinkage:
7575
case UniqueExternalLinkage:
76+
case ModuleInternalLinkage:
7677
llvm_unreachable("Not a sema linkage");
78+
case ModuleLinkage:
7779
case ExternalLinkage:
7880
return false;
7981
}

clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
// RUN: %clang_cc1 -fmodules-ts %S/module.cppm -triple %itanium_abi_triple -emit-module-interface -o %t
22
// 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
33

4+
// CHECK-DAG: @extern_var_exported = external global
5+
// FIXME: Should this be 'external global'?
6+
// CHECK-DAG: @inline_var_exported = linkonce_odr global
7+
// CHECK-DAG: @_ZL19static_var_exported = external global
8+
// CHECK-DAG: @const_var_exported = external constant
9+
//
10+
// FIXME: The module name should be mangled into all of these.
11+
// CHECK-DAG: @extern_var_module_linkage = external global
12+
// FIXME: Should this be 'external global'?
13+
// CHECK-DAG: @inline_var_module_linkage = linkonce_odr global
14+
// CHECK-DAG: @_ZL25static_var_module_linkage = external global
15+
// CHECK-DAG: @_ZL24const_var_module_linkage = external constant
16+
417
module Module;
518

619
void use() {
@@ -9,8 +22,13 @@ void use() {
922
// CHECK: declare {{.*}}@_Z18noninline_exportedv
1023
noninline_exported();
1124

25+
(void)&extern_var_exported;
26+
(void)&inline_var_exported;
27+
(void)&static_var_exported; // FIXME: Should not be exported.
28+
(void)&const_var_exported;
29+
1230
// FIXME: This symbol should not be visible here.
13-
// CHECK: define internal {{.*}}@_ZL26used_static_module_linkagev
31+
// CHECK: declare {{.*}}@_ZL26used_static_module_linkagev
1432
used_static_module_linkage();
1533

1634
// FIXME: The module name should be mangled into the name of this function.
@@ -20,4 +38,9 @@ void use() {
2038
// FIXME: The module name should be mangled into the name of this function.
2139
// CHECK: declare {{.*}}@_Z24noninline_module_linkagev
2240
noninline_module_linkage();
41+
42+
(void)&extern_var_module_linkage;
43+
(void)&inline_var_module_linkage;
44+
(void)&static_var_module_linkage; // FIXME: Should not be visible here.
45+
(void)&const_var_module_linkage;
2346
}

0 commit comments

Comments
 (0)