My apologies in advance for the title. I'm honestly not sure how to summarize this. GCC appears to incorrectly flag the creation of a constexpr local variable when a conversion operator is used that accesses a private member of a class. According to Godbolt, the code compiles under Clang 5.0.0-16.0.0 and the MSVC 19.14-19.latest, but GCC 7.1 and up rejects the code. (For a little bit of context, I ran into this when using Neargye/magic_enum for some enum reflection, and I create some constexpr local variables to hold stringified enum names) Here is the heavily reduced code ([Godbolt](https://godbolt.org/z/hGTMWvPrz)): struct static_string { constexpr operator const char*() const { return {&chars_}; } private: char chars_{'\0'}; }; constexpr static_string enum_name_v{}; constexpr const char* nonlocal_name = enum_name_v; template<auto V> constexpr auto enum_name() { constexpr const char* local_name = enum_name_v; return local_name; } auto n = enum_name<0>(); GCC complains about local_name: <source>: In instantiation of 'constexpr auto enum_name() [with auto V = 0]': <source>:17:22: required from here <source>:13:40: error: 'char static_string::chars_' is private within this context 13 | constexpr const char* local_name = enum_name_v; | ^~~~~~~~~~~ <source>:4:10: note: declared private here 4 | char chars_{'\0'}; | ^~~~~~ Compiler returned: 1 This seems like valid C++ to me. enum_name_v should be convertible via the operator string_view, and I'm not sure why the visibility of chars_ is relevant at all. In addition, some non-visibility-related changes gets the code to compile, which seems inconsistent with this being a visibility issue: - Making `local_name` a non-local variable (e.g., `nonlocal_name`) - Making `local_name` non-`constexpr` - Making `enum_name` a non-template function
Another testcase: ``` struct static_string { constexpr operator const char*() const { return &chars_; } private: char chars_{'\0'}; }; constexpr static_string enum_name_v{}; template<int V> struct s{ static constexpr const char* local_name = enum_name_v; }; auto t = s<0>::local_name; ```
Another one: ``` struct static_string { constexpr operator const char*() const { return &chars_; } private: char chars_{'\0'}; }; constexpr static_string enum_name_v{}; template<int V> constexpr const char* local_name = enum_name_v; auto t = local_name<0>; ``` Confirmed.
Another testcase: ``` struct static_string { constexpr operator const char*() const { return &chars_; } constexpr static_string() : chars_(0) {} private: char chars_ ;//= '\0'; }; constexpr static_string enum_name_v{}; template<int V> struct s{ static constexpr const char* local_name = enum_name_v; }; auto t = s<0>::local_name; ``` Note the above fails in GCC 4.6.1 differently: <source>:12:51: error: '(const char*){'\000'}' is not a constant expression
Just realized my previous searches were only searching the summary. Is this bug a duplicate of either https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96716 and/or https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97740?
(In reply to Alex Wang from comment #4) > Just realized my previous searches were only searching the summary. > > Is this bug a duplicate of either > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96716 and/or > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97740? Yes and those are dups of each other too :).
(In reply to Andrew Pinski from comment #5) > Yes and those are dups of each other too :). Or at least related.
let's call this a dup of PR97740 (which is marked as a regression and has been recently fixed on trunk) *** This bug has been marked as a duplicate of bug 97740 ***