https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67529
Bug ID: 67529
Summary: rx-elf C++ inherited class malformed call to
overridden methods
Product: gcc
Version: 5.2.0
Status: UNCONFIRMED
Severity: critical
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: ericns1 at spirilis dot net
Target Milestone: ---
Created attachment 36313
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36313&action=edit
Files needed to reproduce this bug using rx-elf-g++ cmd listed in bug report.
I've been able to reproduce what appears to be a glitch in the rx-elf-g++ C++
compiler. Originally found on GCC 4.8.4 (KPIT Cummins' GNURXv15.01-SP1 release
that pairs with Renesas' e2studio IDE), I have compiled GCC 5.2.0 from scratch
for the rx-elf target and confirmed similar ASM output.
In this example, I am writing an all-pure virtual method-laden class to define
an interface of sorts for a common hardware API, and writing implementation
classes which override the pure virtual methods with their correct
implementations. When a method inside the class attempts to execute another
method inside the class that was overriding a pure virtual method in the parent
class, the actual function call produced includes a JSR instruction against a
register value which appears to be derived from the in-SRAM address of the
object's data storage, not the actual in-Flash location of the function itself.
Example:
my_template_parent.h:
#ifndef MY_TEMPLATE_PARENT_H_
#define MY_TEMPLATE_PARENT_H_
#include
#include
#include
class MyTemplateParent {
public:
// prove it doesn't need to be a pure virtual function for the bug to
occur
virtual void begin(void) { return; };
virtual void check(void) = 0;
};
my_template.h:
#ifndef MY_TEMPLATE_H_
#define MY_TEMPLATE_H_
#include
#include
#include
#include "my_template_parent.h"
class MyTemplate : MyTemplateParent {
private:
uint8_t buffer[256];
unsigned int head;
uint8_t value = 0;
public:
__noinline
void begin(void) {
head = 0;
buffer[0] = value;
}
__noinline
void begin(uint8_t val1) {
buffer[1] = val1;
//begin(); // set buffer[0] to value (template argument)
check();
};
__noinline
void check(void) {
if (buffer[2] == 0xF3)
buffer[3] = 0xF3;
}
};
#endif /* MY_TEMPLATE_H_ */
Main provided by "main.cpp":
#include "my_template.h"
MyTemplate obj;
int main(void)
{
volatile unsigned long i = 0;
obj.begin(33);
while(1)
i++;
}
Compiled using: rx-elf-g++ -T rx2108.ld -ffunction-sections -fdata-sections
-Wl,--gc-sections -D__RX_LITTLE_ENDIAN__=1 -DCPPAPP -mlittle-endian-data
-mcpu=rx200 -nofpu -o a.out main.cpp
(rx2108.ld provided as an attachment)
The assembler output, rx-elf-objdump -C -dS, produces the following for the
MyTemplate-related functions:
fff80160 :
fff80160: 7e a6 push.l r6
fff80162: 71 06 fcadd #-4, r0, r6
fff80165: ef 60 mov.l r6, r0
fff80167: e3 61 mov.l r1, [r6]
fff80169: 03 nop
fff8016a: 3f 66 02rtsd#8, r6-r6
fff8016d :
fff8016d: 6e 6b pushm r6-r11
fff8016f: 71 06 fcadd #-4, r0, r6
fff80172: ef 60 mov.l r6, r0
fff80174: e3 61 mov.l r1, [r6]
fff80176: ec 6a mov.l [r6], r10
fff80178: f9 a6 41 00 mov.l #0, 260[r10]
fff8017c: ec 6a mov.l [r6], r10
fff8017e: ce ab 08 01 mov.b 264[r10], r11
fff80182: ec 6a mov.l [r6], r10
fff80184: c7 ab 04mov.b r11, 4[r10]
fff80187: 03 nop
fff80188: 3f 6b 07rtsd#28, r6-r11
fff8018b :
fff8018b: 6e 6b pushm r6-r11
fff8018d: 71 06 f8add #-8, r0, r6
fff80190: ef 60 mov.l r6, r0
fff80192: e3 61 mov.l r1, [r6]
fff80194: 81 62 mov.b r2, 4[r6]
fff80196: ec 6a mov.l [r6], r10
fff80198: cd 6b 04mov.b 4[r6], r11
fff8019b: c7 ab 05mov.b r11, 5[r10]
fff8019e: ec 6a mov.l [