================
@@ -2247,9 +2247,10 @@ DeclResult Sema::CheckClassTemplate(
NewTemplate->setModulePrivate();
if (IsMemberSpecialization) {
- assert(PrevClassTemplate &&
+ assert((PrevClassTemplate || Invalid) &&
"Member specialization without a primary template?");
- NewTemplate->setMemberSpecialization();
+ if (PrevClassTemplate)
+ NewTemplate->setMemberSpecialization();
----------------
w007878 wrote:
Thank you for reviewing, that's a good point to discuss.
The flag `Invalid` could be set in other cases here
https://github.com/llvm/llvm-project/blob/8d478d367bfd57630c483eb50c7984dc819269f0/clang/lib/Sema/SemaTemplate.cpp#L2179-L2194
Consider this example
```c++
template <class T> struct A {
template <class U = int> struct B;
};
// First error: redefinition of default argument -> Invalid = true,
// but still marked a member specialization.
template <>
template <class U = int>
struct A<int>::B {
// Second, independent error.
// Its condition is dependent on U, so it is deferred to instantiation.
static_assert(sizeof(U) == 0, "second diagnostic, from the member-spec body");
};
void use() {
A<int>::B<char> b;
}
```
If we check the `Invalid` in the `if` condition, the compilation error would be
```
invalid_member_template.cpp:8:21: error: template parameter redefines default
argument
8 | template <class U = int>
| ^
invalid_member_template.cpp:2:23: note: previous default template argument
defined here
2 | template <class U = int> struct B;
| ^
invalid_member_template.cpp:16:19: error: implicit instantiation of undefined
template 'A<int>::B<char>'
16 | A<int>::B<char> b;
| ^
invalid_member_template.cpp:2:35: note: template is declared here
2 | template <class U = int> struct B;
| ^
2 errors generated.
```
Otherwise, we allow `Invalid` in assertions but still do the member
specialization, we got this:
```
invalid_member_template.cpp:8:21: error: template parameter redefines default
argument
8 | template <class U = int>
| ^
invalid_member_template.cpp:2:23: note: previous default template argument
defined here
2 | template <class U = int> struct B;
| ^
invalid_member_template.cpp:12:17: error: static assertion failed due to
requirement 'sizeof(char) == 0': second diagnostic, from the member-spec body
12 | static_assert(sizeof(U) == 0, "second diagnostic, from the
member-spec body");
| ^~~~~~~~~~~~~~
invalid_member_template.cpp:16:19: note: in instantiation of template class
'A<int>::B<char>' requested here
16 | A<int>::B<char> b;
| ^
invalid_member_template.cpp:12:27: note: expression evaluates to '1 == 0'
12 | static_assert(sizeof(U) == 0, "second diagnostic, from the
member-spec body");
| ~~~~~~~~~~^~~~
2 errors generated.
```
The number of errors are same, but we got more diagnostic results. I do prefer
to proceed with the member specialization, therefore we catch the errors
inside. Suggestions are welcome for this.
https://github.com/llvm/llvm-project/pull/201506
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits