From: Jason Merrill Date: Wed, 28 Jun 2017 21:06:35 +0000 (-0400) Subject: PR c++/72764 - ICE with invalid template typename. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cffc4a68d759fdca588cdf9ece998862b76141e6;p=gcc.git PR c++/72764 - ICE with invalid template typename. * decl.c (build_typename_type): No longer static. * tree.c (strip_typedefs): Use it instead of make_typename_type. From-SVN: r249760 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2245ca9060c..4b05c7efbac 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2017-06-28 Jason Merrill + PR c++/72764 - ICE with invalid template typename. + * decl.c (build_typename_type): No longer static. + * tree.c (strip_typedefs): Use it instead of make_typename_type. + PR c++/69300 - ICE with self-referential noexcept * pt.c (maybe_instantiate_noexcept): Check for recursion. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f82b1b6ae10..946a9167992 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6087,6 +6087,7 @@ extern tree define_label (location_t, tree); extern void check_goto (tree); extern bool check_omp_return (void); extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t); +extern tree build_typename_type (tree, tree, tree, tag_types); extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t); extern tree build_library_fn_ptr (const char *, tree, int); extern tree build_cp_library_fn_ptr (const char *, tree, int); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 93e24fc8984..3d96a3ea0fd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3594,7 +3594,7 @@ struct typename_hasher : ggc_ptr_hash static GTY (()) hash_table *typename_htab; -static tree +tree build_typename_type (tree context, tree name, tree fullname, enum tag_types tag_type) { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index bb17278c611..4535af64dc6 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1503,13 +1503,13 @@ strip_typedefs (tree t, bool *remove_attributes) break; case TYPENAME_TYPE: { + bool changed = false; tree fullname = TYPENAME_TYPE_FULLNAME (t); if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR && TREE_OPERAND (fullname, 1)) { tree args = TREE_OPERAND (fullname, 1); tree new_args = copy_node (args); - bool changed = false; for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) { tree arg = TREE_VEC_ELT (args, i); @@ -1533,12 +1533,15 @@ strip_typedefs (tree t, bool *remove_attributes) else ggc_free (new_args); } - result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t), - remove_attributes), - fullname, typename_type, tf_none); - /* Handle 'typedef typename A::N N;' */ - if (typedef_variant_p (result)) - result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (result))); + tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes); + if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t)) + return t; + tree name = fullname; + if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR) + name = TREE_OPERAND (fullname, 0); + /* Use build_typename_type rather than make_typename_type because we + don't want to resolve it here, just strip typedefs. */ + result = build_typename_type (ctx, name, fullname, typename_type); } break; case DECLTYPE_TYPE: diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C new file mode 100644 index 00000000000..6bf9b7b1666 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C @@ -0,0 +1,16 @@ +// PR c++/72764 +// { dg-do compile { target c++11 } } + +template < typename > struct A; +template < typename > struct B {}; + +template < typename T > +using C = typename A < T >::template D < T >; + +template < typename T > struct A +{ + // should be: template < typename > struct D : B < C < T > > {}; + struct D : B < C < T > > {}; // { dg-error "not a class template" } +}; + +A < int >::D a; // { dg-message "required" }