From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21223 invoked by alias); 4 Sep 2011 18:45:44 -0000 Received: (qmail 21208 invoked by uid 22791); 4 Sep 2011 18:45:41 -0000 X-SWARE-Spam-Status: No, hits=-2.9 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from localhost (HELO gcc.gnu.org) (127.0.0.1) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 04 Sep 2011 18:45:27 +0000 From: "redi at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/50282] pointer-to-member cast works incorrectly Date: Sun, 04 Sep 2011 18:45:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: redi at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2011-09/txt/msg00259.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50282 --- Comment #5 from Jonathan Wakely 2011-09-04 18:45:24 UTC --- The problem is is your code, not gcc The type of &T4::f is void(T2::*)() not void(T4::*)() so when you cast the pointer to void(T4::*)() you are not casting back to the original type. You can fix the code by using reinterpret_cast for the cases that use the expression &T4::f, instead of reinterpret_cast For what it's worth, clang gives exactly the same result as g++ for a reduced version of your program: // define class N with no member, // we just need a type void(N::*)() of which an object can hold a pointer-to-member-function class N {} ; // define class T1 & T3 with some member data/functions // so that an object of class T4 which derives from T1 & T2 & T3 // will has its base object of type T2 have different address from the object itself. class T1 { public: char c ; int i ; } ; class T3:virtual public T1 { public: int i3 ; public: virtual void f2() { __builtin_printf("Foo3 !! this=%p\n", (void*)this); } ; } ; // define class T2 // T2 has a memmber function f, which our pointer-to-member-function will point to. // as T4 derives from T2 as a public base type, this function is an accessable from T4 ; // the function outputs the value of 'this' pointer, which i expect it always points to an object of T2. class T2 { public: int i2 ; public: virtual void f() { __builtin_printf("Foo2 !! this=%p\n", (void*)this); } ; } ; // define class T4, which simply derives from T1&T2&T3 class T4:public virtual T1, public T3, public T2 {} ; int main(int, char**) { T4 t4 ; void (N::*pfn)() = 0; void(T4::*pf4)() = &T4::f ; // this line shows the address of t4 and its base object t4.t2 differ ; __builtin_printf("AddressOf t4=%p, t4.t2=%p\n", (void*)(&t4), (void*)(&(T2&)(t4))); { __builtin_printf("\nwhat i expect:\n"); // the following lines show what i expect to see: // no matter what form the function call is, the function tells me the address of t4.t2 t4.f() ; (t4.*(&T4::f))() ; (t4.*pf4)() ; } { __builtin_printf("\nTestCase1:\n"); __builtin_printf("pfn assignment: pfn = reinterpret_cast(&T4::f) \n"); __builtin_printf("Function call form: (t4.*reinterpret_cast( pfn )() \n"); // Case1: // pfn is assigned directly from &T4::f, // but actually, its value shows that is &T2::f pfn= reinterpret_cast(&T4::f) ; // comparing with the result i memtioned above, this is not what i want. (t4.*reinterpret_cast(pfn))() ; } { __builtin_printf("\nTestCase2:\n"); __builtin_printf( "pfn assignment: pfn = reinterpret_cast(pf4) \n"); __builtin_printf("Function call form: (t4.*reinterpret_cast( pfn )() \n"); // Case2: pfn is transfromed from pf4, which is defined as type void(T4::*)(), and its value // has been correctly assigned as &T4::f, not &T2::f pfn = reinterpret_cast(pf4) ; // this time, the function call works correctly (t4.*reinterpret_cast(pfn))() ; } { __builtin_printf("\nTestCase3:\n"); // Case3: // this case exactly follows the standered draft, if anyone might say // in the above casese i used a lvalue(pfn), // this time, i have rvalue only, but it's obviously not functioning. __builtin_printf("Function call form: (t4.*reinterpret_cast( reinterpret_cast(&T4::f)))() \n"); (t4.*reinterpret_cast( reinterpret_cast(&T4::f) ))() ; } } When the 1st and 3rd tests are altered to use reinterpret_cast it gives the results you expect so I think this is invalid