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())
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;
= 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
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();
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
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;
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify
+
+// This is a test for a hack in Clang that works around an issue with libc++'s
+// <valarray> implementation. The <valarray> header contains explicit
+// instantiations of functions that it declared with the internal_linkage
+// attribute, which are ill-formed by [temp.explicit]p13 (and meaningless).
+
+#ifdef BE_THE_HEADER
+
+#pragma GCC system_header
+namespace std {
+ using size_t = __SIZE_TYPE__;
+ template<typename T> struct valarray {
+ __attribute__((internal_linkage)) valarray(size_t) {}
+ __attribute__((internal_linkage)) ~valarray() {}
+ };
+
+ extern template valarray<size_t>::valarray(size_t);
+ extern template valarray<size_t>::~valarray();
+}
+
+#else
+
+#define BE_THE_HEADER
+#include "libcxx_valarray_hack.cpp"
+
+template<typename T> struct foo {
+ __attribute__((internal_linkage)) void x() {};
+};
+extern template void foo<int>::x(); // expected-error {{explicit instantiation declaration of 'x' with internal linkage}}
+
+#endif