In C++, when there’s a class with multiple inheritance and one wants to cast a
pointer to it to the type of a base class which is not the first in the list,
like in this code:

class D: public B1, B2 { . . . };
D* d = get_some_D_possibly_NULL();
B2* b = d;

the pointer must be offset according to the position of the B2 subobject within
D. At the same time, if the pointer is NULL, it must remain NULL (4.10/3).
However, the situation is different when ‘this’ pointers or references are
cast, neither of which can be NULL.

g++ (tested on 3.4, 4.2 and 4.3) does this in a very straightforward way, at
least on x86-32:

    cmpl    $0, -12(%ebp)
    je      .L30
    movl    -12(%ebp), %eax
    addl    $12, %eax
    movl    %eax, -24(%ebp)
    jmp     .L32
.L30:
    movl    $0, -24(%ebp)
.L32:

If a reference is cast this way, GCC avoids comparison with 0 and a conditional
jump. At the same time, MSVC is more smart in this respect:

; esi = the pointer
; edi = esi + offset
    neg    esi
    sbb    esi, esi
    and    esi, edi

MSVC uses this branchless code for references as well, even though this check
is needless for standard-conforming code. GCC should adopt this approach as
well. It serves two purposes: firstly, it’s a small performance increase and
secondly, some programmers have come to expect NULL references and ‘this’
pointers to be casted successfully, even though it’s UB. For example, as
recently as yesterday someone posted on a forum that he returns NULL from
methods if this==NULL in order to be sure expressions like X* p =
x->foo()->bar() do not crash. They will -- when he uses GCC to compile the
code.

Even though programmers are supposed to know that static_cast<X *>(0)->foo() is
UB and null references are as well, most see no reason why that should
fail--but such a reason does exist. Having GCC handle this seems less evil than
crashing unpredictably.

Bottom line: GCC should use more efficient code as MSVC does, which will give a
performance increase (even though unnoticeable in most cases) and, more
importantly, will cause certain code to behave as expected, even though it’s
erroneous.


-- 
           Summary: Should cast pointers and references more efficiently and
                    safely
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: to dot roma dot from dot bugcc at qwertty dot com


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

Reply via email to