|
@@ -610,6 +610,18 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
|
|
|
return LinkageInfo::external();
|
|
|
}
|
|
|
|
|
|
+static StorageClass getStorageClass(const Decl *D) {
|
|
|
+ if (auto *TD = dyn_cast<TemplateDecl>(D))
|
|
|
+ D = TD->getTemplatedDecl();
|
|
|
+ if (D) {
|
|
|
+ if (auto *VD = dyn_cast<VarDecl>(D))
|
|
|
+ return VD->getStorageClass();
|
|
|
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
|
|
|
+ return FD->getStorageClass();
|
|
|
+ }
|
|
|
+ return SC_None;
|
|
|
+}
|
|
|
+
|
|
|
LinkageInfo
|
|
|
LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
LVComputationKind computation,
|
|
@@ -621,24 +633,28 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
// C++ [basic.link]p3:
|
|
|
// A name having namespace scope (3.3.6) has internal linkage if it
|
|
|
// is the name of
|
|
|
- // - an object, reference, function or function template that is
|
|
|
- // explicitly declared static; or,
|
|
|
- // (This bullet corresponds to C99 6.2.2p3.)
|
|
|
+
|
|
|
+ if (getStorageClass(D->getCanonicalDecl()) == SC_Static) {
|
|
|
+ // - a variable, variable template, function, or function template
|
|
|
+ // that is explicitly declared static; or
|
|
|
+ // (This bullet corresponds to C99 6.2.2p3.)
|
|
|
+ return getInternalLinkageFor(D);
|
|
|
+ }
|
|
|
+
|
|
|
if (const auto *Var = dyn_cast<VarDecl>(D)) {
|
|
|
- // Explicitly declared static.
|
|
|
- if (Var->getStorageClass() == SC_Static)
|
|
|
- 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.
|
|
|
+ // - a non-template variable of non-volatile const-qualified type, unless
|
|
|
+ // - it is explicitly declared extern, or
|
|
|
+ // - it is inline or exported, or
|
|
|
+ // - it was previously declared and the prior declaration did not have
|
|
|
+ // internal linkage
|
|
|
+ // (There is no equivalent in C99.)
|
|
|
if (Context.getLangOpts().CPlusPlus &&
|
|
|
Var->getType().isConstQualified() &&
|
|
|
!Var->getType().isVolatileQualified() &&
|
|
|
!Var->isInline() &&
|
|
|
- !isExportedFromModuleInterfaceUnit(Var)) {
|
|
|
+ !isExportedFromModuleInterfaceUnit(Var) &&
|
|
|
+ !isa<VarTemplateSpecializationDecl>(Var) &&
|
|
|
+ !Var->getDescribedVarTemplate()) {
|
|
|
const VarDecl *PrevVar = Var->getPreviousDecl();
|
|
|
if (PrevVar)
|
|
|
return getLVForDecl(PrevVar, computation);
|
|
@@ -658,14 +674,6 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
if (PrevVar->getStorageClass() == SC_Static)
|
|
|
return getInternalLinkageFor(Var);
|
|
|
}
|
|
|
- } else if (const FunctionDecl *Function = D->getAsFunction()) {
|
|
|
- // C++ [temp]p4:
|
|
|
- // A non-member function template can have internal linkage; any
|
|
|
- // other template name shall have external linkage.
|
|
|
-
|
|
|
- // Explicitly declared static.
|
|
|
- if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
|
|
|
- return getInternalLinkageFor(Function);
|
|
|
} else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
|
|
|
// - a data member of an anonymous union.
|
|
|
const VarDecl *VD = IFD->getVarDecl();
|
|
@@ -674,6 +682,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
}
|
|
|
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
|
|
|
|
|
|
+ // FIXME: This gives internal linkage to names that should have no linkage
|
|
|
+ // (those not covered by [basic.link]p6).
|
|
|
if (D->isInAnonymousNamespace()) {
|
|
|
const auto *Var = dyn_cast<VarDecl>(D);
|
|
|
const auto *Func = dyn_cast<FunctionDecl>(D);
|
|
@@ -733,10 +743,20 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
|
|
|
// C++ [basic.link]p4:
|
|
|
|
|
|
- // A name having namespace scope has external linkage if it is the
|
|
|
- // name of
|
|
|
+ // A name having namespace scope that has not been given internal linkage
|
|
|
+ // above and that is the name of
|
|
|
+ // [...bullets...]
|
|
|
+ // has its linkage determined as follows:
|
|
|
+ // - if the enclosing namespace has internal linkage, the name has
|
|
|
+ // internal linkage; [handled above]
|
|
|
+ // - otherwise, if the declaration of the name is attached to a named
|
|
|
+ // module and is not exported, the name has module linkage;
|
|
|
+ // - otherwise, the name has external linkage.
|
|
|
+ // LV is currently set up to handle the last two bullets.
|
|
|
//
|
|
|
- // - an object or reference, unless it has internal linkage; or
|
|
|
+ // The bullets are:
|
|
|
+
|
|
|
+ // - a variable; or
|
|
|
if (const auto *Var = dyn_cast<VarDecl>(D)) {
|
|
|
// GCC applies the following optimization to variables and static
|
|
|
// data members, but not to functions:
|
|
@@ -782,7 +802,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
mergeTemplateLV(LV, spec, computation);
|
|
|
}
|
|
|
|
|
|
- // - a function, unless it has internal linkage; or
|
|
|
+ // - a function; or
|
|
|
} else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
|
|
|
// In theory, we can modify the function's LV by the LV of its
|
|
|
// type unless it has C linkage (see comment above about variables
|
|
@@ -836,7 +856,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
mergeTemplateLV(LV, spec, computation);
|
|
|
}
|
|
|
|
|
|
- // - an enumerator belonging to an enumeration with external linkage;
|
|
|
+ // FIXME: This is not part of the C++ standard any more.
|
|
|
+ // - an enumerator belonging to an enumeration with external linkage; or
|
|
|
} else if (isa<EnumConstantDecl>(D)) {
|
|
|
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
|
|
|
computation);
|
|
@@ -844,16 +865,16 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|
|
return LinkageInfo::none();
|
|
|
LV.merge(EnumLV);
|
|
|
|
|
|
- // - a template, unless it is a function template that has
|
|
|
- // internal linkage (Clause 14);
|
|
|
+ // - a template
|
|
|
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
|
|
|
bool considerVisibility = !hasExplicitVisibilityAlready(computation);
|
|
|
LinkageInfo tempLV =
|
|
|
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
|
|
|
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
|
|
|
|
|
|
- // - a namespace (7.3), unless it is declared within an unnamed
|
|
|
- // namespace.
|
|
|
+ // An unnamed namespace or a namespace declared directly or indirectly
|
|
|
+ // within an unnamed namespace has internal linkage. All other namespaces
|
|
|
+ // have external linkage.
|
|
|
//
|
|
|
// We handled names in anonymous namespaces above.
|
|
|
} else if (isa<NamespaceDecl>(D)) {
|