================
@@ -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

Reply via email to