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++-concepts] constraints redux


This patch revisits the normalization and checking of constraints. In
particular, it ensures that associated constraints are always
normalized so that checking constraints will never instantiate a
concept declaration.

This also removes the constraint check from fn_type_unification as per
discussion in Rapperswil. Candidates whose constraints are not
satisfied are just marked non-viable in overload resolution. This also
clears up an issue where constraints for function templates were being
checked twice during overload resolution.

I also ended up renaming a lot of functions to make them match the
wording the specification. Basically, "requirements -> constraints".

Updated all affected tests.

2014-08-08  Andrew Sutton  <andrew.n.sutton@gmail.com>

        * gcc/cp/logic.cc (subsumes_constraints_nonnull): Don't re-normalize
        constraints, it's already been done.
        * gcc/cp/cp-tree.h (*_requirement[s]): Renamed to *_constraint[s] to
        reflect wording in specification. Removed reduce_requirements.
        * gcc/cp/pt.c (process_template_parm, tsubst_pack_conjunction): Update
        from renaming.
        (fn_type_unification): Remove constraint check.
        * gcc/cp/parser.c (cp_parser_type_parameter,
        cp_parser_trailing_requirements,
        cp_parser_template_declaration_after_export,
        synthesize_implicit_template_parm): Update from renaming.
        * gcc/cp/constraint.cc: Renamed a lot of functions to reflect wording
        in specification.
        (finish_template_constraints): Normalize associated constraints.
        (tsubst_constraint_expr): Renamed from instantiate_requirements.
        Normalize associated constraints.
        (check_satisfied): Return true if the arguments refer to template
        parameters.
        (all_constraints_satisfied, any_conjunctions_satisfied,
        check_requirements): No longer needed.
        (check_diagnostic_constraints): Just normalize the expression, don't
        decompose it.

