aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-07-07 20:04:28 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-07-07 20:04:28 +0000
commitaffbdbb5c5edf998ffc65b7f51ea00591be91dc2 (patch)
treeba31e82c5fe32afc6d45261f233533cee9965334
parent807bcad4b090ed067caaa50bb1224dbf32766a30 (diff)
[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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@307434 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/Linkage.h24
-rw-r--r--lib/AST/Decl.cpp78
-rw-r--r--lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp2
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp2
-rw-r--r--lib/Index/IndexSymbol.cpp4
-rw-r--r--test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp25
-rw-r--r--test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm76
-rw-r--r--test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp12
9 files changed, 198 insertions, 27 deletions
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index e96fb568c0..6ec8763f24 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -45,6 +45,17 @@ enum Linkage : unsigned char {
/// translation units because of types defined in a inline function.
VisibleNoLinkage,
+ /// \brief Internal linkage according to the Modules TS, but can be referred
+ /// to from other translation units indirectly through inline functions and
+ /// templates in the module interface.
+ ModuleInternalLinkage,
+
+ /// \brief Module linkage, which indicates that the entity can be referred
+ /// to from other translation units within the same module, and indirectly
+ /// from arbitrary other translation units through inline functions and
+ /// templates in the module interface.
+ ModuleLinkage,
+
/// \brief External linkage, which indicates that the entity can
/// be referred to from other translation units.
ExternalLinkage
@@ -74,15 +85,20 @@ inline bool isDiscardableGVALinkage(GVALinkage L) {
}
inline bool isExternallyVisible(Linkage L) {
- return L == ExternalLinkage || L == VisibleNoLinkage;
+ return L >= VisibleNoLinkage;
}
inline Linkage getFormalLinkage(Linkage L) {
- if (L == UniqueExternalLinkage)
+ switch (L) {
+ case UniqueExternalLinkage:
return ExternalLinkage;
- if (L == VisibleNoLinkage)
+ case VisibleNoLinkage:
return NoLinkage;
- return L;
+ case ModuleInternalLinkage:
+ return InternalLinkage;
+ default:
+ return L;
+ }
}
inline bool isExternalFormalLinkage(Linkage L) {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 24d9983912..573a98efe9 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -573,6 +573,44 @@ static bool isSingleLineLanguageLinkage(const Decl &D) {
return false;
}
+static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) {
+ switch (D->getModuleOwnershipKind()) {
+ case Decl::ModuleOwnershipKind::Unowned:
+ case Decl::ModuleOwnershipKind::ModulePrivate:
+ return false;
+ case Decl::ModuleOwnershipKind::Visible:
+ case Decl::ModuleOwnershipKind::VisibleWhenImported:
+ if (auto *M = D->getOwningModule())
+ return M->Kind == Module::ModuleInterfaceUnit;
+ }
+ llvm_unreachable("unexpected module ownership kind");
+}
+
+static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
+ // Internal linkage declarations within a module interface unit are modeled
+ // as "module-internal linkage", which means that they have internal linkage
+ // formally but can be indirectly accessed from outside the module via inline
+ // functions and templates defined within the module.
+ if (auto *M = D->getOwningModule())
+ if (M->Kind == Module::ModuleInterfaceUnit)
+ return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);
+
+ return LinkageInfo::internal();
+}
+
+static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
+ // C++ Modules TS [basic.link]/6.8:
+ // - A name declared at namespace scope that does not have internal linkage
+ // by the previous rules and that is introduced by a non-exported
+ // declaration has module linkage.
+ if (auto *M = D->getOwningModule())
+ if (M->Kind == Module::ModuleInterfaceUnit)
+ if (!isExportedFromModuleIntefaceUnit(D))
+ return LinkageInfo(ModuleLinkage, DefaultVisibility, false);
+
+ return LinkageInfo::external();
+}
+
static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
LVComputationKind computation) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
@@ -588,16 +626,18 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
if (const auto *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == SC_Static)
- return LinkageInfo::internal();
+ return getInternalLinkageFor(Var);
// - a non-inline, non-volatile object or reference that is explicitly
// declared const or constexpr and neither explicitly declared extern
// nor previously declared to have external linkage; or (there is no
// equivalent in C99)
+ // The C++ modules TS adds "non-exported" to this list.
if (Context.getLangOpts().CPlusPlus &&
Var->getType().isConstQualified() &&
!Var->getType().isVolatileQualified() &&
- !Var->isInline()) {
+ !Var->isInline() &&
+ !isExportedFromModuleIntefaceUnit(Var)) {
const VarDecl *PrevVar = Var->getPreviousDecl();
if (PrevVar)
return getLVForDecl(PrevVar, computation);
@@ -605,7 +645,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
if (Var->getStorageClass() != SC_Extern &&
Var->getStorageClass() != SC_PrivateExtern &&
!isSingleLineLanguageLinkage(*Var))
- return LinkageInfo::internal();
+ return getInternalLinkageFor(Var);
}
for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
@@ -615,7 +655,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
return PrevVar->getLinkageAndVisibility();
// Explicitly declared static.
if (PrevVar->getStorageClass() == SC_Static)
- return LinkageInfo::internal();
+ return getInternalLinkageFor(Var);
}
} else if (const FunctionDecl *Function = D->getAsFunction()) {
// C++ [temp]p4:
@@ -624,7 +664,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// Explicitly declared static.
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
- return LinkageInfo(InternalLinkage, DefaultVisibility, false);
+ return getInternalLinkageFor(Function);
} else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
// - a data member of an anonymous union.
const VarDecl *VD = IFD->getVarDecl();
@@ -637,7 +677,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
const auto *Var = dyn_cast<VarDecl>(D);
const auto *Func = dyn_cast<FunctionDecl>(D);
// FIXME: In C++11 onwards, anonymous namespaces should give decls
- // within them internal linkage, not unique external linkage.
+ // within them (including those inside extern "C" contexts) internal
+ // linkage, not unique external linkage:
+ //
+ // C++11 [basic.link]p4:
+ // An unnamed namespace or a namespace declared directly or indirectly
+ // within an unnamed namespace has internal linkage.
if ((!Var || !isFirstInExternCContext(Var)) &&
(!Func || !isFirstInExternCContext(Func)))
return LinkageInfo::uniqueExternal();
@@ -718,7 +763,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// because of this, but unique-external linkage suits us.
if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
- if (TypeLV.getLinkage() != ExternalLinkage)
+ if (TypeLV.getLinkage() != ExternalLinkage &&
+ TypeLV.getLinkage() != ModuleLinkage)
return LinkageInfo::uniqueExternal();
if (!LV.isVisibilityExplicit())
LV.mergeVisibility(TypeLV);
@@ -816,7 +862,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
- } else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
+ //
+ // We handled names in anonymous namespaces above.
+ } else if (isa<NamespaceDecl>(D)) {
return LV;
// By extension, we assign external linkage to Objective-C
@@ -1125,6 +1173,8 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
if (const auto *ND = dyn_cast<NamedDecl>(DC))
return getLVForDecl(ND, computation);
+ // FIXME: We have a closure at TU scope with no context declaration. This
+ // should probably have no linkage.
return LinkageInfo::external();
}
@@ -1137,7 +1187,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
// This is a "void f();" which got merged with a file static.
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
- return LinkageInfo::internal();
+ return getInternalLinkageFor(Function);
LinkageInfo LV;
if (!hasExplicitVisibilityAlready(computation)) {
@@ -1226,7 +1276,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
LVComputationKind computation) {
// Internal_linkage attribute overrides other considerations.
if (D->hasAttr<InternalLinkageAttr>())
- return LinkageInfo::internal();
+ return getInternalLinkageFor(D);
// Objective-C: treat all Objective-C declarations as having external
// linkage.
@@ -1275,14 +1325,14 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
- return LinkageInfo::external();
+ return getExternalLinkageFor(D);
case Decl::CXXRecord: {
const auto *Record = cast<CXXRecordDecl>(D);
if (Record->isLambda()) {
if (!Record->getLambdaManglingNumber()) {
// This lambda has no mangling number, so it's internal.
- return LinkageInfo::internal();
+ return getInternalLinkageFor(D);
}
// This lambda has its linkage/visibility determined:
@@ -1298,7 +1348,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
const CXXRecordDecl *OuterMostLambda =
getOutermostEnclosingLambda(Record);
if (!OuterMostLambda->getLambdaManglingNumber())
- return LinkageInfo::internal();
+ return getInternalLinkageFor(D);
return getLVForClosure(
OuterMostLambda->getDeclContext()->getRedeclContext(),
@@ -1349,7 +1399,7 @@ public:
LVComputationKind computation) {
// Internal_linkage attribute overrides other considerations.
if (D->hasAttr<InternalLinkageAttr>())
- return LinkageInfo::internal();
+ return getInternalLinkageFor(D);
if (computation == LVForLinkageOnly && D->hasCachedLinkage())
return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 20d945fe50..10838b751c 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1098,7 +1098,7 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
const NamedDecl *ND) {
// Set linkage and visibility in case we never see a definition.
LinkageInfo LV = ND->getLinkageAndVisibility();
- if (LV.getLinkage() != ExternalLinkage) {
+ if (!isExternallyVisible(LV.getLinkage())) {
// Don't set internal linkage on declarations.
} else {
if (ND->hasAttr<DLLImportAttr>()) {
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index e6d38aff34..c82b9677ea 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2959,6 +2959,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
return llvm::GlobalValue::InternalLinkage;
case VisibleNoLinkage:
+ case ModuleInternalLinkage:
+ case ModuleLinkage:
case ExternalLinkage:
// RTTI is not enabled, which means that this type info struct is going
// to be used for exception handling. Give it linkonce_odr linkage.
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index e68a16e0bd..78b510bb46 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -3425,6 +3425,8 @@ static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
return llvm::GlobalValue::InternalLinkage;
case VisibleNoLinkage:
+ case ModuleInternalLinkage:
+ case ModuleLinkage:
case ExternalLinkage:
return llvm::GlobalValue::LinkOnceODRLinkage;
}
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index bf358a3721..0dc3720208 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -69,11 +69,13 @@ bool index::isFunctionLocalSymbol(const Decl *D) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
switch (ND->getFormalLinkage()) {
case NoLinkage:
- case VisibleNoLinkage:
case InternalLinkage:
return true;
+ case VisibleNoLinkage:
case UniqueExternalLinkage:
+ case ModuleInternalLinkage:
llvm_unreachable("Not a sema linkage");
+ case ModuleLinkage:
case ExternalLinkage:
return false;
}
diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
index c8b8725ed2..dc6a3635a8 100644
--- a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
+++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
@@ -1,6 +1,19 @@
// 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 global
+// FIXME: Should this be 'external global'?
+// CHECK-DAG: @inline_var_exported = linkonce_odr global
+// CHECK-DAG: @_ZL19static_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
+
module Module;
void use() {
@@ -9,8 +22,13 @@ void use() {
// CHECK: declare {{.*}}@_Z18noninline_exportedv
noninline_exported();
+ (void)&extern_var_exported;
+ (void)&inline_var_exported;
+ (void)&static_var_exported; // FIXME: Should not be exported.
+ (void)&const_var_exported;
+
// FIXME: This symbol should not be visible here.
- // CHECK: define internal {{.*}}@_ZL26used_static_module_linkagev
+ // CHECK: declare {{.*}}@_ZL26used_static_module_linkagev
used_static_module_linkage();
// FIXME: The module name should be mangled into the name of this function.
@@ -20,4 +38,9 @@ void use() {
// FIXME: The module name should be mangled into the name of this function.
// CHECK: declare {{.*}}@_Z24noninline_module_linkagev
noninline_module_linkage();
+
+ (void)&extern_var_module_linkage;
+ (void)&inline_var_module_linkage;
+ (void)&static_var_module_linkage; // FIXME: Should not be visible here.
+ (void)&const_var_module_linkage;
}
diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
index be3644efa5..d452f741a0 100644
--- a/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
+++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
@@ -1,9 +1,39 @@
-// RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s --implicit-check-not=unused
+// RUN: %clang_cc1 -fmodules-ts %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s --implicit-check-not unused_inline --implicit-check-not unused_stastic_global_module
+
+// CHECK-DAG: @extern_var_global_module = external global
+// CHECK-DAG: @inline_var_global_module = linkonce_odr global
+// CHECK-DAG: @_ZL24static_var_global_module = internal global
+// 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 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 global
+// CHECK-DAG: @_ZL19static_var_exported = global
+// CHECK-DAG: @const_var_exported = constant
+//
+// FIXME: The module name should be mangled into all of these.
+// CHECK-DAG: @extern_var_module_linkage = external 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_module_linkage = linkonce_odr global
+// CHECK-DAG: @_ZL25static_var_module_linkage = global
+// CHECK-DAG: @_ZL24const_var_module_linkage = constant
static void unused_static_global_module() {}
static void used_static_global_module() {}
+
inline void unused_inline_global_module() {}
inline void used_inline_global_module() {}
+
+extern int extern_var_global_module;
+inline int inline_var_global_module;
+static int static_var_global_module;
+const int const_var_global_module = 3;
+
// CHECK: define void {{.*}}@_Z23noninline_global_modulev
void noninline_global_module() {
// FIXME: This should be promoted to module linkage and given a
@@ -15,6 +45,11 @@ void noninline_global_module() {
used_static_global_module();
// CHECK: define linkonce_odr {{.*}}@_Z25used_inline_global_modulev
used_inline_global_module();
+
+ (void)&extern_var_global_module;
+ (void)&inline_var_global_module;
+ (void)&static_var_global_module;
+ (void)&const_var_global_module;
}
export module Module;
@@ -22,33 +57,62 @@ 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
static void unused_static_exported() {}
+ // CHECK: define void {{.*}}@_ZL20used_static_exportedv
static void used_static_exported() {}
inline void unused_inline_exported() {}
inline void used_inline_exported() {}
+
+ extern int extern_var_exported;
+ inline int inline_var_exported;
+ // FIXME: This should be ill-formed: you can't export an internal linkage
+ // symbol.
+ static int static_var_exported;
+ const int const_var_exported = 3;
+
// CHECK: define void {{.*}}@_Z18noninline_exportedv
void noninline_exported() {
- // CHECK: define internal {{.*}}@_ZL20used_static_exportedv
used_static_exported();
// CHECK: define linkonce_odr {{.*}}@_Z20used_inline_exportedv
used_inline_exported();
+
+ (void)&extern_var_exported;
+ (void)&inline_var_exported;
+ (void)&static_var_exported;
+ (void)&const_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.
+// FIXME: The module name should be mangled into the name of this function.
+// CHECK: define void {{.*}}@_ZL28unused_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
static void used_static_module_linkage() {}
+
inline void unused_inline_module_linkage() {}
inline void used_inline_module_linkage() {}
+
+extern int extern_var_module_linkage;
+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
void noninline_module_linkage() {
- // FIXME: This should be promoted to module linkage and given a
- // module-mangled name, if it's called from an inline function within
- // the module interface.
- // CHECK: define internal {{.*}}@_ZL26used_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
used_inline_module_linkage();
+
+ (void)&extern_var_module_linkage;
+ (void)&inline_var_module_linkage;
+ (void)&static_var_module_linkage;
+ (void)&const_var_module_linkage;
}
diff --git a/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp b/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
index bbd67e2c89..f6e0238c6b 100644
--- a/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
+++ b/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
@@ -1,6 +1,13 @@
// 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 global
+// 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: @const_var_exported = constant
+
import Module;
void use() {
@@ -9,5 +16,10 @@ void use() {
// CHECK: declare {{.*}}@_Z18noninline_exportedv
noninline_exported();
+ (void)&extern_var_exported;
+ (void)&inline_var_exported;
+ (void)&static_var_exported;
+ (void)&const_var_exported;
+
// Module-linkage declarations are not visible here.
}