Are there any caveats in C++ with constexpr / static function usage in volatile members?

Viewed 115

I need to have volatile member function in my class (which is trivial and has standard layout), so that class instances can be declared volatile (needed for memory-mapped register access).

However, I found that GCC is not willing to call static constexpr functions from volatile members. clang is just fine with that.

Here is the simplified code example: https://gcc.godbolt.org/z/36rE7h

#include <cstddef>
#include <cstdint>

class B {
public:
    static constexpr uint32_t genMask()
    {
        return 0xFF;
    }

    uint32_t get(size_t word) const volatile
    {
        constexpr uint32_t mask = genMask();

        return data[word] & mask;
    }
private:
    uint32_t data[5];
};

uint32_t fun()
{
    constexpr uint32_t my_mmio_reg_addr = 0x8000BEEF;
    volatile B *b = new (reinterpret_cast<uint32_t *>(my_mmio_reg_addr)) B;

    return b->get(0);
}

GCC complains with

In member function 'uint32_t B::get(size_t) const volatile':

13:43: error: 'this' is not a constant expression
13 |         constexpr uint32_t mask = genMask();
   |                                           ^

If I change

constexpr uint32_t mask = genMask();

with

constexpr volatile uint32_t mask = genMask();

GCC compiles code just fine, but then it treats mask as volatile, always re-reading it's value resulting in non-optimal code.

Why volatile member specifier affects local constexpr variables and static constexpr member functions? Is it a bug in GCC or some dark side of C++ spec? Why *this is somehow involved here, if it's only local variables and static member function involved?

1 Answers

It turns out to be already known GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80456

According to my testing issue appeared in GCC 4.9 for the first time and is not fix as of GCC 10.2.

Unfortunately, there is no fix for it yet in trunk as well.

Related