...because apparently someone wants to write such a thing?
Anyway, it's a simple matter of looking through templates when calling reset_decl_linkage.
Tested x86_64-pc-linux-gnu, applying to trunk and 5.
commit c96622dda7826a32ccc3caa34d727d8c1e7c3b3f Author: Jason Merrill <ja...@redhat.com> Date: Wed Feb 17 16:01:48 2016 -0500 PR c++/68679 * decl2.c (reset_type_linkage_2): Look through member templates. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 15d7617..73b0d28 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2685,14 +2685,22 @@ reset_type_linkage_2 (tree type) reset_decl_linkage (ti); } for (tree m = TYPE_FIELDS (type); m; m = DECL_CHAIN (m)) - if (VAR_P (m)) - reset_decl_linkage (m); + { + tree mem = STRIP_TEMPLATE (m); + if (VAR_P (mem)) + reset_decl_linkage (mem); + } for (tree m = TYPE_METHODS (type); m; m = DECL_CHAIN (m)) { - reset_decl_linkage (m); - if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (m)) - /* Also update its name, for cxx_dwarf_name. */ - DECL_NAME (m) = TYPE_IDENTIFIER (type); + tree mem = STRIP_TEMPLATE (m); + reset_decl_linkage (mem); + if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (mem)) + { + /* Also update its name, for cxx_dwarf_name. */ + DECL_NAME (mem) = TYPE_IDENTIFIER (type); + if (m != mem) + DECL_NAME (m) = TYPE_IDENTIFIER (type); + } } binding_table_foreach (CLASSTYPE_NESTED_UTDS (type), bt_reset_linkage_2, NULL); diff --git a/gcc/testsuite/g++.dg/other/anon8.C b/gcc/testsuite/g++.dg/other/anon8.C new file mode 100644 index 0000000..1fdd4c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/anon8.C @@ -0,0 +1,9 @@ +// PR c++/68679 + +typedef struct { + struct { + unsigned d[4]; + template<typename T> + unsigned operator[] (T i) const { return d[i]; } + } c; +} A;