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 {&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

Reply via email to