summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp81
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp52
2 files changed, 50 insertions, 83 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 64010666299..e8201fc4ea2 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -610,18 +610,6 @@ 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,
@@ -633,28 +621,24 @@ 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
-
- 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);
- }
-
+ // - an object, reference, function or function template that is
+ // explicitly declared static; or,
+ // (This bullet corresponds to C99 6.2.2p3.)
if (const auto *Var = dyn_cast<VarDecl>(D)) {
- // - 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.)
+ // 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.
if (Context.getLangOpts().CPlusPlus &&
Var->getType().isConstQualified() &&
!Var->getType().isVolatileQualified() &&
!Var->isInline() &&
- !isExportedFromModuleInterfaceUnit(Var) &&
- !isa<VarTemplateSpecializationDecl>(Var) &&
- !Var->getDescribedVarTemplate()) {
+ !isExportedFromModuleInterfaceUnit(Var)) {
const VarDecl *PrevVar = Var->getPreviousDecl();
if (PrevVar)
return getLVForDecl(PrevVar, computation);
@@ -674,6 +658,14 @@ 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();
@@ -682,8 +674,6 @@ 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);
@@ -743,20 +733,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// C++ [basic.link]p4:
- // 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.
+ // A name having namespace scope has external linkage if it is the
+ // name of
//
- // The bullets are:
-
- // - a variable; or
+ // - an object or reference, unless it has internal linkage; or
if (const auto *Var = dyn_cast<VarDecl>(D)) {
// GCC applies the following optimization to variables and static
// data members, but not to functions:
@@ -802,7 +782,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
mergeTemplateLV(LV, spec, computation);
}
- // - a function; or
+ // - a function, unless it has internal linkage; 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
@@ -856,8 +836,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
mergeTemplateLV(LV, spec, computation);
}
- // FIXME: This is not part of the C++ standard any more.
- // - an enumerator belonging to an enumeration with external linkage; or
+ // - an enumerator belonging to an enumeration with external linkage;
} else if (isa<EnumConstantDecl>(D)) {
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
computation);
@@ -865,16 +844,16 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
return LinkageInfo::none();
LV.merge(EnumLV);
- // - a template
+ // - a template, unless it is a function template that has
+ // internal linkage (Clause 14);
} else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility = !hasExplicitVisibilityAlready(computation);
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
- // An unnamed namespace or a namespace declared directly or indirectly
- // within an unnamed namespace has internal linkage. All other namespaces
- // have external linkage.
+ // - a namespace (7.3), unless it is declared within an unnamed
+ // namespace.
//
// We handled names in anonymous namespaces above.
} else if (isa<NamespaceDecl>(D)) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 9c7126d9266..10103708384 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -8619,29 +8619,6 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
return false;
}
-/// Common checks for whether an explicit instantiation of \p D is valid.
-static bool CheckExplicitInstantiation(Sema &S, NamedDecl *D,
- SourceLocation InstLoc,
- bool WasQualifiedName,
- TemplateSpecializationKind TSK) {
- // C++ [temp.explicit]p13:
- // An explicit instantiation declaration shall not name a specialization of
- // a template with internal linkage.
- if (TSK == TSK_ExplicitInstantiationDeclaration &&
- D->getFormalLinkage() == InternalLinkage) {
- S.Diag(InstLoc, diag::err_explicit_instantiation_internal_linkage) << D;
- return true;
- }
-
- // C++11 [temp.explicit]p3: [DR 275]
- // An explicit instantiation shall appear in an enclosing namespace of its
- // template.
- if (CheckExplicitInstantiationScope(S, D, InstLoc, WasQualifiedName))
- return true;
-
- return false;
-}
-
/// Determine whether the given scope specifier has a template-id in it.
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
if (!SS.isSet())
@@ -8793,8 +8770,13 @@ DeclResult Sema::ActOnExplicitInstantiation(
TemplateSpecializationKind PrevDecl_TSK
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
- if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc,
- SS.isSet(), TSK))
+ // C++0x [temp.explicit]p2:
+ // [...] An explicit instantiation shall appear in an enclosing
+ // namespace of its template. [...]
+ //
+ // This is C++ DR 275.
+ if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
+ SS.isSet()))
return true;
ClassTemplateSpecializationDecl *Specialization = nullptr;
@@ -9017,7 +8999,12 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
: TSK_ExplicitInstantiationDeclaration;
- CheckExplicitInstantiation(*this, Record, NameLoc, true, TSK);
+ // C++0x [temp.explicit]p2:
+ // [...] An explicit instantiation shall appear in an enclosing
+ // namespace of its template. [...]
+ //
+ // This is C++ DR 275.
+ CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
// Verify that it is okay to explicitly instantiate here.
CXXRecordDecl *PrevDecl
@@ -9248,7 +9235,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
diag::ext_explicit_instantiation_without_qualified_id)
<< Prev << D.getCXXScopeSpec().getRange();
- CheckExplicitInstantiation(*this, Prev, D.getIdentifierLoc(), true, TSK);
+ // Check the scope of this explicit instantiation.
+ CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
// Verify that it is okay to explicitly instantiate here.
TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind();
@@ -9456,11 +9444,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
diag::ext_explicit_instantiation_without_qualified_id)
<< Specialization << D.getCXXScopeSpec().getRange();
- CheckExplicitInstantiation(
- *this,
- FunTmpl ? (NamedDecl *)FunTmpl
- : Specialization->getInstantiatedFromMemberFunction(),
- D.getIdentifierLoc(), D.getCXXScopeSpec().isSet(), TSK);
+ CheckExplicitInstantiationScope(*this,
+ FunTmpl? (NamedDecl *)FunTmpl
+ : Specialization->getInstantiatedFromMemberFunction(),
+ D.getIdentifierLoc(),
+ D.getCXXScopeSpec().isSet());
// FIXME: Create some kind of ExplicitInstantiationDecl here.
return (Decl*) nullptr;
OpenPOWER on IntegriCloud