https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95663

            Bug ID: 95663
           Summary: static_cast checks for null even when the pointer is
                    dereferenced
           Product: gcc
           Version: 10.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jzwinck at gmail dot com
  Target Milestone: ---

Consider this C++ code:

    struct Base1
    {
        int x;
    };

    struct Base2
    {
        int y;
    };

    struct Derived : Base1, Base2
    {
        int get_y() const { return y; }
    };

    int field(Base2* base)
    {
        return static_cast<Derived*>(base)->y;
    }

    int getter(Base2* base)
    {
        return static_cast<Derived*>(base)->get_y();
    }

Both field() and getter() produce this with -O2 or -O3:

    test    rdi, rdi
    je      .L2
    mov     eax, DWORD PTR [rdi]
    ret
    .L2:
    mov     eax, DWORD PTR ds:4
    ud2

That's fair, it traps if we dereference a null pointer.  But I need the best
performance and don't want the null check, so I add
-fno-isolate-erroneous-paths-dereference and see:

    lea     rax, [rdi-4]
    test    rdi, rdi
    cmovne  rdi, rax
    mov     eax, DWORD PTR [rdi+4]
    ret

If I read that correctly, it checks if the pointer is null so it can
dereference 0x4 instead of 0x0.  That's hardly an improvement over the naive
and optimal code:

    mov     eax, DWORD PTR [rdi]
    ret

Which is what Clang generates for field() in all versions through 10, and for
getter() up to 3.6 (3.7 through 10 generate a cmovne like GCC with no-isolate).

I tried adding __attribute__((nonnull)) to the function declarations, but it
didn't help.

Live demo: https://godbolt.org/z/XnhZoz

Reply via email to