Commit cffc4a68 by Jason Merrill Committed by 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.

From-SVN: r249760
parent 395a191d
2017-06-28 Jason Merrill <jason@redhat.com> 2017-06-28 Jason Merrill <jason@redhat.com>
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 PR c++/69300 - ICE with self-referential noexcept
* pt.c (maybe_instantiate_noexcept): Check for recursion. * pt.c (maybe_instantiate_noexcept): Check for recursion.
......
...@@ -6087,6 +6087,7 @@ extern tree define_label (location_t, tree); ...@@ -6087,6 +6087,7 @@ extern tree define_label (location_t, tree);
extern void check_goto (tree); extern void check_goto (tree);
extern bool check_omp_return (void); extern bool check_omp_return (void);
extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t); 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 make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree build_library_fn_ptr (const char *, tree, int); extern tree build_library_fn_ptr (const char *, tree, int);
extern tree build_cp_library_fn_ptr (const char *, tree, int); extern tree build_cp_library_fn_ptr (const char *, tree, int);
......
...@@ -3594,7 +3594,7 @@ struct typename_hasher : ggc_ptr_hash<tree_node> ...@@ -3594,7 +3594,7 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
static GTY (()) hash_table<typename_hasher> *typename_htab; static GTY (()) hash_table<typename_hasher> *typename_htab;
static tree tree
build_typename_type (tree context, tree name, tree fullname, build_typename_type (tree context, tree name, tree fullname,
enum tag_types tag_type) enum tag_types tag_type)
{ {
......
...@@ -1503,13 +1503,13 @@ strip_typedefs (tree t, bool *remove_attributes) ...@@ -1503,13 +1503,13 @@ strip_typedefs (tree t, bool *remove_attributes)
break; break;
case TYPENAME_TYPE: case TYPENAME_TYPE:
{ {
bool changed = false;
tree fullname = TYPENAME_TYPE_FULLNAME (t); tree fullname = TYPENAME_TYPE_FULLNAME (t);
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR
&& TREE_OPERAND (fullname, 1)) && TREE_OPERAND (fullname, 1))
{ {
tree args = TREE_OPERAND (fullname, 1); tree args = TREE_OPERAND (fullname, 1);
tree new_args = copy_node (args); tree new_args = copy_node (args);
bool changed = false;
for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
{ {
tree arg = TREE_VEC_ELT (args, i); tree arg = TREE_VEC_ELT (args, i);
...@@ -1533,12 +1533,15 @@ strip_typedefs (tree t, bool *remove_attributes) ...@@ -1533,12 +1533,15 @@ strip_typedefs (tree t, bool *remove_attributes)
else else
ggc_free (new_args); ggc_free (new_args);
} }
result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t), tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes);
remove_attributes), if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t))
fullname, typename_type, tf_none); return t;
/* Handle 'typedef typename A::N N;' */ tree name = fullname;
if (typedef_variant_p (result)) if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (result))); 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; break;
case DECLTYPE_TYPE: case DECLTYPE_TYPE:
......
// 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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment