Bug 109576 - access checking done on constexpr even if the access was done in the class itself when used inside a template
Summary: access checking done on constexpr even if the access was done in the class it...
Status: RESOLVED DUPLICATE of bug 97740
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2023-04-20 19:47 UTC by Alex Wang
Modified: 2025-09-03 14:13 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.7.1, 5.1.0
Last reconfirmed: 2023-04-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Wang 2023-04-20 19:47:55 UTC
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
Comment 1 Drea Pinski 2023-04-20 19:58:29 UTC
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;
```
Comment 2 Drea Pinski 2023-04-20 20:00:10 UTC
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.
Comment 3 Drea Pinski 2023-04-20 20:05:48 UTC
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
Comment 4 Alex Wang 2023-04-20 22:46:41 UTC
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?
Comment 5 Drea Pinski 2023-04-20 22:48:59 UTC
(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 :).
Comment 6 Drea Pinski 2023-04-20 22:49:45 UTC
(In reply to Andrew Pinski from comment #5)
> Yes and those are dups of each other too :).

Or at least related.
Comment 7 Patrick Palka 2025-09-03 14:13:48 UTC
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 ***