public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/66289 (ICE with alias-template)
@ 2015-06-10 13:11 Jason Merrill
  2015-06-10 15:25 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2015-06-10 13:11 UTC (permalink / raw)
  To: gcc-patches List

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

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.

[-- Attachment #2: 66289.patch --]
[-- Type: text/x-patch, Size: 3514 bytes --]

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;

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: C++ PATCH for c++/66289 (ICE with alias-template)
  2015-06-10 13:11 C++ PATCH for c++/66289 (ICE with alias-template) Jason Merrill
@ 2015-06-10 15:25 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2015-06-10 15:25 UTC (permalink / raw)
  To: gcc-patches List

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

On 06/10/2015 09:09 AM, Jason Merrill wrote:
> 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.

Actually, applying this patch, which uses a flag to remember whether an 
alias template is complex.

[-- Attachment #2: 66289.patch --]
[-- Type: text/x-patch, Size: 5759 bytes --]

commit 51f060584f93ef1f3d9ad56b5f11c5b2cfe6fd7a
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jun 5 18:48:24 2015 -0400

    	PR c++/66289
    	* cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): New.
    	* pt.c (push_template_decl_real): Set it.
    	(dependent_alias_template_spec_p): Use it.
    	(dependent_type_p_r): Use dependent_alias_template_spec_p.
    	(uses_all_template_parms_data, uses_all_template_parms_r)
    	(complex_alias_template_p): New.
    	(get_template_parm_index): Handle BOUND_TEMPLATE_TEMPLATE_PARM.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 603a871..1eac636 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -155,6 +155,7 @@ c-common.h, not after.
       LABEL_DECL_CONTINUE (in LABEL_DECL)
    2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
       DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
+      TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL)
    3: DECL_IN_AGGR_P.
    4: DECL_C_BIT_FIELD (in a FIELD_DECL)
       DECL_ANON_UNION_VAR_P (in a VAR_DECL)
@@ -2732,6 +2733,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 #define TYPE_DECL_ALIAS_P(NODE) \
   DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE))
 
+/* Nonzero for TEMPLATE_DECL means that it is a 'complex' alias template.  */
+#define TEMPLATE_DECL_COMPLEX_ALIAS_P(NODE) \
+  DECL_LANG_FLAG_2 (TEMPLATE_DECL_CHECK (NODE))
+
 /* Nonzero for a type which is an alias for another type; i.e, a type
    which declaration was written 'using name-of-type =
    another-type'.  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2ebeb65..7f04fe6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -211,6 +211,7 @@ static tree template_parm_to_arg (tree t);
 static tree current_template_args (void);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
+static bool complex_alias_template_p (const_tree tmpl);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -4420,6 +4421,7 @@ get_template_parm_index (tree parm)
 	   || TREE_CODE (parm) == TEMPLATE_DECL)
     parm = TREE_TYPE (parm);
   if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+      || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM
       || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
     parm = TEMPLATE_TYPE_PARM_INDEX (parm);
   gcc_assert (TREE_CODE (parm) == TEMPLATE_PARM_INDEX);
@@ -5096,6 +5098,11 @@ template arguments to %qD do not match original template %qD",
 	  if (TREE_CODE (parm) == TEMPLATE_DECL)
 	    DECL_CONTEXT (parm) = tmpl;
 	}
+
+      if (TREE_CODE (decl) == TYPE_DECL
+	  && TYPE_DECL_ALIAS_P (decl)
+	  && complex_alias_template_p (tmpl))
+	TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
     }
 
   /* The DECL_TI_ARGS of DECL contains full set of arguments referring
@@ -5353,13 +5360,56 @@ 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;
+}
+
+static bool
+complex_alias_template_p (const_tree tmpl)
+{
+  struct uses_all_template_parms_data data;
+  tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (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
 dependent_alias_template_spec_p (const_tree t)
 {
   return (alias_template_specialization_p (t)
+	  && TEMPLATE_DECL_COMPLEX_ALIAS_P (DECL_TI_TEMPLATE (TYPE_NAME (t)))
 	  && (any_dependent_template_arguments_p
 	      (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
 }
@@ -20951,9 +21001,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;

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-06-10 15:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-10 13:11 C++ PATCH for c++/66289 (ICE with alias-template) Jason Merrill
2015-06-10 15:25 ` 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).