https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100754
Bug ID: 100754 Summary: Order of multiple inheritance can lead to illegal code jump Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: mgaron at pleora dot com Target Milestone: --- First time filing a bug, sorry for anything wrong I might be doing. Experienced with microblaze gcc v8.2.0, v9.2.0, on our existing code base. I made a simpler example program for sake of debugging. Simple Base class, with pure virtual function. Compiled in its own shared library: class Base { public: Base(int value); virtual ~Base() {} int GetValue(void); protected: virtual int ModInt(int value) = 0; private: int value; }; When used to create a derived class with multiple inheritance, the code generated seems to be wrong when the base class is specified after some other interface: This class too is compiled in its own shared library. #include <Base.h> class ILocalInterface { public: virtual ~ILocalInterface() {} virtual void PrintMsg(void) = 0; }; class Derived : public ILocalInterface, public Base {// This leads to a program crash! //: public Base, public ILocalInterface { // This works fine... public: Derived(int value); ~Derived() {} // ILocalInterface void PrintMsg(void) override; protected: // Base. int ModifyInt(int value) override; }; Used as-is in some test application, any call to ModInt() will cause an illegal instruction or segfault error. I created a dump of the .o file and got this: 00000128 <_ZN7Derived9ModifyIntEi>: int Derived::ModifyInt(int value) { 128: 3021ffdc addik r1, r1, -36 ... 000001a4 <_ZThn4_N7Derived9ModifyIntEi>: // ILocalInterface void PrintMsg(void) override; protected: // Base. int ModifyInt(int value) override; 1a4: 30a5fffc addik r5, r5, -4 1a8: b0000000 imm 0 1a8: R_MICROBLAZE_GOT_64 $LTHUNK2 1ac: e9940000 lwi r12, r20, 0 1b0: 98086000 bra r12 _ZThn4_N7Derived9ModifyIntEi symbol does get call appropriately, but it computes the address to jump to (_ZN7Derived9ModifyIntEi) based on an offset in the GOT. r20 is the register that holds the GOT for microblaze. When called, r20 has the value of the GOT of the Base.so library, while it should have the value of the Derived.so library. All other compilers I tried (arm64, arm32, x86_64) issue a simple local jump relative to the PC (2 instructions). Microblaze does support such jump. So in effect, this might have better to do with the Microblaze backend than the C++ frontend. Let me know if I should modify the affected component. Also, swapping the order of the interfaces in the declaration of the Derived class, no such assembly as above is created. Neither is it the case with simple inheritance. To me it looks highly suspicious that microblaze generates different code based on the order of inheritance. Also that the faulty code looks nothing like the other compiler backends. Will be happy to provide any assistance, further tests, patch trials, etc.