10

gcc fails to compile the code below, while clang compiles ok. I have no control on the macro PORTB, as it is in a 3rd party library (avr).

Is it a gcc bug? How can I work around it in gcc? As a workaround is somehow possible to create a pre-processor macro which extracts the numerical value from PORTB?

Note this question is similar, but not identical to my previous question. It is also different from this question, where the developer has the flexibility to change the rhs of the assignment, thus avoiding the reinterpret_cast.

#include <iostream>
#include <cstdint>

#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))

struct PortB {
    static const uintptr_t port = reinterpret_cast<uintptr_t>(&PORTB);
};

int main() {
    std::cout << PortB::port << "\n";
    return 0;
}
Fabio
  • 2,105
  • 16
  • 26
  • 3
    Possible duplicate of [constexpr and initialization of a static const void pointer with reinterpret cast, which compiler is right?](https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas) – kmdreko Jan 14 '19 at 01:22
  • `g++ foo.cpp -std=c++11` works fine for me. – selbie Jan 14 '19 at 01:27
  • 1
    It used to work for me as well, but not anymore with latest `gcc` versions. I use `8.2.1`. See for instance: https://godbolt.org/z/TSOHN0 – Fabio Jan 14 '19 at 01:59
  • Does this answer your question? [How to create a constexpr pointer to a register on embedded system](https://stackoverflow.com/questions/67037386/how-to-create-a-constexpr-pointer-to-a-register-on-embedded-system) – user3840170 Dec 19 '21 at 17:23
  • @user3840170: The answer seems to be that it is impossible as you see in the linked question. It feels like a real language bug! It makes it impossible to use vendor provided register definitions anymore in constant expressions anymore. This breaks tons of my code... Now a have to write my own code parser to create linker scripts. Bad change to the language! – Klaus Nov 30 '22 at 15:41

1 Answers1

1

It seems reinterpret_cast is not allowed during compilation. Thus the newer version of the compiler simply is more conforming to the language. reinterpret_cast will not be allowed where a constexpr is required.

But maybe these workaround may help (compiles with g++ 9.2):

#include <iostream>
#include <cstdint>

#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))

struct PortB {
    static uintptr_t port; 
};

uintptr_t PortB::port = reinterpret_cast<uintptr_t>(&PORTB);
const uintptr_t freePort = reinterpret_cast<uintptr_t>(&PORTB);
#define macroPort reinterpret_cast<uintptr_t>(&PORTB)

int main() {
    std::cout << PortB::port << "\n";
    std::cout << freePort << "\n";
    std::cout << macroPort << "\n";
    return 0;
}
user5534993
  • 518
  • 2
  • 17
  • This will not work as einterpret_cast(&PORTB) is not a constant expression anymore. Youcan't use the expression nor the macro inside any constexpr expression like as NTTP or others. For me a real language bug! – Klaus Nov 30 '22 at 15:44