https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90960
Bug ID: 90960 Summary: declaring a member function with a computed typedef is confused as a data member definition Product: gcc Version: 9.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: alisdairm at me dot com Target Milestone: --- Note that this bug is a real corner case unlikely to occur in production code, but bit us in experimental coding. In fact, there are two bugs lurking in this report (single test case), but it feels too obscure to tie up two issues! The following program should compile equivalently, regardless of the definition of the SHOW_BUG macro: #include <type_traits> #define SHOW_ERROR 1 using namespace std; template <typename T> struct why_me { #if defined(SHOW_ERROR) using what_the = conditional_t<is_const_v<T>, void() noexcept, void()>; #else using what_the = void() noexcept(is_const_v<T>); #endif what_the heck; }; template <typename T> void why_me<T>::heck() noexcept(is_const_v<T>) {} int main() { why_me<int> x = {}; x.heck(); why_me<int> y = {}; y.heck(); } However, when SHOW_ERROR is defined, we get the following errors: to_heck_with_it.cpp:20:6: error: no declaration matches 'void why_me<T>::heck()' 20 | void why_me<T>::heck() noexcept(is_const_v<T>) {} | ^~~~~~~~~ to_heck_with_it.cpp:16:13: note: candidate is: 'why_me<T>::what_the why_me<T>::heck' 16 | what_the heck; | ^~~~ to_heck_with_it.cpp:8:8: note: 'struct why_me<T>' defined here 8 | struct why_me { | ^~~~~~ to_heck_with_it.cpp: In instantiation of 'struct why_me<int>': to_heck_with_it.cpp:23:16: required from here to_heck_with_it.cpp:16:13: error: field 'why_me<int>::heck' invalidly declared function type 16 | what_the heck; | ^~~~ It is not clear why the last error claims a function type is invalid here (I believe it should be). However, there is a second bug lurking when we do not define SHOW_ERROR (the program compiles cleanly on other compilers): to_heck_with_it.cpp:20:6: error: declaration of 'void why_me<T>::heck() noexcept (is_const_v<T>)' has a different exception specifier 20 | void why_me<T>::heck() noexcept(is_const_v<T>) {} | ^~~~~~~~~ to_heck_with_it.cpp:16:13: note: from previous declaration 'void why_me<T>::heck()' 16 | what_the heck; | ^~~~ Here, the exception specifications are clearly the same, as they are even spelled the same, so the error is just wrong.