https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100723
Bug ID: 100723 Summary: [8/9/10/11] ICE in tsubst when using std::variant in templated class using CTAD Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: cadet.gabriel at gmail dot com Target Milestone: --- The following code compile in others compiler, but fails to compile on every version of g++ I've checked (8 to 12). As per bug reporting guidelines, I've added .ii file as an attachment. In this example, this code occured inside a noexcept specifier, but it also happened when writting a template classe to check if all types inside a std::variant respect some constexpr predicate. Strangely enough, if I use some static constexpr, the bug does not occurs. -------------------------------------------- #include <iostream> #include <type_traits> #include <variant> #include <vector> #include <unordered_map> #include <string> #define TEMPLATE_DECL_SUB \ template <typename, typename, typename...> class Map, \ class Other #define TEMPLATE_DECL \ template <TEMPLATE_DECL_SUB> template <TEMPLATE_DECL class Value, TEMPLATE_DECL_SUB> struct trait_impl { using value_t = Value<Map, Other>; using object_t = Map<Other, value_t>; using other_t = Other; using variant_t = std::variant<other_t, object_t *>; trait_impl(value_t const &) {} }; template <typename T> using trait = decltype(trait_impl{std::declval<T>()}); TEMPLATE_DECL struct test_type { using trait_t = trait<test_type>; using other_t = typename trait<test_type>::other_t; using variant_t = typename trait_t::variant_t; other_t _val; static constexpr bool noex = std::is_nothrow_constructible_v<other_t, Other>; //test_type() noexcept(noex): _val() {} // Works fine with this line instead of the next. test_type() noexcept(std::is_nothrow_constructible_v<other_t, Other>): _val() {} test_type(test_type const& oth) : _val(oth._val) {} }; int main(void) { test_type<std::unordered_map, int> t; return 0; } ------------------------------------------ I first found this bug in archlinux g++ packages, then used docker + self-compiled g++ to check whether it was only in the current arch version or in other as well. Here is g++12 output (I recompiled it to have some debug infos and confirm the bug still exist.) : ------------------------------------------ Using built-in specs. COLLECT_GCC=/home/phantomas/sources/gcc_from_source/build/out/bin/g++ COLLECT_LTO_WRAPPER=/home/phantomas/sources/gcc_from_source/build/out/libexec/gcc/x86_64-pc-linux-gnu/12.0.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc/configure --prefix=/home/phantomas/sources/gcc_from_source/build/out --with-linker-hash-style=gnu --with-system-zlib --enable-languages=c,c++ --enable-__cxa_atexit --enable-cet=auto --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-libunwind-exceptions --disable-werror Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 12.0.0 20210518 (experimental) (GCC) COLLECT_GCC_OPTIONS='-std=c++17' '-g3' '-Wall' '-Wextra' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'a-' /home/phantomas/sources/gcc_from_source/build/out/libexec/gcc/x86_64-pc-linux-gnu/12.0.0/cc1plus -E -quiet -v -dD -D_GNU_SOURCE tsubst_bug.cpp -mtune=generic -march=x86-64 -std=c++17 -Wall -Wextra -g3 -fworking-directory -fpch-preprocess -o a-tsubst_bug.ii ignoring nonexistent directory "/home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../x86_64-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0 /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/x86_64-pc-linux-gnu /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/backward /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/include /usr/local/include /home/phantomas/sources/gcc_from_source/build/out/include /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-std=c++17' '-g3' '-Wall' '-Wextra' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'a-' /home/phantomas/sources/gcc_from_source/build/out/libexec/gcc/x86_64-pc-linux-gnu/12.0.0/cc1plus -fpreprocessed a-tsubst_bug.ii -quiet -dumpdir a- -dumpbase tsubst_bug.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -g3 -Wall -Wextra -std=c++17 -version -o a-tsubst_bug.s GNU C++17 (GCC) version 12.0.0 20210518 (experimental) (x86_64-pc-linux-gnu) compiled by GNU C version 12.0.0 20210518 (experimental), GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 GNU C++17 (GCC) version 12.0.0 20210518 (experimental) (x86_64-pc-linux-gnu) compiled by GNU C version 12.0.0 20210518 (experimental), GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: f0735d336a82ba6e425f24ae91b2e265 tsubst_bug.cpp: In instantiation of ‘test_type<Map, Other>::test_type() [with Map = std::unordered_map; Other = int]’: tsubst_bug.cpp:44:40: required from here tsubst_bug.cpp:38:31: internal compiler error: in tsubst, at cp/pt.c:15652 38 | test_type() noexcept(std::is_nothrow_constructible_v<other_t, Other>): _val() {} | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0x6ad098 tsubst(tree_node*, tree_node*, int, tree_node*) ../../gcc/gcc/cp/pt.c:15652 0xaa1fb4 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/gcc/cp/pt.c:20685 0xabd5f7 tsubst(tree_node*, tree_node*, int, tree_node*) ../../gcc/gcc/cp/pt.c:16193 0xabd50b tsubst(tree_node*, tree_node*, int, tree_node*) ../../gcc/gcc/cp/pt.c:16086 0xabfe6d tsubst_template_args(tree_node*, tree_node*, int, tree_node*) ../../gcc/gcc/cp/pt.c:13421 0xaa2ef6 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/gcc/cp/pt.c:19627 0xaa60b6 maybe_instantiate_noexcept(tree_node*, int) ../../gcc/gcc/cp/pt.c:25706 0xaa5ca3 maybe_instantiate_noexcept(tree_node*, int) ../../gcc/gcc/cp/pt.c:25649 0x99866a mark_used(tree_node*, int) ../../gcc/gcc/cp/decl2.c:5626 0x8e0c43 build_over_call ../../gcc/gcc/cp/call.c:9490 0x8de9f8 build_new_method_call_1 ../../gcc/gcc/cp/call.c:10776 0x8e3891 build_new_method_call(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, tree_node*, int, tree_node**, int) ../../gcc/gcc/cp/call.c:10852 0x8e3891 build_special_member_call(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, tree_node*, int, int) ../../gcc/gcc/cp/call.c:10252 0x9b711c expand_default_init ../../gcc/gcc/cp/init.c:1992 0x9b711c expand_aggr_init_1 ../../gcc/gcc/cp/init.c:2107 0x9b98f6 build_aggr_init(tree_node*, tree_node*, int, int) ../../gcc/gcc/cp/init.c:1841 0x963e7c build_aggr_init_full_exprs ../../gcc/gcc/cp/decl.c:6899 0x963e7c check_initializer ../../gcc/gcc/cp/decl.c:7060 0x989701 cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int) ../../gcc/gcc/cp/decl.c:8054 0xa74967 cp_parser_init_declarator ../../gcc/gcc/cp/parser.c:21915 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. --------------------------------------------- If I remove the unordered_map, a parsing error seems to occurs, I'll add it here too to be thorough. Here is the code: --------------------------------------------- #include <iostream> #include <type_traits> #include <variant> #include <vector> #include <unordered_map> #include <string> #define TEMPLATE_DECL_SUB \ /*template <typename, typename, typename...> class Map, \*/ \ class Other #define TEMPLATE_DECL \ template <TEMPLATE_DECL_SUB> template <TEMPLATE_DECL class Value, TEMPLATE_DECL_SUB> struct trait_impl { using value_t = Value</*Map, */ Other>; //using object_t = Map<Other, value_t>; using other_t = Other; using variant_t = std::variant<other_t /*, object_t * */>; trait_impl(value_t const &) {} }; template <typename T> using trait = decltype(trait_impl{std::declval<T>()}); TEMPLATE_DECL struct test_type { using trait_t = trait<test_type>; using other_t = typename trait<test_type>::other_t; using variant_t = typename trait_t::variant_t; other_t _val; static constexpr bool noex = std::is_nothrow_constructible_v<other_t, Other>; //test_type() noexcept(noex): _val() {} // Works fine with this line instead of the next. test_type() noexcept(std::is_nothrow_constructible_v<other_t, Other>): _val() {} test_type(test_type const& oth) : _val(oth._val) {} }; int main(void) { test_type</* std::unordered_map, */ int> t; return 0; } ----------------------------------------------- And g++ output: ----------------------------------------------- Using built-in specs. COLLECT_GCC=/home/phantomas/sources/gcc_from_source/build/out/bin/g++ COLLECT_LTO_WRAPPER=/home/phantomas/sources/gcc_from_source/build/out/libexec/gcc/x86_64-pc-linux-gnu/12.0.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc/configure --prefix=/home/phantomas/sources/gcc_from_source/build/out --with-linker-hash-style=gnu --with-system-zlib --enable-languages=c,c++ --enable-__cxa_atexit --enable-cet=auto --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-libunwind-exceptions --disable-werror Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 12.0.0 20210518 (experimental) (GCC) COLLECT_GCC_OPTIONS='-std=c++17' '-g3' '-Wall' '-Wextra' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'a-' /home/phantomas/sources/gcc_from_source/build/out/libexec/gcc/x86_64-pc-linux-gnu/12.0.0/cc1plus -E -quiet -v -dD -D_GNU_SOURCE parse_bug.cpp -mtune=generic -march=x86-64 -std=c++17 -Wall -Wextra -g3 -fworking-directory -fpch-preprocess -o a-parse_bug.ii ignoring nonexistent directory "/home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../x86_64-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0 /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/x86_64-pc-linux-gnu /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/backward /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/include /usr/local/include /home/phantomas/sources/gcc_from_source/build/out/include /home/phantomas/sources/gcc_from_source/build/out/lib/gcc/x86_64-pc-linux-gnu/12.0.0/include-fixed /usr/include End of search list. COLLECT_GCC_OPTIONS='-std=c++17' '-g3' '-Wall' '-Wextra' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'a-' /home/phantomas/sources/gcc_from_source/build/out/libexec/gcc/x86_64-pc-linux-gnu/12.0.0/cc1plus -fpreprocessed a-parse_bug.ii -quiet -dumpdir a- -dumpbase parse_bug.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -g3 -Wall -Wextra -std=c++17 -version -o a-parse_bug.s GNU C++17 (GCC) version 12.0.0 20210518 (experimental) (x86_64-pc-linux-gnu) compiled by GNU C version 12.0.0 20210518 (experimental), GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 GNU C++17 (GCC) version 12.0.0 20210518 (experimental) (x86_64-pc-linux-gnu) compiled by GNU C version 12.0.0 20210518 (experimental), GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: f0735d336a82ba6e425f24ae91b2e265 parse_bug.cpp: In instantiation of ‘test_type<Other>::test_type() [with Other = int]’: parse_bug.cpp:44:21: required from here parse_bug.cpp:38:31: error: cannot convert ‘test_type<int>’ to ‘int’ in initialization 38 | test_type() noexcept(std::is_nothrow_constructible_v<other_t, Other>): _val() {} | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~