Base class with pure virtual method must have inline constructor

Bug #1605158 reported by Konrad Adasiewicz
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
GNU Arm Embedded Toolchain
New
Undecided
Unassigned

Bug Description

Example of behaviour:

This links:

 class A {
 public:
  A() {}
  virtual void foo() = 0;
 };

 class B : public A {
 public:
  void foo() {}
 };

This does not link:

 class A {
 public:
  A();
  virtual void foo() = 0;
 };

 A::A() {}

 class B : public A {
 public:
  void foo() {}
 };

When instantianing B object.

Linker flags:
-mcpu=cortex-m3 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -pedantic -Wunused -Wuninitialized -Wall -Wextra -g3 -Xlinker --gc-sections --specs=nano.specs

Linking exits with an error:

c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-abort.o): In function `abort':
abort.c:(.text.abort+0xa): undefined reference to `_exit'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-signalr.o): In function `_kill_r':
signalr.c:(.text._kill_r+0xe): undefined reference to `_kill'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-signalr.o): In function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x10): undefined reference to `_write'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
c:/eclipsearm/toolchain/5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/../../../../arm-none-eabi/lib/armv7-m\libg_nano.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x10): undefined reference to `_read'
collect2.exe: error: ld returned 1 exit status

Toolchain version:
arm-none-eabi-gcc.exe (GNU Tools for ARM Embedded Processors) 5.2.1 20151202 (release) [ARM/embedded-5-branch revision 231848]

Revision history for this message
Andre Vieira (andre-simoesdiasvieira) wrote :

Hi Konrad,

I haven't tried to reproduce your issue but I quickly noticed that you are using --specs=nano.specs without also specifying either --specs=rdimon.specs or --specs=nosys.specs.

Could you try adding --specs=rdimon.specs and see if that solves the issue?

Cheers,
Andre

Revision history for this message
Konrad Adasiewicz (omicronns) wrote :

Andre,

I do not want to use dynamic memory allocation, but when I add --specs=nosys.specs or --specs=rdimon.specs to linker flags, it links with malloc call also. So what I want to achieve is pure virtual functions, without inline constructor and without dynamic memory allocation. Is that possible? Why compiler looks for this system functions when constructor is not inlined?

Thanks
Konrad

Revision history for this message
Andre Vieira (andre-simoesdiasvieira) wrote :

Hi Konrad,

I'm trying to understand where the dynamic allocation is coming from in your example. Can you send us a reduced test case that I can compile?

Cheers,
Andre

Revision history for this message
Konrad Adasiewicz (omicronns) wrote :

Hi Andre,

I attach simple example of the problem.

Regards
Konrad

Revision history for this message
Konrad Adasiewicz (omicronns) wrote :

Also, even inlined constructor version, does not work without optimization enabled (-O0).

Revision history for this message
Andre Vieira (andre-simoesdiasvieira) wrote :

Hi Konrad,

OK so in your example to get what you call the "non-inline constructor" to work, you need to define your own __cxa_pure_virtual () function to prevent it linking with the one in libstdc++. The implementation of __cxa_pure_virtual in libstdc++ uses writestr which is why you need --specs=nano.specs or --specs=rdimon.specs, pulling newlib's reentrant functions which use the embedded signal handling, which uses malloc...

So overriding __cxa_pure_virtual like:
extern "C" void __cxa_pure_virtual() { /* error or abort or hang? */ }

will get rid of your issue in the second compilation command.

What I am not understanding is why the first one optimizes away the constructor and the second one doesn't... I need to investigate further to figure this out.

Hope that helps.

Cheers,
Andre

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Bug attachments

Remote bug watches

Bug watches keep track of this bug in other bug trackers.