Andrew Sutton
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 213667)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -6079,10 +6079,6 @@ extern tree maybe_resolve_dummy			(tree,
 extern tree nonlambda_method_basetype		(void);
 extern void maybe_add_lambda_conv_op            (tree);
 extern bool is_lambda_ignored_entity            (tree);
-extern tree finish_template_requirements        (tree);
-extern tree save_leading_requirements           (tree);
-extern tree save_trailing_requirements          (tree);
-extern bool valid_requirements_p                (tree);
 
 /* in tree.c */
 extern int cp_tree_operand_length		(const_tree);
@@ -6415,20 +6411,23 @@ extern void suggest_alternatives_for
 extern tree strip_using_decl                    (tree);
 
 /* in constraint.cc */
-extern tree conjoin_requirements                (tree, tree);
-extern tree conjoin_requirements                (tree);
-extern tree reduce_requirements                 (tree);
+extern tree conjoin_constraints                 (tree, tree);
+extern tree conjoin_constraints                 (tree);
 extern tree get_constraints                     (tree);
 extern void set_constraints                     (tree, tree);
-extern tree get_shorthand_requirements          (tree);
+extern tree get_shorthand_constraints           (tree);
 
 extern tree build_concept_check                 (tree, tree, tree = NULL_TREE);
 extern tree build_constrained_parameter         (tree, tree, tree = NULL_TREE);
 extern bool deduce_constrained_parameter        (tree, tree&, tree&);
 extern tree resolve_constraint_check            (tree);
 
+extern tree finish_template_constraints         (tree);
+extern tree save_leading_constraints            (tree);
+extern tree save_trailing_constraints           (tree);
+extern bool valid_requirements_p                (tree);
 extern tree finish_concept_name                 (tree);
-extern tree finish_shorthand_requirement        (tree, tree);
+extern tree finish_shorthand_constraint         (tree, tree);
 extern tree finish_requires_expr                (tree, tree);
 extern tree finish_expr_requirement             (tree, tree, tree);
 extern tree finish_expr_requirement             (tree);
@@ -6439,8 +6438,6 @@ extern tree finish_noexcept_requirement
 extern tree finish_validexpr_expr               (tree);
 extern tree finish_validtype_expr               (tree);
 extern tree finish_constexpr_expr               (tree);
-extern tree finish_concept_name                 (tree);
-extern tree finish_shorthand_requirement        (tree, tree);
 
 extern void check_constrained_friend            (tree, tree);
 
@@ -6452,8 +6449,8 @@ extern tree tsubst_expr_req
 extern tree tsubst_type_req                     (tree, tree, tree);
 extern tree tsubst_nested_req                   (tree, tree, tree);
 
-extern tree instantiate_requirements            (tree, tree, bool);
 extern tree tsubst_constraint_info              (tree, tree);
+extern tree tsubst_constraint_expr              (tree, tree, bool);
 
 extern bool check_constraints                   (tree);
 extern bool check_constraints                   (tree, tree);
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 213667)
+++ gcc/cp/semantics.c	(working copy)
@@ -2704,7 +2704,7 @@ finish_template_template_parm (tree aggr
   DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   DECL_ARTIFICIAL (decl) = 1;
-  set_constraints (tmpl, finish_template_requirements (current_template_reqs));
+  set_constraints (tmpl, finish_template_constraints (current_template_reqs));
 
   end_template_decl ();
 
Index: gcc/cp/logic.cc
===================================================================
--- gcc/cp/logic.cc	(revision 213665)
+++ gcc/cp/logic.cc	(working copy)
@@ -506,7 +506,7 @@ subsumes_constraints_nonnull (tree left,
   // Check that the required expression in RIGHT is subsumed by each
   // subgoal in the assumptions of LEFT.
   tree as = CI_ASSUMPTIONS (left);
-  tree c = reduce_requirements (CI_ASSOCIATED_REQS (right));
+  tree c = CI_ASSOCIATED_REQS (right);
   for (int i = 0; i < TREE_VEC_LENGTH (as); ++i)
     if (!subsumes_prop (TREE_VEC_ELT (as, i), c))
       return false;
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 213667)
+++ gcc/cp/pt.c	(working copy)
@@ -3887,7 +3887,7 @@ process_template_parm (tree list, locati
 	= is_parameter_pack;
 
       // Build requirements for the parameter.
-      reqs = finish_shorthand_requirement (parm, constr);        
+      reqs = finish_shorthand_constraint (parm, constr);        
     }
   else
     {
@@ -3922,7 +3922,7 @@ process_template_parm (tree list, locati
       TYPE_CANONICAL (t) = canonical_type_parameter (t);
 
       // Build requirements for the type/template parameter.
-      reqs = finish_shorthand_requirement (parm, constr);
+      reqs = finish_shorthand_constraint (parm, constr);
     }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
@@ -4183,7 +4183,7 @@ build_template_decl (tree decl, tree par
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
-  set_constraints (tmpl, finish_template_requirements (constr));
+  set_constraints (tmpl, finish_template_constraints (constr));
 
   return tmpl;
 }
@@ -7979,7 +7979,7 @@ lookup_template_class_1 (tree d1, tree a
           // anywhere else.
           if (complain & tf_error)
             {
-              error ("template argument deduction failure");
+              error ("template constraint failure");
               diagnose_constraints (input_location, gen_tmpl, arglist);
             }
           return error_mark_node;
@@ -10081,7 +10081,7 @@ tsubst_pack_conjunction (tree t, tree ar
     }
 
   // Conjoin requirements. An empty conjunction is equivalent to ture.
-  if (tree reqs = conjoin_requirements (terms))
+  if (tree reqs = conjoin_constraints (terms))
     return reqs;
   else
     return boolean_true_node;
@@ -16515,15 +16515,6 @@ fn_type_unification (tree fn,
       goto fail;
     }
 
-  // All is well so far. Now, check that the template constraints
-  // are satisfied.
-  if (!check_template_constraints (fn, targs)) 
-    {
-      if (explain_p)
-        diagnose_constraints (DECL_SOURCE_LOCATION (fn), fn, targs);
-      return error_mark_node;
-    }
-
   /* All is well so far.  Now, check:
 
      [temp.deduct]
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 213667)
+++ gcc/cp/parser.c	(working copy)
@@ -13642,10 +13642,10 @@ cp_parser_type_parameter (cp_parser* par
         // If template requirements are present, parse them.
           if (flag_concepts)
           {
-            tree reqs = get_shorthand_requirements (current_template_parms);
+            tree reqs = get_shorthand_constraints (current_template_parms);
             if (tree r = cp_parser_requires_clause_opt (parser))
-              reqs = conjoin_requirements (reqs, r);
-            current_template_reqs = save_leading_requirements (reqs);
+              reqs = conjoin_constraints (reqs, r);
+            current_template_reqs = save_leading_constraints (reqs);
 
             // Attach the constraints to the parameter list.
             TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) 
@@ -17103,7 +17103,7 @@ cp_parser_trailing_requirements (cp_pars
           push_function_parms (decl);
           cp_lexer_consume_token (parser->lexer);
           tree reqs = cp_parser_requires_clause (parser);
-          current_template_reqs = save_trailing_requirements (reqs);
+          current_template_reqs = save_trailing_constraints (reqs);
           finish_scope();
           --cp_unevaluated_operand;
         }
@@ -24139,10 +24139,10 @@ cp_parser_template_declaration_after_exp
   // Manage template requirements
   if (flag_concepts)
     {
-      tree reqs = get_shorthand_requirements (current_template_parms);
+      tree reqs = get_shorthand_constraints (current_template_parms);
       if (tree r = cp_parser_requires_clause_opt (parser))
-        reqs = conjoin_requirements (reqs, r);
-      current_template_reqs = save_leading_requirements (reqs);
+        reqs = conjoin_constraints (reqs, r);
+      current_template_reqs = save_leading_constraints (reqs);
 
       // Attach the constraints to the template parameter list.
       // This is used to pass template requirements to out-of-class
@@ -33313,7 +33313,7 @@ synthesize_implicit_template_parm  (cp_p
 
   // If the invented parameter was constrained, save the constraint.
   if (tree reqs = TEMPLATE_PARM_CONSTRAINTS (tree_last (new_parm)))
-    current_template_reqs = save_leading_requirements (reqs);
+    current_template_reqs = save_leading_constraints (reqs);
 
   // Chain the new parameter to the list of implicit parameters.
   if (parser->implicit_template_parms)
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 213667)
+++ gcc/cp/decl.c	(working copy)
@@ -7542,7 +7542,7 @@ declare_simd_adjust_this (tree *tp, int
 
 // Returns the there leading template requirements if they exist.
 static inline tree
-get_leading_template_requirements () 
+get_leading_constraints () 
 {
   return current_template_reqs ? 
     CI_LEADING_REQS (current_template_reqs) : NULL_TREE;
@@ -7571,8 +7571,8 @@ adjust_out_of_class_fn_requirements (tre
       if (tree ci = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
         {
           tree reqs = CI_LEADING_REQS (ci);
-          if (reqs && !get_leading_template_requirements ())
-            current_template_reqs = save_leading_requirements (reqs);
+          if (reqs && !get_leading_constraints ())
+            current_template_reqs = save_leading_constraints (reqs);
         }
     }
   else if (current_template_parms)
@@ -7584,10 +7584,10 @@ adjust_out_of_class_fn_requirements (tre
           {
             tree r2 = CI_LEADING_REQS (current_template_reqs);
             CI_LEADING_REQS (current_template_reqs) = 
-                conjoin_requirements (r1, r2);
+                conjoin_constraints (r1, r2);
           }
         else
-          current_template_reqs = save_leading_requirements (r1);
+          current_template_reqs = save_leading_constraints (r1);
       }
   }
 }
@@ -7648,7 +7648,7 @@ grokfndecl (tree ctype,
 
   // Possibly adjust the template requirements for out-of-class
   // function definitions. This guarantees that current_template_reqs
-  // will be fully completed before calling finish_template_requirements.
+  // will be fully completed before calling finish_template_constraints.
   // verbatim ("%d", processing_template_decl);
   if (flag_concepts)
     adjust_out_of_class_fn_requirements (ctype);
@@ -7659,7 +7659,7 @@ grokfndecl (tree ctype,
   if (current_template_reqs)
     {
       current_template_reqs
-          = finish_template_requirements (current_template_reqs);
+          = finish_template_constraints (current_template_reqs);
       set_constraints (decl, current_template_reqs);
     }
 
@@ -12471,7 +12471,7 @@ xref_tag_1 (enum tag_types tag_code, tre
           // since a class doesn't have trailing requirements.
           if (current_template_reqs)
             current_template_reqs = 
-                finish_template_requirements (current_template_reqs);
+                finish_template_constraints (current_template_reqs);
 	  if (!redeclare_class_template (t, 
                                    current_template_parms, 
                                    current_template_reqs))
Index: gcc/cp/constraint.cc
===================================================================
--- gcc/cp/constraint.cc	(revision 213665)
+++ gcc/cp/constraint.cc	(working copy)
@@ -63,11 +63,11 @@ join_requirements (tree_code c, tree a,
 // expression with  NULL_TREE is an identity operation. That is, for some 
 // non-null A,
 //
-//    conjoin_requirements(a, NULL_TREE) == a
+//    conjoin_constraints(a, NULL_TREE) == a
 //
 // If both A and B are NULL_TREE, the result is also NULL_TREE.
 tree
-conjoin_requirements (tree a, tree b)
+conjoin_constraints (tree a, tree b)
 {
   if (a)
     return b ? join_requirements (TRUTH_ANDIF_EXPR, a, b) : a;
@@ -80,12 +80,12 @@ conjoin_requirements (tree a, tree b)
 // Transform the list of expressions in the T into a conjunction
 // of requirements. T must be a TREE_VEC.
 tree 
-conjoin_requirements (tree t)
+conjoin_constraints (tree t)
 {
   gcc_assert (TREE_CODE (t) == TREE_VEC);
   tree r = NULL_TREE;
   for (int i = 0; i < TREE_VEC_LENGTH (t); ++i)
-    r = conjoin_requirements (r, TREE_VEC_ELT (t, i));
+    r = conjoin_constraints (r, TREE_VEC_ELT (t, i));
   return r;
 }
 
@@ -234,25 +234,25 @@ deduce_constrained_parameter (tree call,
 namespace {
 
 // Helper functions
-static tree reduce_node (tree);
-static tree reduce_expr (tree);
-static tree reduce_stmt (tree);
-static tree reduce_decl (tree);
-static tree reduce_misc (tree);
-
-static tree reduce_logical     (tree);
-static tree reduce_call        (tree);
-static tree reduce_requires    (tree);
-static tree reduce_expr_req    (tree);
-static tree reduce_type_req    (tree);
-static tree reduce_nested_req  (tree);
-static tree reduce_template_id (tree);
-static tree reduce_stmt_list   (tree);
+tree normalize_constraints (tree);
+tree normalize_node (tree);
+tree normalize_expr (tree);
+tree normalize_stmt (tree);
+tree normalize_decl (tree);
+tree normalize_misc (tree);
+tree normalize_logical (tree);
+tree normalize_call(tree);
+tree normalize_requires (tree);
+tree normalize_expr_req (tree);
+tree normalize_type_req (tree);
+tree normalize_nested_req (tree);
+tree normalize_template_id (tree);
+tree normalize_stmt_list (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
 // atomic propositions.
 tree 
-reduce_node (tree t)
+normalize_node (tree t)
 {
   switch (TREE_CODE_CLASS (TREE_CODE (t))) 
     {
@@ -260,16 +260,16 @@ reduce_node (tree t)
     case tcc_binary:
     case tcc_expression:
     case tcc_vl_exp:
-      return reduce_expr (t);
+      return normalize_expr (t);
     
     case tcc_statement:   
-      return reduce_stmt (t);
+      return normalize_stmt (t);
     
     case tcc_declaration: 
-      return reduce_decl (t);
+      return normalize_decl (t);
     
     case tcc_exceptional: 
-      return reduce_misc (t);
+      return normalize_misc (t);
     
     // These kinds of expressions are atomic.
     case tcc_constant:
@@ -285,37 +285,37 @@ reduce_node (tree t)
 
 // Reduction rules for the expression node T.
 tree
-reduce_expr (tree t)
+normalize_expr (tree t)
 {
   switch (TREE_CODE (t))
     {
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:  
-      return reduce_logical (t);
+      return normalize_logical (t);
 
     case CALL_EXPR:        
-      return reduce_call (t);
+      return normalize_call (t);
 
     case REQUIRES_EXPR:
-      return reduce_requires (t);
+      return normalize_requires (t);
 
     case EXPR_REQ:
-      return reduce_expr_req (t);
+      return normalize_expr_req (t);
 
     case TYPE_REQ:
-      return reduce_type_req (t);
+      return normalize_type_req (t);
 
     case NESTED_REQ:
-      return reduce_nested_req (t);
+      return normalize_nested_req (t);
 
     case TEMPLATE_ID_EXPR: 
-      return reduce_template_id (t);
+      return normalize_template_id (t);
 
     case CAST_EXPR:
-      return reduce_node (TREE_VALUE (TREE_OPERAND (t, 0)));
+      return normalize_node (TREE_VALUE (TREE_OPERAND (t, 0)));
     
     case BIND_EXPR:        
-      return reduce_node (BIND_EXPR_BODY (t));
+      return normalize_node (BIND_EXPR_BODY (t));
 
     // Do not recurse.
     case TAG_DEFN:         
@@ -330,13 +330,13 @@ reduce_expr (tree t)
 
 // Reduction rules for the statement T.
 tree
-reduce_stmt (tree t)
+normalize_stmt (tree t)
 {
   switch (TREE_CODE (t))
     {
     // Reduce the returned expression.
     case RETURN_EXPR:
-      return reduce_node (TREE_OPERAND (t, 0));
+      return normalize_node (TREE_OPERAND (t, 0));
 
     // These statements do not introduce propositions
     // in the constraints language. Do not recurse.
@@ -352,7 +352,7 @@ reduce_stmt (tree t)
 
 // Reduction rules for the declaration T.
 tree
-reduce_decl (tree t)
+normalize_decl (tree t)
 {
   switch (TREE_CODE (t))
     {
@@ -368,7 +368,7 @@ reduce_decl (tree t)
 
 // Reduction rules for the node T.
 tree
-reduce_misc (tree t)
+normalize_misc (tree t)
 {
   switch (TREE_CODE (t))
     {
@@ -378,7 +378,7 @@ reduce_misc (tree t)
       return t;
 
     case STATEMENT_LIST:
-      return reduce_stmt_list (t);
+      return normalize_stmt_list (t);
     
     default:
       gcc_unreachable ();
@@ -391,10 +391,10 @@ reduce_misc (tree t)
 // Generate a new expression from the reduced operands. If either operand
 // cannot be reduced, then the resulting expression is null.
 tree
-reduce_logical (tree t)
+normalize_logical (tree t)
 {
-  tree l = reduce_expr (TREE_OPERAND (t, 0));
-  tree r = reduce_expr (TREE_OPERAND (t, 1));
+  tree l = normalize_expr (TREE_OPERAND (t, 0));
+  tree r = normalize_expr (TREE_OPERAND (t, 1));
   if (l && r)
     {
       t = copy_node (t);
@@ -411,7 +411,7 @@ reduce_logical (tree t)
 // If T is a call to a constraint instantiate its definition and
 // recursively reduce its returned expression.
 tree
-reduce_call (tree t)
+normalize_call (tree t)
 {
   // Is the function call actually a constraint check?
   tree check = resolve_constraint_check (t);
@@ -422,7 +422,7 @@ reduce_call (tree t)
   tree args = TREE_PURPOSE (check);
 
   // Reduce the body of the function into the constriants language.
-  tree body = reduce_requirements (DECL_SAVED_TREE (fn));
+  tree body = normalize_constraints (DECL_SAVED_TREE (fn));
   if (!body)
     {
       error ("could not inline requirements from %qD", fn);
@@ -430,7 +430,7 @@ reduce_call (tree t)
     }
 
   // Instantiate the reduced results using the deduced args.
-  tree result = instantiate_requirements (body, args, false);
+  tree result = tsubst_constraint_expr (body, args, false);
   if (result == error_mark_node)
     {
       error ("could not instantiate requirements from %qD", fn);
@@ -450,7 +450,7 @@ reduce_call (tree t)
 // Where Foo<T> should actually be written as Foo<T>(). Generate an
 // error and suggest the improved writing.
 tree
-reduce_template_id (tree t)
+normalize_template_id (tree t)
 {
   vec<tree, va_gc>* args = NULL;
   tree c = finish_call_expr (t, &args, true, false, 0);
@@ -467,25 +467,25 @@ reduce_template_id (tree t)
 // Reduce an expression requirement as a conjunction of its
 // individual constraints.
 tree
-reduce_expr_req (tree t) 
+normalize_expr_req (tree t) 
 {
   tree r = NULL_TREE;
   for (tree l = TREE_OPERAND (t, 0); l; l = TREE_CHAIN (l))
-    r = conjoin_requirements (r, reduce_expr (TREE_VALUE (l)));
+    r = conjoin_constraints (r, normalize_expr (TREE_VALUE (l)));
   return r;
 }
 
 // Reduce a type requirement by returing its underlying
 // constraint.
 tree
-reduce_type_req (tree t) 
+normalize_type_req (tree t) 
 {
   return TREE_OPERAND (t, 0);
 }
 
 // Reduce a nested requireemnt by returing its only operand.
 tree
-reduce_nested_req (tree t) 
+normalize_nested_req (tree t) 
 {
   return TREE_OPERAND (t, 0);
 }
@@ -494,10 +494,10 @@ reduce_nested_req (tree t)
 // rewriting the list of requirements so that we end up with a
 // list of expressions, some of which may be conjunctions.
 tree
-reduce_requires (tree t)
+normalize_requires (tree t)
 {
   for (tree l = TREE_OPERAND (t, 1); l; l = TREE_CHAIN (l))
-    TREE_VALUE (l) = reduce_expr (TREE_VALUE (l));
+    TREE_VALUE (l) = normalize_expr (TREE_VALUE (l));
   return t;
 }
 
@@ -510,35 +510,36 @@ reduce_requires (tree t)
 // statement. The primary purpose of these rules is to filter those
 // non-return statements from the constraints language.
 tree
-reduce_stmt_list (tree stmts)
+normalize_stmt_list (tree stmts)
 {
   tree lhs = NULL_TREE;
   tree_stmt_iterator i = tsi_start (stmts);
   while (!tsi_end_p (i))
     {
-      if (tree rhs = reduce_node (tsi_stmt (i)))
-        lhs = conjoin_requirements (lhs, rhs);
+      if (tree rhs = normalize_node (tsi_stmt (i)))
+        lhs = conjoin_constraints (lhs, rhs);
       tsi_next (&i);
     }
   return lhs;
 }
 
-} // end namespace
-
 // Reduce the requirement REQS into a logical formula written in terms of
 // atomic propositions.
 tree
-reduce_requirements (tree reqs)
+normalize_constraints (tree reqs)
 {
   if (!reqs)
     return NULL_TREE;
 
   ++processing_template_decl;
-  tree expr = reduce_node (reqs);
+  tree expr = normalize_node (reqs);
   --processing_template_decl;
   return expr;
 }
 
+} // end namespace
+
+
 // -------------------------------------------------------------------------- //
 // Constraint Semantic Processing
 //
@@ -567,14 +568,14 @@ set_constraints (tree t, tree ci)
 // parameter list PARMS. Note that the requirements are stored in
 // the TYPE of each tree node.
 tree
-get_shorthand_requirements (tree parms)
+get_shorthand_constraints (tree parms)
 {
   tree reqs = NULL_TREE;
   parms = INNERMOST_TEMPLATE_PARMS (parms);
   for (int i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
       tree parm = TREE_VEC_ELT (parms, i);
-      reqs = conjoin_requirements(reqs, TEMPLATE_PARM_CONSTRAINTS (parm));
+      reqs = conjoin_constraints(reqs, TEMPLATE_PARM_CONSTRAINTS (parm));
     }
   return reqs;
 }
@@ -590,7 +591,7 @@ build_constraint_info ()
 // Create a constraint info object, initialized with the given template
 // requirements.
 inline tree
-init_leading_requirements (tree reqs)
+init_leading_constraints (tree reqs)
 {
   tree_constraint_info* ci = build_constraint_info ();
   ci->leading_reqs = reqs;
@@ -600,7 +601,7 @@ init_leading_requirements (tree reqs)
 // Initialize a constraint info object, initialized with the given
 // trailing requirements.
 inline tree
-init_trailing_requirements (tree reqs)
+init_trailing_constraints (tree reqs)
 {
   tree_constraint_info* ci = build_constraint_info ();
   ci->trailing_reqs = reqs;
@@ -609,9 +610,9 @@ init_trailing_requirements (tree reqs)
 
 // Upodate the template requiremnets.
 inline tree
-update_leading_requirements (tree ci, tree reqs) {
+update_leading_constraints (tree ci, tree reqs) {
   tree& current = CI_LEADING_REQS (ci);
-  current = conjoin_requirements (current, reqs);
+  current = conjoin_constraints (current, reqs);
   return ci;
 }
 
@@ -619,7 +620,7 @@ update_leading_requirements (tree ci, tr
 // traling requirements cannot be updated once set: no other reqiurements
 // can be found after parsing a trailing requires-clause.
 inline tree
-update_trailing_requirements (tree ci, tree reqs) {
+update_trailing_constraints (tree ci, tree reqs) {
   gcc_assert(CI_TRAILING_REQS (ci) == NULL_TREE);
   CI_TRAILING_REQS (ci) = reqs;
   return ci;
@@ -634,14 +635,14 @@ update_trailing_requirements (tree ci, t
 // constrained type specifiers in a parameter list. These update the
 // template requirements after the template header has been parsed.
 tree
-save_leading_requirements (tree reqs)
+save_leading_constraints (tree reqs)
 {
   if (!reqs || reqs == error_mark_node)
     return NULL_TREE;
   else if (!current_template_reqs)
-    return init_leading_requirements (reqs);
+    return init_leading_constraints (reqs);
   else
-    return update_leading_requirements (current_template_reqs, reqs);
+    return update_leading_constraints (current_template_reqs, reqs);
 }
 
 // Return a constraint info object containing saved trailing requirements.
@@ -649,21 +650,21 @@ save_leading_requirements (tree reqs)
 // existing requirements. Otherwise, an empty constraint-info object
 // holding only these trailing requirements is returned.
 tree
-save_trailing_requirements (tree reqs)
+save_trailing_constraints (tree reqs)
 {
   if (!reqs || reqs == error_mark_node)
     return NULL_TREE;
   else if (!current_template_reqs)
-    return init_trailing_requirements (reqs);
+    return init_trailing_constraints (reqs);
   else
-    return update_trailing_requirements (current_template_reqs, reqs);
+    return update_trailing_constraints (current_template_reqs, reqs);
 }
 
 // Finish the template requirements, by computing the associated
 // constrains (the conjunction of template and trailing requirements),
 // and then decomposing that into sets of atomic propositions.
 tree
-finish_template_requirements (tree ci)
+finish_template_constraints (tree ci)
 {
   if (!ci || ci == error_mark_node)
     return NULL_TREE;
@@ -678,11 +679,10 @@ finish_template_requirements (tree ci)
   // are ill-formed, this is a hard error.
   tree r1 = CI_LEADING_REQS (ci);
   tree r2 = CI_TRAILING_REQS (ci);
-  tree assoc = conjoin_requirements (r1, r2);
-  CI_ASSOCIATED_REQS (ci) = assoc;
+  tree reqs = normalize_constraints (conjoin_constraints (r1, r2));
+  CI_ASSOCIATED_REQS (ci) = reqs;
 
   // Decompose those expressions into sets of atomic constraints. 
-  tree reqs = reduce_requirements (assoc);
   CI_ASSUMPTIONS (ci) = decompose_assumptions (reqs);
   return ci;
 }
@@ -994,7 +994,7 @@ build_constrained_parameter (tree fn, tr
   return decl;
 }
 
-// Create a requirement expression for the given DECL that evaluates the
+// Create a constraint expression for the given DECL that evaluates the
 // requirements specified by CONSTR, a TYPE_DECL that contains all the 
 // information necessary to build the requirements (see finish_concept_name 
 // for the layout of that TYPE_DECL).
@@ -1002,7 +1002,7 @@ build_constrained_parameter (tree fn, tr
 // Note that the constraints are neither reduced nor decomposed. That is
 // done only after the requires clause has been parsed (or not).
 tree
-finish_shorthand_requirement (tree decl, tree constr)
+finish_shorthand_constraint (tree decl, tree constr)
 {
   // No requirements means no constraints.
   if (!constr)
@@ -1176,7 +1176,7 @@ tsubst_expr_req (tree t, tree args, tree
   for (tree l = TREE_OPERAND (t, 0); l; l = TREE_CHAIN (l))
     {
       tree e = tsubst_expr (TREE_VALUE (l), args, tf_none, in_decl, false);
-      r = conjoin_requirements (r, e);
+      r = conjoin_constraints (r, e);
     }
   return r;
 }
@@ -1205,7 +1205,7 @@ tsubst_nested_req (tree t, tree args, tr
 // if parsing a template declaration, which causes the resulting expression
 // to not be folded.
 tree
-instantiate_requirements (tree reqs, tree args, bool do_not_fold)
+tsubst_constraint_expr (tree reqs, tree args, bool do_not_fold)
 {
   cp_unevaluated guard;
   if (do_not_fold)
@@ -1227,17 +1227,16 @@ tsubst_constraint_info (tree ci, tree ar
   // Substitute into the various constraint fields.
   tree_constraint_info* result = build_constraint_info ();
   if (tree r = CI_LEADING_REQS (ci))
-    result->leading_reqs = instantiate_requirements (r, args, true);
+    result->leading_reqs = tsubst_constraint_expr (r, args, true);
   if (tree r = CI_TRAILING_REQS (ci))
-    result->trailing_reqs = instantiate_requirements (r, args, true);
+    result->trailing_reqs = tsubst_constraint_expr (r, args, true);
 
-  // Build the associated requiremnts.
-  result->associated_reqs = 
-      conjoin_requirements (result->leading_reqs, result->trailing_reqs);
+  // Build the normalized associated requiremnts.
+  tree r = conjoin_constraints (result->leading_reqs, result->trailing_reqs);
+  result->associated_reqs = normalize_constraints (r);
   
   // Analyze the resulting constraints.
   // TODO: Is this actually necessary if the constraints are non-dependent?
-  // Presumably not since we'd never actually look at them, right?
   result->assumptions = decompose_assumptions (result->associated_reqs);
   return (tree)result;
 }
@@ -1255,8 +1254,13 @@ namespace {
 static bool
 check_satisfied (tree req, tree args) 
 {
+  // If any arguments are dependent, then we can't check the
+  // requirements. Just return true.
+  if (args && uses_template_parms (args))
+    return true;
+
   // Instantiate and evaluate the requirements. 
-  req = instantiate_requirements (req, args, false);
+  req = tsubst_constraint_expr (req, args, false);
   if (req == error_mark_node)
     return false;
 
@@ -1269,45 +1273,6 @@ check_satisfied (tree req, tree args)
   return result == boolean_true_node;
 }
 
-// Returns true iff all atomic constraints in the list are satisfied.
-static bool
-all_constraints_satisfied (tree reqs, tree args)
-{
-  int n = TREE_VEC_LENGTH (reqs);
-  for (int i = 0; i < n; ++i)
-    {
-      tree req = TREE_VEC_ELT (reqs, i);
-      if (!check_satisfied (req, args))
-        return false;
-    }
-  return true;
-}
-
-// Returns true if any conjunction of assumed requirements are satisfied.
-static bool
-any_conjunctions_satisfied (tree reqs, tree args)
-{
-  int n = TREE_VEC_LENGTH (reqs);
-  for (int i = 0; i < n; ++i)
-    {
-      tree con = TREE_VEC_ELT (reqs, i);
-      if (all_constraints_satisfied (con, args))
-        return true;
-    }
-  return false;
-}
-
-// Returns true iff the assumptions in REQS are satisfied.
-static inline bool
-check_requirements (tree reqs, tree args)
-{
-  // If any arguments are dependent, then we can't check the
-  // requirements. Just return true.
-  if (args && uses_template_parms (args))
-    return true;
-
-  return any_conjunctions_satisfied (reqs, args);
-}
 } // namespace
 
 // Check the instantiated declaration constraints.
@@ -1325,7 +1290,7 @@ check_constraints (tree cinfo)
   // all remaining expressions that are not constant expressions
   // (e.g., template-id expressions).
   else
-    return check_requirements (CI_ASSUMPTIONS (cinfo), NULL_TREE);
+    return check_satisfied (CI_ASSOCIATED_REQS (cinfo), NULL_TREE);
 }
 
 // Check the constraints in CINFO against the given ARGS, returning
@@ -1340,7 +1305,7 @@ check_constraints (tree cinfo, tree args
   else if (!valid_requirements_p (cinfo))
     return false;
   else {
-    return check_requirements (CI_ASSUMPTIONS (cinfo), args);
+    return check_satisfied (CI_ASSOCIATED_REQS (cinfo), args);
   }
 }
 
@@ -1353,13 +1318,6 @@ check_template_constraints (tree t, tree
   return check_constraints (get_constraints (t), args);
 }
 
-bool
-check_diagnostic_constraints (tree t, tree args)
-{
-  tree reqs = decompose_assumptions (reduce_requirements (t));
-  return check_requirements (reqs, args);
-}
-
 // -------------------------------------------------------------------------- //
 // Constraint Relations
 //
@@ -1413,6 +1371,15 @@ more_constrained (tree a, tree b) {
 
 namespace {
 
+// Given an arbitrary constraint expression, normalize it and
+// then check it. We have to normalize so we don't accidentally
+// instantiate concept declarations.
+inline bool
+check_diagnostic_constraints (tree reqs, tree args)
+{
+  return check_satisfied (normalize_constraints (reqs), args);
+}
+
 void diagnose_node (location_t, tree, tree);
 
 // Diagnose a constraint failure for type trait expressions.
@@ -1422,7 +1389,7 @@ diagnose_trait (location_t loc, tree t,
   if (check_diagnostic_constraints (t, args))
     return;
 
-  tree subst = instantiate_requirements (t, args, true);
+  tree subst = tsubst_constraint_expr (t, args, true);
 
   if (subst == error_mark_node)
     {
@@ -1527,7 +1494,7 @@ diagnose_check (location_t loc, tree t,
 
   // Locally instantiate the body with the call's template args, 
   // and recursively diagnose.
-  body = instantiate_requirements (body, targs, true);
+  body = tsubst_constraint_expr (body, targs, true);
   
   diagnose_node (loc, body, args);
 }
@@ -1554,7 +1521,7 @@ diagnose_requires (location_t loc, tree
   if (check_diagnostic_constraints (t, args))
     return;
 
-  tree subst = instantiate_requirements (t, args, true);
+  tree subst = tsubst_constraint_expr (t, args, true);
 
   // Print the header for the requires expression.
   tree parms = TREE_OPERAND (subst, 0);
Index: gcc/testsuite/g++.dg/concepts/req2.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/req2.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/req2.C	(working copy)
@@ -16,6 +16,6 @@ void f2(auto a)
 struct S { } s;
 
 int main() {
-  f1(0); // { dg-error "matching" }
-  f2((void*)0); // { dg-error "matching" }
+  f1(0); // { dg-error "cannot call" }
+  f2((void*)0); // { dg-error "cannot call" }
 }
Index: gcc/testsuite/g++.dg/concepts/alias3.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/alias3.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/alias3.C	(working copy)
@@ -9,5 +9,5 @@ template<typename T>
 
 int main()
 {
-  X<int> x1; // { dg-error "deduction|invalid" }
+  X<int> x1; // { dg-error "constraint|invalid" }
 }
Index: gcc/testsuite/g++.dg/concepts/class2.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/class2.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/class2.C	(working copy)
@@ -9,6 +9,6 @@ template<typename T>
 
 struct X { };
 
-S<int> sx; // { dg-error "deduction|invalid" }
+S<int> sx; // { dg-error "constraint|invalid" }
 
 int main() { }
Index: gcc/testsuite/g++.dg/concepts/class6.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/class6.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/class6.C	(working copy)
@@ -13,6 +13,6 @@ template<One T> struct S4<T> { }; // Sho
 struct one_type { char x[4]; };
 
 // Constraints are checked even when decls are not instantiatied.
-S4<one_type>* x4b; // { dg-error "deduction|invalid" }
+S4<one_type>* x4b; // { dg-error "constraint|invalid" }
 
 int main() { }
Index: gcc/testsuite/g++.dg/concepts/class8.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/class8.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/class8.C	(working copy)
@@ -7,7 +7,7 @@ template<C T> struct S;
 
 struct X { };
 
-// Not a valid declaration, int does not satisfy C.
-template<> struct S<int> { }; // { dg-error "deduction" }
+// Not a valid explicit specialization, int does not satisfy C.
+template<> struct S<int> { }; // { dg-error "constraint" }
 
 int main() { }
Index: gcc/testsuite/g++.dg/concepts/mem-concept-err.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/mem-concept-err.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/mem-concept-err.C	(working copy)
@@ -30,8 +30,8 @@ template<typename T>
   };
 
 int main() { 
-  f1('a'); // { dg-error "matching" }
-  f2(0);   // { dg-error "matching" }
+  f1('a'); // { dg-error "cannot call" }
+  f2(0);   // { dg-error "cannot call" }
 
   S<int> s;
   s.f1('a'); // { dg-error "matching" }
Index: gcc/testsuite/g++.dg/concepts/explicit-inst1.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/explicit-inst1.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/explicit-inst1.C	(revision 0)
@@ -0,0 +1,14 @@
+// { dg-options "-std=c++1z" }
+
+template<typename T>
+  concept bool C() { return __is_class(T); }
+
+template<typename T>
+  requires C<T>()
+    struct Test { };
+
+struct X { };
+
+template struct Test<X>;
+
+int main() { }
Index: gcc/testsuite/g++.dg/concepts/explicit-inst2.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/explicit-inst2.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/explicit-inst2.C	(revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++1z" }
+
+template<typename T>
+  concept bool C() { return __is_class(T); }
+
+template<typename T>
+  requires C<T>()
+    struct Test { };
+
+template struct Test<int>; // { dg-error "constraint" }
+
+int main() { }
Index: gcc/testsuite/g++.dg/concepts/fn2.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/fn2.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/fn2.C	(working copy)
@@ -10,9 +10,9 @@ template<typename T>
 // Non-dependent args are checked even in dependent scope.
 template<typename T>
   void h(T x) {
-    f(0); // { dg-error "matching" }
+    f(0); // { dg-error "cannot call" }
   }
 
 int main() {
-  f(0); // { dg-error "matching" }
+  f(0); // { dg-error "cannot call" }
 }
Index: gcc/testsuite/g++.dg/concepts/traits2.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/traits2.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/traits2.C	(working copy)
@@ -79,21 +79,21 @@ template<Enum T> void f18();
 
 
 int main() { 
-  f1<void>(); // { dg-error "matching" }
-  f2<void>(); // { dg-error "matching" }
-  f3<void>(); // { dg-error "matching" }
-  f4<void>(); // { dg-error "matching" }
-  f5<void>(); // { dg-error "matching" }
-  f6<void>(); // { dg-error "matching" }
-  f7<void>(); // { dg-error "matching" }
-  f8<void>(); // { dg-error "matching" }
-  f9<void>(); // { dg-error "matching" }
-  f10<void>(); // { dg-error "matching" }
-  f11<void>(); // { dg-error "matching" }
-  f12<void>(); // { dg-error "matching" }
-  f13<void>(); // { dg-error "matching" }
-  f14<void>(); // { dg-error "matching" }
-  f15<void>(); // { dg-error "matching" }
-  f16<void>(); // { dg-error "matching" }
-  f17<void>(); // { dg-error "matching" }
+  f1<void>(); // { dg-error "cannot call" }
+  f2<void>(); // { dg-error "cannot call" }
+  f3<void>(); // { dg-error "cannot call" }
+  f4<void>(); // { dg-error "cannot call" }
+  f5<void>(); // { dg-error "cannot call" }
+  f6<void>(); // { dg-error "cannot call" }
+  f7<void>(); // { dg-error "cannot call" }
+  f8<void>(); // { dg-error "cannot call" }
+  f9<void>(); // { dg-error "cannot call" }
+  f10<void>(); // { dg-error "cannot call" }
+  f11<void>(); // { dg-error "cannot call" }
+  f12<void>(); // { dg-error "cannot call" }
+  f13<void>(); // { dg-error "cannot call" }
+  f14<void>(); // { dg-error "cannot call" }
+  f15<void>(); // { dg-error "cannot call" }
+  f16<void>(); // { dg-error "cannot call" }
+  f17<void>(); // { dg-error "cannot call" }
 }
Index: gcc/testsuite/g++.dg/concepts/fn5.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/fn5.C	(revision 213665)
+++ gcc/testsuite/g++.dg/concepts/fn5.C	(working copy)
@@ -15,9 +15,9 @@ void f(Same<int> q) { }
 void g(Type a, Same<decltype(a)> b) { }
 
 int main() {
-  S1<char> s1;      // { dg-error "deduction|invalid" }
-  S2<int, char> s2; // { dg-error "deduction|invalid" }
+  S1<char> s1;      // { dg-error "constraint|invalid" }
+  S2<int, char> s2; // { dg-error "constraint|invalid" }
 
-  f('a');    // { dg-error "matching" }
-  g(0, 'a'); // { dg-error "matching" }
+  f('a');    // { dg-error "cannot" }
+  g(0, 'a'); // { dg-error "cannot" }
 }

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