https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82336
Bug ID: 82336 Summary: GCC requires but does not emit defaulted constructors in certain cases Product: gcc Version: 7.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: m101010a at gmail dot com Target Milestone: --- When compiling the following source file, gcc requires a definition for bar::bar() but does not emit one, causing a linker error: $ cat x.cpp struct foo { int x = 5; }; struct bar : foo { bar() = default; }; struct baz { bar x; }; void qux(baz = {}){} int main() { qux(); } $ g++ -v -Wall -Wextra x.cpp Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /build/gcc-multilib/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp Thread model: posix gcc version 7.1.1 20170630 (GCC) COLLECT_GCC_OPTIONS='-v' '-std=c++11' '-Wall' '-Wextra' '-g' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/cc1plus -quiet -v -D_GNU_SOURCE x.cpp -quiet -dumpbase x.cpp -mtune=generic -march=x86-64 -auxbase x -g -Wall -Wextra -std=c++11 -version -o /tmp/ccwPoekN.s GNU C++11 (GCC) version 7.1.1 20170630 (x86_64-pc-linux-gnu) compiled by GNU C version 7.1.1 20170630, GMP version 6.1.2, MPFR version 3.1.5-p2, MPC version 1.0.3, isl version isl-0.18-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../x86_64-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1 /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1/x86_64-pc-linux-gnu /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1/backward /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/include /usr/local/include /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/include-fixed /usr/include End of search list. GNU C++11 (GCC) version 7.1.1 20170630 (x86_64-pc-linux-gnu) compiled by GNU C version 7.1.1 20170630, GMP version 6.1.2, MPFR version 3.1.5-p2, MPC version 1.0.3, isl version isl-0.18-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 53125f87ce78f0cf5a177bd50a2fd619 COLLECT_GCC_OPTIONS='-v' '-std=c++11' '-Wall' '-Wextra' '-g' '-shared-libgcc' '-mtune=generic' '-march=x86-64' as -v --64 -o /tmp/ccXARTmy.o /tmp/ccwPoekN.s GNU assembler version 2.28.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.28.0.20170506 COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-std=c++11' '-Wall' '-Wextra' '-g' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccvOLjqj.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 --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../.. /tmp/ccXARTmy.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../lib/crtn.o /tmp/ccXARTmy.o: In function `main': /home/m42a/tmp/gcc-bug/x.cpp:5: undefined reference to `bar::bar()' collect2: error: ld returned 1 exit status Since bar's constructor is declared and defaulted, it should exist. This behavior appears in every version since 4.8, but not in 4.7.4. It occurs at all optimization levels, and on both Linux and MinGW. Removing the explicit declaration of bar's constructor does not fix the issue, but many other small changes do. Removing foo::x's initializer fixes it, and so does adding an initializer to baz::x ("bar x{}", "bar x = {}", and "bar x = bar()" all work), and changing qux's parameter to "baz = baz{}" or "baz = baz()", and providing an explicit parameter when calling qux, even if that parameter is just "{}".