>>template <class T>
>>struct A
>>{
>>   void f(T);
>>};
>>
>>template <class T>
>>void A<T>::f(const T)
>>{ }
>>
>>which is certainly questionable code, but is currently also accepted by 
>>clang and EDG compilers.

I just found out that clang actually correctly reject this code during 
specialization. 
(https://www.godbolt.org/z/evjvhqqoo)
It all depends on explicit argument which may turn "const" into 
top-level-cv-qualifier
or not.
For example, when argument is "int[3]", the function signature of 
specialization 
will have to keep the const because it is no longer top-level cv qualifier.

template<>
void A<int[3]>::f(const int*){} // not matching declaration "void(int*)"

Obviously when explicit argument is "int", the const would be dropped and 
specialization matches
declaration. i.e.
template<>
void A<int>::f(int){} // this matches declaration "void(int)"

So, clang is correct to NOT reject template definition when there is no 
specialization yet.

As a comparison, GCC is not able to reject  incorrect specialization. Should we 
file this bug? Or just add this 
as test case to original 1001 core issue?

Again, my patch cannot deal this case as it is not "typename". We may have to 
fix "tsubst_function_decl" to see any workaround of line 
"SET_DECL_IMPLICIT_INSTANTIATION (r);" 
(See my previous email 
https://gcc.gnu.org/pipermail/gcc-patches/2021-September/580260.html)
This macro "DECL_USE_TEMPLATE" is set to 1. However, the comment says "1" is 
for "implicit specialization", but we are actually dealing with "partial or 
explicit specialization" which is "2".

Here I quote comment from cp-tree.h

/* Nonzero iff NODE is a specialization of a template.  The value
   indicates the type of specializations:

     1=implicit instantiation

     2=partial or explicit specialization, e.g.:

        template <> int min<int> (int, int),

     3=explicit instantiation, e.g.:

        template int min<int> (int, int);

   Note that NODE will be marked as a specialization even if the
   template it is instantiating is not a primary template.  For
   example, given:

     template <typename T> struct O {
       void f();
       struct I {};
     };

   both O<int>::f and O<int>::I will be marked as instantiations.

   If DECL_USE_TEMPLATE is nonzero, then DECL_TEMPLATE_INFO will also
   be non-NULL.  */

Reply via email to