This patch fixes an ICE in a checking build where structural_comptypes disagrees with TYPE_CANONICAL.

An (implicit) template alias has a different TYPE_TI_TEMPLATE to the thing its aliasing. That make structural comparison think it's different. In the testcase we end up thinking 'Loc' refers to a different template than 'Traits<T>'

Solved by breaking TYPE_TEMPLATE_INFO into an underlying helper that doesn't deal with type aliases. While there, I noticed TYPE_TEMPLATE_INFO was doing more work than necessary because it checked twice whether DECL_LANG_SPECIFIC (TYPE_NAME (NODE)) was non-null. There's no need to check it again in the branch we can only get to when it's non-null. I also removed some unnecessary parens.

ok?

nathan
--
Nathan Sidwell
2016-12-12  Nathan Sidwell  <nat...@acm.org>

	PR c++/78776
	* cp-tree.h (TYPE_TEMPLATE_INFO_RAW): New, broken out of ...
	(TYPE_TEMPLATE_INFO): ... here. Use it.
	* typeck.c (structural_comptypes): Adjust record/union check to
	avoid alias template confusion.

	PR c++/78776
	* g++.dg/cpp0x/pr78776.C: New.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 243554)
+++ cp/cp-tree.h	(working copy)
@@ -3038,22 +3038,25 @@ extern void decl_shadowed_for_var_insert
    ->template_info)
 
 /* Template information for an ENUMERAL_, RECORD_, UNION_TYPE, or
-   BOUND_TEMPLATE_TEMPLATE_PARM type.  Note that if NODE is a
-   specialization of an alias template, this accessor returns the
-   template info for the alias template, not the one (if any) for the
-   template of the underlying type.  */
+   BOUND_TEMPLATE_TEMPLATE_PARM type.  This ignores any alias
+   templateness of NODE.  */
+
+#define TYPE_TEMPLATE_INFO_RAW(NODE)					\
+  (TREE_CODE (NODE) == ENUMERAL_TYPE					\
+   ? ENUM_TEMPLATE_INFO (NODE)						\
+   : (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM			\
+      ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE)			\
+      : (CLASS_TYPE_P (NODE)						\
+	 ? CLASSTYPE_TEMPLATE_INFO (NODE)				\
+	 : NULL_TREE)))
+
+/* If NODE is a specialization of an alias template, this accessor
+   returns the template info for the alias template.  Otherwise behave
+   as TYPE_TEMPLATE_INFO_RAW.  */
 #define TYPE_TEMPLATE_INFO(NODE)					\
-  ((TYPE_ALIAS_P (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE)))	\
-   ? (DECL_LANG_SPECIFIC (TYPE_NAME (NODE))				\
-      ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE))				\
-      : NULL_TREE)							\
-   : ((TREE_CODE (NODE) == ENUMERAL_TYPE)				\
-      ? ENUM_TEMPLATE_INFO (NODE)					\
-      : ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)		\
-	 ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE)			\
-	 : (CLASS_TYPE_P (NODE)						\
-	    ? CLASSTYPE_TEMPLATE_INFO (NODE)				\
-	    : NULL_TREE))))
+  (TYPE_ALIAS_P (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE))		\
+   ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE))				\
+   : TYPE_TEMPLATE_INFO_RAW (NODE))
 
 
 /* Set the template information for an ENUMERAL_, RECORD_, or
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 243554)
+++ cp/typeck.c	(working copy)
@@ -1284,18 +1284,23 @@ structural_comptypes (tree t1, tree t2,
 
     case RECORD_TYPE:
     case UNION_TYPE:
-      if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2)
-	  && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2)
-	      || TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM)
-	  && comp_template_args (TYPE_TI_ARGS (t1), TYPE_TI_ARGS (t2)))
-	break;
+      {
+	/* Ignore any alias templateness.  */
+	tree ti1 = TYPE_TEMPLATE_INFO_RAW (t1);
+	tree ti2 = TYPE_TEMPLATE_INFO_RAW (t2);
 
-      if ((strict & COMPARE_BASE) && DERIVED_FROM_P (t1, t2))
-	break;
-      else if ((strict & COMPARE_DERIVED) && DERIVED_FROM_P (t2, t1))
-	break;
+	if (ti1 && ti2
+	    && (TI_TEMPLATE (ti1) == TI_TEMPLATE (ti2)
+		|| TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM)
+	    && comp_template_args (TI_ARGS (ti1), TI_ARGS (ti2)))
+	  break;
+	if ((strict & COMPARE_BASE) && DERIVED_FROM_P (t1, t2))
+	  break;
+	else if ((strict & COMPARE_DERIVED) && DERIVED_FROM_P (t2, t1))
+	  break;
 
-      return false;
+	return false;
+      }
 
     case OFFSET_TYPE:
       if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
Index: testsuite/g++.dg/cpp0x/pr78776.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr78776.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr78776.C	(working copy)
@@ -0,0 +1,15 @@
+// PR c++/78776
+// { dg-do compile { target c++11 } }
+
+// ICE with canonical type verification
+
+template <typename> struct Traits;
+
+template <typename T>
+struct Bob {
+  using Loc = Traits<T>;
+  using typename Loc::Thing;
+
+  Thing Foo (); 
+};
+

Reply via email to