This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/66289 (ICE with alias-template)


My patch for DR 1558 broke this testcase: suppressing the stripping of alias template-ids with dependent arguments prevented us from recognizing that APtr<T> is more specialized than shared_ptr<T>. At the Lenexa meeting we in Core talked about establishing a category of alias templates that are actually equivalent to their expansions, based largely on whether all the template parameters are used. This patch implements that idea, and fixes the testcase.

Tested x86_64-pc-linux-gnu, applying to trunk and 5.
commit 434545f66e7c33ab7f8d9604d894c33bab9a5f1e
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jun 5 18:48:24 2015 -0400

    	PR c++/66289
    	* pt.c (uses_all_template_parms_data, uses_all_template_parms_r)
    	(complex_alias_template_p): New.
    	(dependent_alias_template_spec_p): Use complex_alias_template_p.
    	(dependent_type_p_r): Use dependent_alias_template_spec_p.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2ebeb65..15dba30 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5353,7 +5353,49 @@ alias_template_specialization_p (const_tree t)
   return false;
 }
 
-/* Return TRUE iff T is a specialization of an alias template with
+/* An alias template is complex from a SFINAE perspective if a template-id
+   using that alias can be ill-formed when the expansion is not, as with
+   the void_t template.  We determine this by checking whether the
+   expansion for the alias template uses all its template parameters.  */
+
+struct uses_all_template_parms_data
+{
+  int level;
+  bool *seen;
+};
+
+static int
+uses_all_template_parms_r (tree t, void *data_)
+{
+  struct uses_all_template_parms_data &data
+    = *(struct uses_all_template_parms_data*)data_;
+  tree idx = get_template_parm_index (t);
+
+  if (TEMPLATE_PARM_LEVEL (idx) == data.level)
+    data.seen[TEMPLATE_PARM_IDX (idx)] = true;
+  return 0;
+}
+
+bool
+complex_alias_template_p (const_tree tmpl)
+{
+  struct uses_all_template_parms_data data;
+  tree pat = TREE_TYPE (tmpl);
+  tree parms = DECL_TEMPLATE_PARMS (tmpl);
+  data.level = TMPL_PARMS_DEPTH (parms);
+  int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (parms));
+  data.seen = XALLOCAVEC (bool, len);
+  for (int i = 0; i < len; ++i)
+    data.seen[i] = false;
+
+  for_each_template_parm (pat, uses_all_template_parms_r, &data, NULL, true);
+  for (int i = 0; i < len; ++i)
+    if (!data.seen[i])
+      return true;
+  return false;
+}
+
+/* Return TRUE iff T is a specialization of a complex alias template with
    dependent template-arguments.  */
 
 bool
@@ -5361,7 +5403,8 @@ dependent_alias_template_spec_p (const_tree t)
 {
   return (alias_template_specialization_p (t)
 	  && (any_dependent_template_arguments_p
-	      (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
+	      (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t))))
+	  && complex_alias_template_p (DECL_TI_TEMPLATE (TYPE_NAME (t))));
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
@@ -20951,9 +20994,7 @@ dependent_type_p_r (tree type)
     return true;
   /* For an alias template specialization, check the arguments both to the
      class template and the alias template.  */
-  else if (alias_template_specialization_p (type)
-	   && (any_dependent_template_arguments_p
-	       (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (type)))))
+  else if (dependent_alias_template_spec_p (type))
     return true;
 
   /* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C
new file mode 100644
index 0000000..8d5eb23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C
@@ -0,0 +1,13 @@
+// PR c++/66289
+// { dg-do compile { target c++11 } }
+
+template<typename T> struct A {};
+
+template<typename T> struct shared_ptr { };
+template<typename T> using APtr = shared_ptr<A<T>>;
+
+template<typename T> struct foo;
+template<typename T> struct foo<shared_ptr<T>> { };
+template<typename T> struct foo<APtr<T>> { };
+
+foo<shared_ptr<A<int>>> aa;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]