r359266 - PR41607: Don't forget to substitute outer template arguments into a
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 25 19:11:24 PDT 2019
Author: rsmith
Date: Thu Apr 25 19:11:23 2019
New Revision: 359266
URL: http://llvm.org/viewvc/llvm-project?rev=359266&view=rev
Log:
PR41607: Don't forget to substitute outer template arguments into a
class-scope explicit specialization of a class template.
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=359266&r1=359265&r2=359266&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Apr 25 19:11:23 2019
@@ -1746,6 +1746,20 @@ public:
return getSpecializationKind() == TSK_ExplicitSpecialization;
}
+ /// Is this an explicit specialization at class scope (within the class that
+ /// owns the primary template)? For example:
+ ///
+ /// \code
+ /// template<typename T> struct Outer {
+ /// template<typename U> struct Inner;
+ /// template<> struct Inner; // class-scope explicit specialization
+ /// };
+ /// \endcode
+ bool isClassScopeExplicitSpecialization() const {
+ return isExplicitSpecialization() &&
+ isa<CXXRecordDecl>(getLexicalDeclContext());
+ }
+
/// True if this declaration is an explicit specialization,
/// explicit instantiation declaration, or explicit instantiation
/// definition.
@@ -2581,6 +2595,11 @@ public:
return getSpecializationKind() == TSK_ExplicitSpecialization;
}
+ bool isClassScopeExplicitSpecialization() const {
+ return isExplicitSpecialization() &&
+ isa<CXXRecordDecl>(getLexicalDeclContext());
+ }
+
/// True if this declaration is an explicit specialization,
/// explicit instantiation declaration, or explicit instantiation
/// definition.
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=359266&r1=359265&r2=359266&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Apr 25 19:11:23 2019
@@ -66,9 +66,12 @@ Sema::getTemplateInstantiationArgs(Named
if (!Ctx) {
Ctx = D->getDeclContext();
- // Add template arguments from a variable template instantiation.
- if (VarTemplateSpecializationDecl *Spec =
- dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ // Add template arguments from a variable template instantiation. For a
+ // class-scope explicit specialization, there are no template arguments
+ // at this level, but there may be enclosing template arguments.
+ VarTemplateSpecializationDecl *Spec =
+ dyn_cast<VarTemplateSpecializationDecl>(D);
+ if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
// We're done when we hit an explicit specialization.
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<VarTemplatePartialSpecializationDecl>(Spec))
@@ -111,8 +114,9 @@ Sema::getTemplateInstantiationArgs(Named
while (!Ctx->isFileContext()) {
// Add template arguments from a class template instantiation.
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+ ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
+ if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
// We're done when we hit an explicit specialization.
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<ClassTemplatePartialSpecializationDecl>(Spec))
Modified: cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp?rev=359266&r1=359265&r2=359266&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp (original)
+++ cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp Thu Apr 25 19:11:23 2019
@@ -62,3 +62,20 @@ namespace SpecLoc {
template<> float A<int>::n; // expected-error {{different type}}
template<> void A<int>::f() throw(); // expected-error {{does not match}}
}
+
+namespace PR41607 {
+ template<int N> struct Outer {
+ template<typename...> struct Inner;
+ template<> struct Inner<> {
+ static constexpr int f() { return N; }
+ };
+
+ template<typename...> static int a; // expected-note 2{{}}
+ template<> static constexpr int a<> = 42;
+ };
+ static_assert(Outer<123>::Inner<>::f() == 123, "");
+ static_assert(Outer<123>::Inner<>::f() != 125, "");
+ // FIXME: The class-scope explicit specialization of the variable template doesn't work!
+ static_assert(Outer<123>::a<> == 42, ""); // expected-error {{}} expected-note {{}}
+ static_assert(Outer<123>::a<> != 43, ""); // expected-error {{}} expected-note {{}}
+}
More information about the cfe-commits
mailing list