Created attachment 54241 [details] Minimal C++ file that reproduces the bug This seems similar but different from #107852. Starting with gcc 12 and continuing into the current trunk (git aa966d54ee4), the compiler emits a stringop overflow warning. In addition to the attachment: https://godbolt.org/z/3xorbqsha I would expect either of the following behaviors: - In line 20 (marked with "// !!!"), the compiler sees that even if `new` returned a nullptr for any reason, if execution continues in the make_vector() function, it can now assume that new_buffer is non-null, and therefore memset is safe. - Alternatively, if the compiler cannot deduce that, then the warning should not be generated, since the compiler cannot now what pointer will be returned by data(). gcc trunk (git aa966d54ee4) → spurious warning gcc 12.2.0 (Debian 12.2.0-13) → spurious warning gcc 11.3.0 (Debian 11.3.0-10) → no warning gcc 10.4.0 (Debian 10.4.0-6) → no warning clang 13 and 14 → no warning system type: Debian testing, x86_64 options during configure: Debian gcc reports: ../src/configure -v --with-pkgversion='Debian 12.2.0-13' --with-bugurl=file:///usr/share/doc/gcc-12/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-12 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-12-PBog5r/gcc-12-12.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-12-PBog5r/gcc-12-12.2.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu When I manually built it I used this: ../gcc-src/configure --enable-shared --disable-werror --enable-languages=c,c++ --enable-default-pie --enable-lto --enable-threads=posix --enable-initfini-array --with-linker-hash-style=gnu --disable-multilib complete commandline that triggers the bug: g++ -O2 -o foo repro.cpp compiler error message: ``` In function ‘Vector make_vector()’, inlined from ‘int main()’ at repro.cpp:36:31: repro.cpp:27:11: warning: ‘void* memset(void*, int, size_t)’ writing 128 bytes into a region of size 40 overflows the destination [-Wstringop-overflow=] 27 | memset(buffer.data(), 'A', new_size); | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ repro.cpp: In function ‘int main()’: repro.cpp:36:10: note: destination object ‘actual’ of size 40 36 | auto actual = make_vector(); | ^~~~~~ ``` preprocessed file (*.i*) that triggers the bug: See next comments, I can't figure out how to put more than one attachment in a single comment.
Preprocessed file see attachments, and output as generated by -v -save-temps here: $ g++ -v -o foo -O2 -std=c++20 -save-temps repro.cpp Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/12/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 12.2.0-13' --with-bugurl=file:///usr/share/doc/gcc-12/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-12 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-12-PBog5r/gcc-12-12.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-12-PBog5r/gcc-12-12.2.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 12.2.0 (Debian 12.2.0-13) COLLECT_GCC_OPTIONS='-v' '-o' 'foo' '-O2' '-std=c++20' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'foo-' /usr/lib/gcc/x86_64-linux-gnu/12/cc1plus -E -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE repro.cpp -mtune=generic -march=x86-64 -std=c++20 -O2 -fpch-preprocess -fasynchronous-unwind-tables -o foo-repro.ii ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/12" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/12/include-fixed" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/12 /usr/include/x86_64-linux-gnu/c++/12 /usr/include/c++/12/backward /usr/lib/gcc/x86_64-linux-gnu/12/include /usr/local/include /usr/include/x86_64-linux-gnu /usr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-o' 'foo' '-O2' '-std=c++20' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'foo-' /usr/lib/gcc/x86_64-linux-gnu/12/cc1plus -fpreprocessed foo-repro.ii -quiet -dumpdir foo- -dumpbase repro.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -O2 -std=c++20 -version -fasynchronous-unwind-tables -o foo-repro.s GNU C++20 (Debian 12.2.0-13) version 12.2.0 (x86_64-linux-gnu) compiled by GNU C version 12.2.0, GMP version 6.2.1, MPFR version 4.1.1-p1, MPC version 1.3.1, isl version isl-0.25-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C++20 (Debian 12.2.0-13) version 12.2.0 (x86_64-linux-gnu) compiled by GNU C version 12.2.0, GMP version 6.2.1, MPFR version 4.1.1-p1, MPC version 1.3.1, isl version isl-0.25-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: b9e5387ca128f541a98a8ca5afd00294 In function ‘Vector make_vector()’, inlined from ‘int main()’ at repro.cpp:36:31: repro.cpp:27:11: warning: ‘void* memset(void*, int, size_t)’ writing 128 bytes into a region of size 40 overflows the destination [-Wstringop-overflow=] 27 | memset(buffer.data(), 'A', new_size); | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ repro.cpp: In function ‘int main()’: repro.cpp:36:10: note: destination object ‘actual’ of size 40 36 | auto actual = make_vector(); | ^~~~~~ COLLECT_GCC_OPTIONS='-v' '-o' 'foo' '-O2' '-std=c++20' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'foo-' as -v --64 -o foo-repro.o foo-repro.s GNU assembler version 2.39.90 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.39.90.20230104 COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/:/usr/lib/gcc/x86_64-linux-gnu/12/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/12/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/:/usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/12/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/12/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-o' 'foo' '-O2' '-std=c++20' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'foo.' /usr/lib/gcc/x86_64-linux-gnu/12/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/12/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/12/lto-wrapper -plugin-opt=-fresolution=foo.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o foo /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/12/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/12 -L/usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/12/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/12/../../.. foo-repro.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/12/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/crtn.o COLLECT_GCC_OPTIONS='-v' '-o' 'foo' '-O2' '-std=c++20' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'foo.'
Created attachment 54242 [details] precompiled file as generated by -save-temps
Started with r12-145-gd1d01a66012a93cc.
Warns from #1 0x00000000013bc420 in warn_for_access<gimple*> (loc=2147485003, func=<function_decl 0x7ffff633ad00 memset>, exp=<gimple_call 0x7ffff60938e8>, opt=761, range=0x7fffffffd560, size=<integer_cst 0x7ffff63f42e8>, write=true, read=false, maybe=false) at /home/rguenther/src/gcc-12-branch/gcc/gimple-ssa-warn-access.cc:995 (gdb) l 990 } 991 992 if (write) 993 { 994 if (tree_int_cst_equal (range[0], range[1])) 995 warned = (func 996 ? warning_n (loc, opt, tree_to_uhwi (range[0]), 997 (maybe 998 ? G_("%qD may write %E byte into a region " 999 "of size %E") (gdb) p debug_gimple_stmt (exp) # .MEM_2 = VDEF <.MEM_23> memset (&MEM <char[32]> [(void *)&actual], 65, 128); on a path where actual.m_outline == nullptr for some unknown reason we reload actual.m_outline in the loop, likely because storing to it is thought to clobber actual.m_outline (which is initialized from a new expression). Note 'actual' escapes the function via the printf call and 'new' can inspect/clobber globals. We're also "bad" in computing points-to info because of the memset(buffer.data(), 'A', new_size); which with char* data() { if (m_outline) return m_outline; return reinterpret_cast<char*>(m_inline); } simply clobbers the whole object (with our points-to analysis). Helping the compiler and doing auto *b = buffer.m_outline; for (unsigned i = 0; i < 128; ++i) b[i] = 0; allows it to optimize and avoid the diagnostic. Using buffer.m_outline in the memset instead of buffer.data () would probably work as well.
GCC 12.3 is being released, retargeting bugs to GCC 12.4.
GCC 12.4 is being released, retargeting bugs to GCC 12.5.