https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117280
Bug ID: 117280
Summary: Accessing a reference member of a volatile-qualified
class glvalue is misinterpreted as volatile read
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Keywords: rejects-valid
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: de34 at live dot cn
Target Milestone: ---
Currently GCC rejects th following example with a seemingly wrong reason.
https://godbolt.org/z/v9fKKEaGW
```
struct S { const int& ref; };
constexpr int n = 42;
template<class T>
constexpr int readref(T&& t) {
return static_cast<T&&>(t).ref;
}
static_assert(::readref(static_cast<volatile S&&>(S{n})) == 42, "");
```
<source>:9:58: error: non-constant condition for static assertion
9 | static_assert(::readref(static_cast<volatile S&&>(S{n})) == 42, "");
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
<source>:9:24: error: 'constexpr int readref(T&&) [with T = volatile S]' called
in a constant expression
9 | static_assert(::readref(static_cast<volatile S&&>(S{n})) == 42, "");
| ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:15: note: 'constexpr int readref(T&&) [with T = volatile S]' is not
usable as a 'constexpr' function because:
5 | constexpr int readref(T&& t) {
| ^~~~~~~
<source>:6:30: error: lvalue-to-rvalue conversion of a volatile lvalue
't.S::ref' with type 'const int&'
6 | return static_cast<T&&>(t).ref;
| ~~~~~~~~~~~~~~~~~~~~^~~
Compiler returned: 1 ~~~~~~~~~~~~~~~~~~~~^~~
It seems that the current standard wording doesn't treat evaluation of a
reference member itself as accessing the class object. So perhaps there
shouldn't be any volatile read, and this example should be accepted.
(A reference non-static data member behaves like it were an
"auto-dereferencing" pointer in many cases. But IIUC this example is not such a
case.)