mercredi 8 avril 2020

constexpr function return global variable ref or global variable

I am writing a c++ program on an arduino nano (old bootloader). I tried to apply this approach for defining global variables of registers and other hardware. However I hit a weird bump when trying to use this global varialbe inside a constexpr function. Although my code compiled properly in Arduino IDE and I validated the results as well (memory addresses were correct etc), platformIO compained. The problem can be illustrated with the code below:

// globals.h
typedef volatile uint8_t register_t;
extern register_t g_PORTA;

// globals.S
.global g_PORTA
g_PORTA = 0x12

// main.h
class RegWrapper
{
  register_t& reg;
public:
  constexpr RegWrapper(register_t& r) : reg(r) {}
};

struct StaticFieldRef
{
  static constexpr register_t& Port = g_PORTB;  // Works properly
  static constexpr RegWrapper r = RegWrapper(Port);
};

struct ConstexprFunction
{
  static constexpr register_t& Port() // Arduino IDE doesn't complain, but PIO does
  {
    return g_PORTB;
  }
  static constexpr RegWrapper r = RegWrapper(Port());
};

//main.cpp just use the code somehow so it compiles

When trying to return a reference or a pointer to this global var, let alone applying a more complex expression to the return statement, I get an error:

note: 'static constexpr register_t& ConstexprFunction::Port() [with register_t = volatile unsigned char]' is not usable as a constexpr function because:
     static constexpr register_t& Port()
                                  ^
 error: expression 'g_PORTB' has side-effects

I understand that the compiler thinks I am trying to change the value of the global variable inside a constexpr context, but as I said the behaviour isn't consistent among pio, arduino ide and clang analyzer.

I am using the deviot plugin of sublime text.

PlatformIO, version 4.3.2a1
(platform: atmelavr; board: nanoatmega328; framework: arduino; build_type: debug)

Aucun commentaire:

Enregistrer un commentaire