|
@@ -8619,6 +8619,29 @@ 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())
|
|
@@ -8770,13 +8793,8 @@ DeclResult Sema::ActOnExplicitInstantiation(
|
|
|
TemplateSpecializationKind PrevDecl_TSK
|
|
|
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
|
|
|
|
|
|
- // 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()))
|
|
|
+ if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc,
|
|
|
+ SS.isSet(), TSK))
|
|
|
return true;
|
|
|
|
|
|
ClassTemplateSpecializationDecl *Specialization = nullptr;
|
|
@@ -8999,12 +9017,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
|
|
|
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
|
|
|
: TSK_ExplicitInstantiationDeclaration;
|
|
|
|
|
|
- // 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);
|
|
|
+ CheckExplicitInstantiation(*this, Record, NameLoc, true, TSK);
|
|
|
|
|
|
// Verify that it is okay to explicitly instantiate here.
|
|
|
CXXRecordDecl *PrevDecl
|
|
@@ -9235,8 +9248,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|
|
diag::ext_explicit_instantiation_without_qualified_id)
|
|
|
<< Prev << D.getCXXScopeSpec().getRange();
|
|
|
|
|
|
- // Check the scope of this explicit instantiation.
|
|
|
- CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
|
|
|
+ CheckExplicitInstantiation(*this, Prev, D.getIdentifierLoc(), true, TSK);
|
|
|
|
|
|
// Verify that it is okay to explicitly instantiate here.
|
|
|
TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind();
|
|
@@ -9411,6 +9423,20 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|
|
return (Decl*) nullptr;
|
|
|
}
|
|
|
|
|
|
+ // HACK: libc++ has a bug where it attempts to explicitly instantiate the
|
|
|
+ // functions
|
|
|
+ // valarray<size_t>::valarray(size_t) and
|
|
|
+ // valarray<size_t>::~valarray()
|
|
|
+ // that it declared to have internal linkage with the internal_linkage
|
|
|
+ // attribute. Ignore the explicit instantiation declaration in this case.
|
|
|
+ if (Specialization->hasAttr<InternalLinkageAttr>() &&
|
|
|
+ TSK == TSK_ExplicitInstantiationDeclaration) {
|
|
|
+ if (auto *RD = dyn_cast<CXXRecordDecl>(Specialization->getDeclContext()))
|
|
|
+ if (RD->getIdentifier() && RD->getIdentifier()->isStr("valarray") &&
|
|
|
+ RD->isInStdNamespace())
|
|
|
+ return (Decl*) nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes());
|
|
|
|
|
|
// In MSVC mode, dllimported explicit instantiation definitions are treated as
|
|
@@ -9444,11 +9470,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|
|
diag::ext_explicit_instantiation_without_qualified_id)
|
|
|
<< Specialization << D.getCXXScopeSpec().getRange();
|
|
|
|
|
|
- CheckExplicitInstantiationScope(*this,
|
|
|
- FunTmpl? (NamedDecl *)FunTmpl
|
|
|
- : Specialization->getInstantiatedFromMemberFunction(),
|
|
|
- D.getIdentifierLoc(),
|
|
|
- D.getCXXScopeSpec().isSet());
|
|
|
+ CheckExplicitInstantiation(
|
|
|
+ *this,
|
|
|
+ FunTmpl ? (NamedDecl *)FunTmpl
|
|
|
+ : Specialization->getInstantiatedFromMemberFunction(),
|
|
|
+ D.getIdentifierLoc(), D.getCXXScopeSpec().isSet(), TSK);
|
|
|
|
|
|
// FIXME: Create some kind of ExplicitInstantiationDecl here.
|
|
|
return (Decl*) nullptr;
|