[C++] Implement C++20 P1814R0, CTAD for alias templates.
diff mbox series

Message ID 6e852d48-36d7-6cb5-3364-9c3f1a7860a0@redhat.com
State New
Headers show
Series
  • [C++] Implement C++20 P1814R0, CTAD for alias templates.
Related show

Commit Message

Jason Merrill Nov. 16, 2019, 10:51 p.m. UTC
This patch implements C++20 class template argument deduction for alias 
templates, which works by a moderately arcane transformation of the 
deduction guides for the underlying class template.  When implementing 
it, I found that I could simplify the rules in the draft a bit and get 
the same effect; I'll be emailing the committee to that effect soon.

While working on this I ran into various shortcomings in our handling of 
constrained alias templates (like B in the testcase), and fixed those in 
a separate patch.

Tested x86_64-pc-linux-gnu.  I'm going to clean this up a bit more 
before checking it in, but am sending this functional patch now before 
the end of stage 1.

Comments

Jason Merrill Nov. 27, 2019, 10:05 p.m. UTC | #1
On 11/16/19 5:51 PM, Jason Merrill wrote:
> This patch implements C++20 class template argument deduction for alias 
> templates, which works by a moderately arcane transformation of the 
> deduction guides for the underlying class template.  When implementing 
> it, I found that I could simplify the rules in the draft a bit and get 
> the same effect; I'll be emailing the committee to that effect soon.
> 
> While working on this I ran into various shortcomings in our handling of 
> constrained alias templates (like B in the testcase), and fixed those in 
> a separate patch.
> 
> Tested x86_64-pc-linux-gnu.  I'm going to clean this up a bit more 
> before checking it in, but am sending this functional patch now before 
> the end of stage 1.

Here's what I'm checking in now:

Patch
diff mbox series

commit 3784366a87f21dd0b995c1c952ab681165b99756
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Nov 16 15:43:07 2019 -0500

    Fix various issues with constrained alias templates.
    
            * cxx-pretty-print.c (pp_cxx_unqualified_id): Handle alias
            template-id.
            * pt.c (complex_alias_template_p): True if constraints.
            (get_underlying_template, tsubst): Check alias constraints.
            (push_template_decl_real): Set alias constraints here.
            * parser.c (cp_parser_alias_declaration): Not here.
            * constraint.cc (get_constraints): Take const_tree.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d6e9357385a..2a626d6d1ac 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7769,7 +7769,8 @@  extern cp_expr finish_constraint_and_expr	(location_t, cp_expr, cp_expr);
 extern cp_expr finish_constraint_primary_expr	(cp_expr);
 extern tree finish_concept_definition		(cp_expr, tree);
 extern tree combine_constraint_expressions      (tree, tree);
-extern tree get_constraints                     (tree);
+extern tree append_constraint			(tree, tree);
+extern tree get_constraints                     (const_tree);
 extern void set_constraints                     (tree, tree);
 extern void remove_constraints                  (tree);
 extern tree current_template_constraints	(void);
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 00b59a90868..c973d487245 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1119,7 +1119,7 @@  static GTY ((cache)) tree_cache_map *decl_constraints;
    constrained, return NULL_TREE. Note that T must be non-null. */
 
 tree
-get_constraints (tree t)
+get_constraints (const_tree t)
 {
   if (!flag_concepts)
     return NULL_TREE;
@@ -1129,7 +1129,7 @@  get_constraints (tree t)
   gcc_assert (DECL_P (t));
   if (TREE_CODE (t) == TEMPLATE_DECL)
     t = DECL_TEMPLATE_RESULT (t);
-  tree* found = decl_constraints->get (t);
+  tree* found = decl_constraints->get (CONST_CAST_TREE (t));
   if (found)
     return *found;
   else
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 8ece11d276e..909b2a4ef1d 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -172,11 +172,11 @@  pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
     case TYPENAME_TYPE:
     case UNBOUND_CLASS_TEMPLATE:
       pp_cxx_unqualified_id (pp, TYPE_NAME (t));
-      if (CLASS_TYPE_P (t) && CLASSTYPE_USE_TEMPLATE (t))
+      if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (t))
 	{
 	  pp_cxx_begin_template_argument_list (pp);
-	  pp_cxx_template_argument_list (pp, INNERMOST_TEMPLATE_ARGS
-                                                 (CLASSTYPE_TI_ARGS (t)));
+	  tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti));
+	  pp_cxx_template_argument_list (pp, args);
 	  pp_cxx_end_template_argument_list (pp);
 	}
       break;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c473e7fd92f..a80b4c818bb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19891,14 +19891,6 @@  cp_parser_alias_declaration (cp_parser* parser)
   if (decl == error_mark_node)
     return decl;
 
-  /* Attach constraints to the alias declaration.  */
-  if (flag_concepts && current_template_parms)
-    {
-      tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
-      tree constr = build_constraints (reqs, NULL_TREE);
-      set_constraints (decl, constr);
-    }
-
   cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0);
 
   if (pushed_scope)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8f7734a7a41..08b4713035b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5986,9 +5986,18 @@  push_template_decl_real (tree decl, bool is_friend)
 	}
 
       if (TREE_CODE (decl) == TYPE_DECL
-	  && TYPE_DECL_ALIAS_P (decl)
-	  && complex_alias_template_p (tmpl))
-	TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
+	  && TYPE_DECL_ALIAS_P (decl))
+	{
+	  if (tree constr
+	      = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+	    {
+	      /* ??? Why don't we do this here for all templates?  */
+	      constr = build_constraints (constr, NULL_TREE);
+	      set_constraints (decl, constr);
+	    }
+	  if (complex_alias_template_p (tmpl))
+	    TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
+	}
     }
 
   /* The DECL_TI_ARGS of DECL contains full set of arguments referring
@@ -6335,6 +6344,9 @@  uses_all_template_parms_r (tree t, void *data_)
 static bool
 complex_alias_template_p (const_tree tmpl)
 {
+  if (get_constraints (tmpl))
+    return true;
+
   struct uses_all_template_parms_data data;
   tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
   tree parms = DECL_TEMPLATE_PARMS (tmpl);
@@ -6403,7 +6415,8 @@  get_underlying_template (tree tmpl)
 	break;
 
       tree alias_args = INNERMOST_TEMPLATE_ARGS (generic_targs_for (tmpl));
-      if (!comp_template_args (TI_ARGS (tinfo), alias_args))
+      if (!comp_template_args (TI_ARGS (tinfo), alias_args)
+	  || !equivalently_constrained (tmpl, underlying))
 	break;
 
       /* Alias is equivalent.  Strip it and repeat.  */
@@ -14896,6 +14909,18 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	     instantiate it.  */
 	  tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
 	  tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
+	  /* FIXME check for satisfaction in check_instantiated_args.  */
+	  if (flag_concepts
+	      && !any_dependent_template_arguments_p (gen_args)
+	      && !constraints_satisfied_p (tmpl, gen_args))
+	    {
+	      if (complain & tf_error)
+		{
+		  gcc_assert (seen_error ());
+		  diagnose_constraints (input_location, tmpl, args);
+		}
+	      return error_mark_node;
+	    }
 	  r = instantiate_alias_template (tmpl, gen_args, complain);
 	}
       else if (DECL_CLASS_SCOPE_P (decl)