Created attachment 44941 [details] patch to trigger the problem As mentioned in following sub-thread: https://gcc.gnu.org/ml/gcc-patches/2018-10/msg01885.html There's violation of hash table in type_specializations hash table. Attached patch exposes that. $ ./xg++ -B. /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/template/ttp23.C -c /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/template/ttp23.C: In instantiation of ‘struct B<A>’: /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/template/ttp23.C:15:8: required from here /home/marxin/Programming/gcc/gcc/testsuite/g++.dg/template/ttp23.C:8:17: internal compiler error: in equal, at cp/pt.c:1699 8 | friend bool foo (const B<Q>& a); | ^~~ 0x9c1b40 spec_hasher::equal(spec_entry*, spec_entry*) /home/marxin/Programming/gcc/gcc/cp/pt.c:1698 0xa48639 hash_table<spec_hasher, xcallocator>::find_with_hash(spec_entry* const&, unsigned int) /home/marxin/Programming/gcc/gcc/hash-table.h:863 0x9e51f7 lookup_template_class_1 /home/marxin/Programming/gcc/gcc/cp/pt.c:9353 0x9e785d lookup_template_class(tree_node*, tree_node*, tree_node*, tree_node*, int, int) /home/marxin/Programming/gcc/gcc/cp/pt.c:9680 0x9f46a4 tsubst_aggr_type /home/marxin/Programming/gcc/gcc/cp/pt.c:12685 0x9ff5ac tsubst(tree_node*, tree_node*, int, tree_node*) /home/marxin/Programming/gcc/gcc/cp/pt.c:14333 0x9ff527 tsubst(tree_node*, tree_node*, int, tree_node*) /home/marxin/Programming/gcc/gcc/cp/pt.c:14324 0x9fdb8b tsubst_arg_types /home/marxin/Programming/gcc/gcc/cp/pt.c:13930 0x9fe22e tsubst_function_type /home/marxin/Programming/gcc/gcc/cp/pt.c:14071 0xa018c3 tsubst(tree_node*, tree_node*, int, tree_node*) /home/marxin/Programming/gcc/gcc/cp/pt.c:14808 0x9f5dd1 tsubst_function_decl /home/marxin/Programming/gcc/gcc/cp/pt.c:12949 0x9f927f tsubst_template_decl /home/marxin/Programming/gcc/gcc/cp/pt.c:13253 0x9fa86b tsubst_decl /home/marxin/Programming/gcc/gcc/cp/pt.c:13355 0x9febb7 tsubst(tree_node*, tree_node*, int, tree_node*) /home/marxin/Programming/gcc/gcc/cp/pt.c:14251 0x9e9f42 tsubst_friend_function /home/marxin/Programming/gcc/gcc/cp/pt.c:10316 0x9ef597 instantiate_class_template_1 /home/marxin/Programming/gcc/gcc/cp/pt.c:11365 0x9ef816 instantiate_class_template(tree_node*) /home/marxin/Programming/gcc/gcc/cp/pt.c:11430 0xa90c52 complete_type(tree_node*) /home/marxin/Programming/gcc/gcc/cp/typeck.c:138 0x8ea857 start_decl_1(tree_node*, bool) /home/marxin/Programming/gcc/gcc/cp/decl.c:5278 0x91285f start_decl(cp_declarator const*, cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) /home/marxin/Programming/gcc/gcc/cp/decl.c:5241
May I please ping this? I would like to finish the hast table sanitization patch in this stage1.
In the ttp23.C testcase we're comparing B<Q> and B<Q>. In one case the template argument is <tree_vec 0x7fffeab33920 length:1 elt:0 <template_template_parm 0x7fffeab3ad20 VOID align:8 warn_if_not_align:0 symtab:0 alias-set -1 structural-equality index 0 level 1 orig_level 2 chain <template_decl 0x7fffea9f8b80 Q>>> and the other is <tree_vec 0x7fffeab33560 length:1 elt:0 <template_template_parm 0x7fffeab3a348 VOID align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffeab25c78 index 0 level 1 orig_level 1 chain <template_decl 0x7fffea9f8680 Q>>> same_type_p says they're same, so comp_template_args returns true. One of the template_template_parms has TYPE_CANONICAL, so we hash it as: 1905 if (TYPE_CANONICAL (arg)) 1906 return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)), 1907 val); but the other type doesn't have a canonical type: 1910 /* Otherwise just compare the types during lookup. */ 1911 return val; so the hashes end up being different.
An idea would be to hash TEMPLATE_TEMPLATE_PARMs differently in iterative_hash_template_arg: hash its TEMPLATE_TYPE_PARM_INDEX and TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL, so that when they compare equal, they hash equal.
Or maybe just @@ -1879,6 +1888,9 @@ iterative_hash_template_arg (tree arg, hashval_t val) return val; } + case TEMPLATE_TEMPLATE_PARM: + return val; + default: break; }
(In reply to Marek Polacek from comment #4) > Or maybe just > > @@ -1879,6 +1888,9 @@ iterative_hash_template_arg (tree arg, hashval_t val) > return val; > } > > + case TEMPLATE_TEMPLATE_PARM: > + return val; > + > default: > break; > } Thank you Marek for working on that. If I apply both my and your patches I've got: $ cat ba.ii template < typename > struct A; template < typename > class B { public: typedef int value_type; typedef int pointer; typedef int reference; typedef int const_reference; typedef long size_type; typedef long difference_type; typedef int iterator; }; template < typename _Tp > class _Bitmap_counter { typedef B< A< _Tp > > _BPVector; typedef typename _BPVector::size_type _Index_type; typedef _Tp pointer; public: _Bitmap_counter(_BPVector); }; B< long > a; template < typename > class bitmap_allocator { typedef long size_type; typedef long difference_type; typedef int pointer; struct _Alloc_block; typedef A< _Alloc_block * > _Block_pair; typedef B< _Block_pair > _BPVector; static _BPVector b; static _Bitmap_counter< _Alloc_block * > d; }; template < typename _Tp > _Bitmap_counter< typename bitmap_allocator< _Tp >::_Alloc_block * > bitmap_allocator< _Tp >::d(b); template class B< A< bitmap_allocator< wchar_t >::_Alloc_block * > >; template class bitmap_allocator< char >; $ /home/marxin/Programming/gcc2/objdir/./gcc/xgcc -B/home/marxin/Programming/gcc2/objdir/./gcc ba.ii ba.ii: In instantiation of ‘_Bitmap_counter<bitmap_allocator<char>::_Alloc_block*> bitmap_allocator<char>::d’: ba.ii:8:17: required from here ba.ii:6:127: internal compiler error: in instantiate_decl, at cp/pt.c:24494 6 | template < typename _Tp > _Bitmap_counter< typename bitmap_allocator< _Tp >::_Alloc_block * > bitmap_allocator< _Tp >::d(b); | ^ 0x9a3dea instantiate_decl(tree_node*, bool, bool) ../../gcc/cp/pt.c:24493 0x8e1cf3 mark_used(tree_node*, int) ../../gcc/cp/decl2.c:5561 0x9aca07 tsubst_copy ../../gcc/cp/pt.c:15714 0x997e37 tsubst_copy ../../gcc/cp/pt.c:15534 0x997e37 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/cp/pt.c:19483 0x999f64 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/cp/pt.c:19606 0x99ae44 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/cp/pt.c:19244 0x9a7348 tsubst_copy_and_build(tree_node*, tree_node*, int, tree_node*, bool, bool) ../../gcc/cp/pt.c:18248 0x9a7348 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc/cp/pt.c:17924 0x9aaae4 tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) ../../gcc/cp/pt.c:17015 0x9aaae4 tsubst_init ../../gcc/cp/pt.c:15493 0x9a27d1 regenerate_decl_from_template ../../gcc/cp/pt.c:24163 0x9a27d1 instantiate_decl(tree_node*, bool, bool) ../../gcc/cp/pt.c:24707 0x9bc031 do_type_instantiation(tree_node*, tree_node*, int) ../../gcc/cp/pt.c:24024 0x975f37 cp_parser_explicit_instantiation ../../gcc/cp/parser.c:17206 0x9785b1 cp_parser_declaration ../../gcc/cp/parser.c:13190 0x978c9f cp_parser_translation_unit ../../gcc/cp/parser.c:4701 0x978c9f c_parse_file() ../../gcc/cp/parser.c:41181 0xa82ce0 c_common_parse_file() ../../gcc/c-family/c-opts.c:1156 $ g++-8 ba.ii -c [OK]
Created attachment 46387 [details] patch to ignore type_canonical for TTP Does this work better?
Apparently, this is not an issue any longer.
So the issue is still present: https://gcc.gnu.org/ml/gcc-regression/2019-06/msg00144.html I'm testing: https://gcc.gnu.org/bugzilla/attachment.cgi?id=46387&action=diff right now
(In reply to Martin Liška from comment #8) > So the issue is still present: > https://gcc.gnu.org/ml/gcc-regression/2019-06/msg00144.html > > I'm testing: > https://gcc.gnu.org/bugzilla/attachment.cgi?id=46387&action=diff right now So with patch I still see couple of ICEs remaining: FAIL: g++.dg/cpp0x/udlit-template.C -std=c++14 (internal compiler error) FAIL: g++.dg/cpp0x/udlit-template.C -std=c++14 (test for excess errors) FAIL: g++.dg/cpp0x/udlit-template.C -std=c++17 (internal compiler error) FAIL: g++.dg/cpp0x/udlit-template.C -std=c++17 (test for excess errors) FAIL: g++.dg/cpp0x/variadic98.C -std=c++17 (internal compiler error) FAIL: g++.dg/cpp0x/variadic98.C -std=c++17 (test for excess errors) FAIL: g++.dg/cpp1y/feat-cxx14.C (test for excess errors) FAIL: g++.dg/cpp1z/feat-cxx1z.C -std=gnu++17 (test for excess errors) FAIL: g++.dg/cpp1z/pr85569.C -std=c++17 (test for excess errors) FAIL: g++.dg/cpp2a/feat-cxx2a.C (test for excess errors) FAIL: g++.dg/tm/pr46646.C -std=gnu++14 (internal compiler error) FAIL: g++.dg/tm/pr46646.C -std=gnu++14 (test for excess errors) One reduced test-case: $ cat 1.ii template <char...> int operator"" _abc(); template <> int operator"" _abc(); $ ./xg++ -B. 1.ii -c hash table checking failed: equal operator returns true for a pair of values with a different hash value 1.ii:2:33: internal compiler error: in hashtab_chk_error, at hash-table.h:1022 2 | template <> int operator"" _abc(); | ^ 0xaf623e hashtab_chk_error /home/marxin/Programming/gcc/gcc/hash-table.h:1022 0xb83ef9 hash_table<spec_hasher, false, xcallocator>::find_slot_with_hash(spec_entry* const&, unsigned int, insert_option) /home/marxin/Programming/gcc/gcc/hash-table.h:963 0xafe5d8 register_specialization /home/marxin/Programming/gcc/gcc/cp/pt.c:1566 0xb05860 check_explicit_specialization(tree_node*, tree_node*, int, int, tree_node*) /home/marxin/Programming/gcc/gcc/cp/pt.c:3237 0x9aa99d grokfndecl /home/marxin/Programming/gcc/gcc/cp/decl.c:9218 0x9b6999 grokdeclarator(cp_declarator const*, cp_decl_specifier_seq*, decl_context, int, tree_node**) /home/marxin/Programming/gcc/gcc/cp/decl.c:12803 0x9993f2 start_decl(cp_declarator const*, cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) /home/marxin/Programming/gcc/gcc/cp/decl.c:5062 0xab7026 cp_parser_init_declarator /home/marxin/Programming/gcc/gcc/cp/parser.c:20357 0xac6cab cp_parser_single_declaration /home/marxin/Programming/gcc/gcc/cp/parser.c:28244 0xab0ff7 cp_parser_explicit_specialization /home/marxin/Programming/gcc/gcc/cp/parser.c:17304 0xaa9bc8 cp_parser_declaration /home/marxin/Programming/gcc/gcc/cp/parser.c:13168 0xaa9ef4 cp_parser_toplevel_declaration /home/marxin/Programming/gcc/gcc/cp/parser.c:13251 0xa9719a cp_parser_translation_unit /home/marxin/Programming/gcc/gcc/cp/parser.c:4690 0xaee97d c_parse_file() /home/marxin/Programming/gcc/gcc/cp/parser.c:41176 0xcb3987 c_common_parse_file() /home/marxin/Programming/gcc/gcc/c-family/c-opts.c:1156 I'm planning to disable the sanitization of the 2 hash tables now. @Jason: can you please take a look at the remaining test-cases?
Author: marxin Date: Tue Jun 11 07:55:19 2019 New Revision: 272144 URL: https://gcc.gnu.org/viewcvs?rev=272144&root=gcc&view=rev Log: Disable htable sanitization in pt.c (PR c++/87847). 2019-06-11 Martin Liska <mliska@suse.cz> PR c++/87847 * hash-table.h: Extend create_gcc, add one parameter that is passed into hash_table::hash_table. 2019-06-11 Martin Liska <mliska@suse.cz> PR c++/87847 * pt.c (init_template_processing): Disable hash table sanitization for decl_specializations and type_specializations. Modified: trunk/gcc/ChangeLog trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c trunk/gcc/hash-table.h
I posted a patch to enable sanitization for the spec_hasher tables for GCC 11 here: https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545525.html With current trunk I wasn't able to reproduce any sanitization errors in the testsuite or in other libraries even with a debugging patch similar to Martin's (on x86_64-pc-linux-gnu). I suspect they have been fixed by the patches for PR94454.
(In reply to Patrick Palka from comment #11) > I posted a patch to enable sanitization for the spec_hasher tables for GCC > 11 here: https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545525.html > > With current trunk I wasn't able to reproduce any sanitization errors in the > testsuite or in other libraries even with a debugging patch similar to > Martin's (on x86_64-pc-linux-gnu). I suspect they have been fixed by the > patches for PR94454. Cool! Thank you Patrick for working on that.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:573e5f0500968dcf4025b8fc0ae5fb367f9c70d9 commit r11-477-g573e5f0500968dcf4025b8fc0ae5fb367f9c70d9 Author: Patrick Palka <ppalka@redhat.com> Date: Mon May 18 23:50:32 2020 -0400 c++: Enable spec_hasher table sanitization [PR87847] It looks like hash table sanitization is now safe to enable for the decl_specializations and type_specializations tables, probably ever since PR94454 was fixed. gcc/cp/ChangeLog: PR c++/87847 * pt.c (init_template_processing): Enable sanitization for decl_specializations and type_specializations.
Fixed for GCC 11.