public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/72764, ICE with invalid template typename
@ 2017-06-28 21:06 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2017-06-28 21:06 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 696 bytes --]

The problem in this testcase is that when we first parse C<T> we look
up the canonical instantiation of C<T> which doesn't see inside A<T>
because it happens at global scope, but then in strip_typedefs we are
in the context of A<T>, so the call to make_typename_type in
strip_typedefs was finding the error and causing trouble, because we
don't expect strip_typedefs to change anything.

This is an oddity with the current semi-specification of alias
templates that I hope to address in the standard soon, but for now
this patch addresses the issue by rebuilding a TYPENAME_TYPE in
strip_typedefs, even if we could resolve it in the current scope.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: 72764.diff --]
[-- Type: text/plain, Size: 3515 bytes --]

commit 9ab225e01a4aad9a95b6a744196cd03bce9c6e28
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 27 15:25:30 2017 -0400

            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.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f82b1b6..946a916 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 93e24fc..3d96a3e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3594,7 +3594,7 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
 
 static GTY (()) hash_table<typename_hasher> *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 bb17278..4535af6 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 0000000..6bf9b7b
--- /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" }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-06-28 21:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-28 21:06 C++ PATCH for c++/72764, ICE with invalid template typename Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).