https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109576
Bug ID: 109576
Summary: Incorrect rejection of constexpr local var due to
private member even with visible conversion operator
Product: gcc
Version: 12.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: ts826848 at gmail dot com
Target Milestone: ---
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 {_}; }
private:
char chars_{'\0'};
};
constexpr static_string enum_name_v{};
constexpr const char* nonlocal_name = enum_name_v;
template
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:
: In instantiation of 'constexpr auto enum_name() [with auto V =
0]':
:17:22: required from here
:13:40: error: 'char static_string::chars_' is private within this
context
13 | constexpr const char* local_name = enum_name_v;
|^~~
: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