https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99686

--- Comment #7 from Steven Sun <StevenSun2021 at hotmail dot com> ---
After digging for two days, I think I may know what's happening inside. 

Under std=c++20 and my code in comment 1, the flow when parsing a full function
specialization would be

1. Found a full specialization of function.
2. Instantiate all possible primary function templates. 
3. Find the most suitable instantiation (here, the concept constrained is
chosen)
4. Then replace it with full specialization. (this is done in
`reregister_specialization` in `gcc/cp/pt.c`)

So when performing overloading in the main function, there would be one
instantiation and one full specialization to choose. (To be specific, those two
are in the hash table `decl_specialization` defined in `gcc/cp/pt.c`)


While in the c++17 mode, step 4 is broken. So there will be 2 implicit
instantiation to choose when overloading.

Step 4 is performed in the function `duplicate_decls` defined in
`gcc/cp/decl.c`.

Certain conditions must be satisfied to replace the instantiation.

The one failed here is:
"the compiler thinks the full specialization has a different concepts
constraint with primary template (because the primary template has contraints
but the full specialization doesn't)" 

So the reregistration is never triggered. This is the source of the bug.

After getting the whole picture, I simplify the test case as
https://godbolt.org/z/9MM6rEf77

----------------------- std=c++17 -fconcepts

template <typename T>
requires requires(T t) { ++t; }
void func(T &&arg)
{
}

template <>
void func(int&& arg)
{
}

int main()
{
    func(1);
}

-----------------------

I'll give more details in the next comment in case any developer would like to
fix it.

Reply via email to