Given the test case below, it appears that while a pointer to a member function
(PTMF) is initialized properly, the check against a NULL pointer still fails. 
The same case passes properly on x86 and SH4 - it appears to be an ARM ABI
detail which causing the heartburn.

In most platforms, the member pointer (being __pfn and __delta) the __pfn uses
the LSB to determine if the PTMF is pointing to a virtual or static function,
and then uses the __delta as needed.  In the ARM case, since Thumb ISA needs
that LSB, the ARM C++ ABI designates the LSB of the __delta to make that
designation (and the __delta is also twice the actual adjustment needed).

Debugging the testcase shows the __pfn as 0, and the __delta as 1, which tells
me that it's offset 0 into the vtable to call the proper member function. 
Alas, the check against NULL seems to show that the logic to determine NULL
isn't checking both the __pfn and the LSB of the __delta (NULL is __pfn=0 and
LSB of __delta is 0).

Am I missing something, or is this a bug (I did a search on ARM,C++,ABI and
didn't turn up anything)?  Thanks in advance for any ideas/feedback.


Here is the testcase:


#include <iostream>

using namespace std;

class X {
        public:
                virtual void a(void)=0;
                virtual void b(void)=0;

                X(void);
                virtual ~X(void);

        protected:
        private:
                /* none */
};

X::X(void) {
        ;
}
X::~X(void) {
        ;
}
class Z : public X {
        public:
                void a(void);
                void b(void);
                Z(void);
                ~Z(void);
        protected:
        private:
};

Z::Z(void) {
;
}
Z::~Z(void) {
;
}

void Z::a(void) {
        cout << "Doing Z::a" << endl;
}

void Z::b(void) {
        cout << "Doing Z::b" << endl;
}


static int doit = 1;
static int donot = 0;

void f(X *obj) {
        void (X::*xp)(void) = 0;

        if (doit) {
                xp = &X::a;
        } else if (donot) {
                xp = &X::b;
        }

        if(xp!=0) {
                (obj->*xp)();
        } else {
                cout << "Failed! XP is still Zero" << endl;
        }
}

int main(int argc, char* argv[]) {
        Z myobj;

        f(&myobj);
        return 0;
}


-- 
           Summary: ARM C++ ABI mishap
           Product: gcc
           Version: 4.2.0
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: amallory at qnx dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29066

Reply via email to