constexpr constructor static object initialization

Asked by Mark Rubin on 2018-02-03

New to launchpad.net but have been using GNU ARM Embedded Toolchain for almost a year. Fairly convinced this is a bug but following guidelines and asking here first.

When the compiling a static object whose constructor is defined with the "constexpr" keyword and is given const arguments, it should be compile-time constructed and placed in the initialized data section of the output object file. See the "constexpr constructor" section of http://en.cppreference.com/w/cpp/language/constexpr for other requirements on the constructor.

I believe this is the same bug as https://bugs.launchpad.net/gcc-arm-embedded/+bug/1560533 but that was dropped in 2016-04-13 with discussions about object initialization in the startup/init process. That is not the issue: The object should be compile-time constructed and need no run-time initialization.

Here is a simple test case showing the problem, along with proof that GCC on Intel handles it correctly. I just upgraded to gcc-arm-none-eabi-7-2017-q4-major and it shows the same problem as gcc-arm-none-eabi-6-2017-q1-update.

$ cat constexpr_constructor.cxx
#include <stdint.h>

typedef struct {
    volatile uint32_t register1;
    volatile uint32_t register2;
} RegistersTypedef;

#define R (RegistersTypedef*)0x12345678

class C {
  public:
    constexpr C(
    RegistersTypedef* const initializer)
    : initialized(initializer)
    {}
  protected:
    RegistersTypedef* const initialized;
};

C c(const_cast<RegistersTypedef*const>(R));

int main()
{
}

$ arm-none-eabi-g++ --version
arm-none-eabi-g++ (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ arm-none-eabi-g++ -c --std=c++11 constexpr_constructor.cxx

$ arm-none-eabi-nm -C constexpr_constructor.o
00000074 t _GLOBAL__sub_I_c
0000001c t __static_initialization_and_destruction_0(int, int)
00000000 W C::C(RegistersTypedef*)
00000000 W C::C(RegistersTypedef*)
00000000 n C::C(RegistersTypedef*)
00000000 B c
00000000 T main

$ g++ --version
g++ (SUSE Linux) 4.8.5
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -c --std=c++11 constexpr_constructor.cxx

$ nm -C constexpr_constructor.o
0000000000000000 D c
0000000000000000 T main

Note that gcc-arm places the object in the uninitialized data section ("B") and generates calls to run-time constructors whereas Linux/Intel/gcc places the statically-constructed object in the initialized ("D") section.

Thanks for gcc-arm -- it generates amazingly efficient code. Would like to see if this bug can be addressed as it prevents me from making my code as clean and const-correct as it could be.

Question information

Language:
English Edit question
Status:
Expired
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Last query:
2018-02-06
Last reply:
2018-02-22
Mark Rubin (go-embedded) said : #1

FWIW, the Linaro compiler does the same thing:

$ arm-eabi-c++ --version
arm-eabi-c++ (Linaro GCC 7.2-2017.11) 7.2.1 20171011
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ arm-eabi-c++ -c --std=c++11 constexpr_constructor.cxx

$ arm-eabi-nm -C constexpr_constructor.o
00000074 t _GLOBAL__sub_I_c
0000001c t __static_initialization_and_destruction_0(int, int)
00000000 W C::C(RegistersTypedef*)
00000000 W C::C(RegistersTypedef*)
00000000 n C::C(RegistersTypedef*)
00000000 B c
00000000 T main

So ... maybe (probably) in the upstream code. Did this, IMO important-for-embedded-applications optimization get dropped in the 5/6/7 GCC codebases?

I've also tried the ARM compilers with --std=c++14 and --std=c++17 and gotten the same results.

Launchpad Janitor (janitor) said : #2

This question was expired because it remained in the 'Open' state without activity for the last 15 days.