llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.35k stars 11.71k forks source link

[clang] crashes and misbehavior with member function template explicit specialization #111266

Open mizvekov opened 1 day ago

mizvekov commented 1 day ago

Clang crashes compiling the following valid example: https://godbolt.org/z/Kx916caT7

template<class T> struct S {
  template<int> auto foo();
  template<> auto foo<1>() {
    return [](auto x) { return x; };
  }
};
template struct S<void>;

What happens is that when instantiating the members of S, we lose track of the specialization kind of foo<1>, leading to us using the explicit specialization argument when instantiating the function definition.

The behavior for explicit instantiation doesn't match MSVC and EDG as well: https://godbolt.org/z/ejehb88zc

template<class T> struct A {
  int x;
  template<class U = void> static void f();
  template<> void f<int>() { (void)this->x; }
};
template struct A<int>;

Here clang eagerly instantiates f<int> and complains about usage of this in static function, while MSVC / EDG only do so when the definition is actually used.

llvmbot commented 1 day ago

@llvm/issue-subscribers-bug

Author: Matheus Izvekov (mizvekov)

Clang crashes compiling the following valid example: https://godbolt.org/z/Kx916caT7 ```C++ template<class T> struct S { template<int> auto foo(); template<> auto foo<1>() { return [](auto x) { return x; }; } }; template struct S<void>; ``` What happens is that when instantiating the members of S<int>, we lose track of the specialization kind of `foo<1>`, leading to us using the explicit specialization argument when instantiating the function definition. The behavior for explicit instantiation doesn't match MSVC and EDG as well: https://godbolt.org/z/ejehb88zc ```C++ template<class T> struct A { int x; template<class U = void> static void f(); template<> void f<int>() { (void)this->x; } }; template struct A<int>; ``` Here clang eagerly instantiates `f<int>` and complains about usage of `this` in static function, while MSVC / EDG only do so when the definition is actually used.
llvmbot commented 1 day ago

@llvm/issue-subscribers-c-1

Author: Matheus Izvekov (mizvekov)

Clang crashes compiling the following valid example: https://godbolt.org/z/Kx916caT7 ```C++ template<class T> struct S { template<int> auto foo(); template<> auto foo<1>() { return [](auto x) { return x; }; } }; template struct S<void>; ``` What happens is that when instantiating the members of S<int>, we lose track of the specialization kind of `foo<1>`, leading to us using the explicit specialization argument when instantiating the function definition. The behavior for explicit instantiation doesn't match MSVC and EDG as well: https://godbolt.org/z/ejehb88zc ```C++ template<class T> struct A { int x; template<class U = void> static void f(); template<> void f<int>() { (void)this->x; } }; template struct A<int>; ``` Here clang eagerly instantiates `f<int>` and complains about usage of `this` in static function, while MSVC / EDG only do so when the definition is actually used.
llvmbot commented 1 day ago

@llvm/issue-subscribers-clang-frontend

Author: Matheus Izvekov (mizvekov)

Clang crashes compiling the following valid example: https://godbolt.org/z/Kx916caT7 ```C++ template<class T> struct S { template<int> auto foo(); template<> auto foo<1>() { return [](auto x) { return x; }; } }; template struct S<void>; ``` What happens is that when instantiating the members of S<int>, we lose track of the specialization kind of `foo<1>`, leading to us using the explicit specialization argument when instantiating the function definition. The behavior for explicit instantiation doesn't match MSVC and EDG as well: https://godbolt.org/z/ejehb88zc ```C++ template<class T> struct A { int x; template<class U = void> static void f(); template<> void f<int>() { (void)this->x; } }; template struct A<int>; ``` Here clang eagerly instantiates `f<int>` and complains about usage of `this` in static function, while MSVC / EDG only do so when the definition is actually used.