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

            Bug ID: 105569
           Summary: -Waddress warns on dynamic_cast
           Product: gcc
           Version: 12.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: anton.reinhard at protonmail dot com
  Target Milestone: ---

compiling with -Waddress yields a useless warning compiling the following code:

Compiler version:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-bootstrap
--prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man
--infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/
--with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit
--enable-cet=auto --enable-checking=release --enable-clocale=gnu
--enable-default-pie --enable-default-ssp --enable-gnu-indirect-function
--enable-gnu-unique-object --enable-linker-build-id --enable-lto
--enable-multilib --enable-plugin --enable-shared --enable-threads=posix
--disable-libssp --disable-libstdcxx-pch --disable-werror
--with-build-config=bootstrap-lto --enable-link-serialization=1
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.1.0 (GCC) 

Compiled using:
$ g++ warn.cpp -Waddress
warn.cpp: In function ‘int main()’:
warn.cpp:12:22: warning: comparing the result of pointer addition ‘(((A*)ref) +
((sizetype)(*(long int*)((& ref)->B::_vptr.B + -24))))’ and NULL [-Waddress]
   12 |     bool b = nullptr == dynamic_cast<A*>(&ref);
      |              ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~

The file warn.cpp:
class A {};

class B : public virtual A {};

class C : public A {};

int main() {
    B* object = new B();
    B &ref = *object;

    // -Waddress warns here
    bool b = nullptr == dynamic_cast<A*>(&ref);

    // -Waddress doesn't warn anymore
    auto ptr = dynamic_cast<A*>(&ref); 
    bool b2 = ptr == nullptr;

    C* cobject = new C();
    C &cref = *cobject;

    // -Waddress also doesn't warn anymore
    bool b3 = nullptr == dynamic_cast<A*>(&cref);
}

The warning:
warn.cpp: In function ‘int main()’:
warn.cpp:12:22: warning: comparing the result of pointer addition ‘(((A*)ref) +
((sizetype)(*(long int*)((& ref)->B::_vptr.B + -24))))’ and NULL [-Waddress]
   12 |     bool b = nullptr == dynamic_cast<A*>(&ref);
      |              ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~

However, dynamic_cast should return nullptr if the cast failed, so this warning
seems invalid to me. I don't know if just the warning is in error or if the
produced code is buggy.
It only happens when the derived class inherits with virtual (see class C)
It doesn't warn in versions previous to gcc-12, or in any clang versions I've
tried which makes me think it's a bug and not me making a mistake.

Reply via email to