Skip to content

Commit

Permalink
[clang] Fix specialization of non-templated member classes of class t…
Browse files Browse the repository at this point in the history
…emplates

Explicit specialization doesn't increase depth of template parameters,
so need to be careful when gathering template parameters for
instantiation.
For the case:
```
template<typename T>
struct X {
  struct impl;
};

template <>
struct X<int>::impl {
    template<int ct>
    int f() { return ct; };
};
```
instantiation of `f` used to crash because type template parameter
`int` of explicit specialization was taken into account, but non-type
template parameter `ct` had zero depth and index so wrong parameter
ended up inside of a wrong handler.

Fixes #61159

Reviewed By: aaron.ballman, shafik

Differential Revision: https://reviews.llvm.org/D155705
  • Loading branch information
Fznamznon committed Jul 24, 2023
1 parent be5ac66 commit dcb8911
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@ Bug Fixes in This Version
- Invalidate BlockDecl with invalid ParmVarDecl. Remove redundant dump of
BlockDecl's ParmVarDecl
(`#64005 <https://github.com/llvm/llvm-project/issues/64005>_`)
- Fix crash on nested templated class with template function call.
(`#61159 <https://github.com/llvm/llvm-project/issues/61159>_`)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ Response HandleRecordDecl(const CXXRecordDecl *Rec,
/*Final=*/false);
}

if (const MemberSpecializationInfo *MSInfo =
Rec->getMemberSpecializationInfo())
if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return Response::Done();

bool IsFriend = Rec->getFriendObjectKind() ||
(Rec->getDescribedClassTemplate() &&
Rec->getDescribedClassTemplate()->getFriendObjectKind());
Expand Down
39 changes: 39 additions & 0 deletions clang/test/SemaTemplate/gh61159.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
// expected-no-diagnostics

namespace GH61159 {
template <typename T> struct X {
struct I;
};

template <> struct X<int>::I {
template <int ct> constexpr int f() { return ct; };

int data = 3;
};

template <typename T> struct X<T>::I {
template <T ct> constexpr T f() { return ct + 1; };
T data = 7;
};

static_assert(X<int>::I{}.f<17>() == 17);
static_assert(X<int>::I{}.data == 3);
static_assert(X<short>::I{}.data == 7);
static_assert(X<short>::I{}.f<18>() == 19);

template <typename T> struct Y {
struct I;
};

template <> struct Y<int> {
struct I {
template <int ct> constexpr int f() { return ct; };
int data = 3;
};
};

static_assert(Y<int>::I{}.f<17>() == 17);
static_assert(Y<int>::I{}.data == 3);

} // namespace GH61159

0 comments on commit dcb8911

Please sign in to comment.