Update the overloading rules for constraints to bring them into line
with the current wording. This handles overloads of member functions
of class template specializations separately from function templates.

Currently, functions that are not specializations of templates (or
temploids) can only be overloaded by type. They are not ordered by
their constraints.

This patch also contains an uncommitted change fixing some small
diagnostic issues. Unfortunately, they got lumped together.

2014-07-28  Andrew Sutton  <andrew.n.sut...@gmail.com>
        * gcc/cp/cp-tree.h (more_constraints): Remove
        (subsumes_constraints): Renamed from more_constraints
        (more_constrained): Repurposed
        * gcc/cp/call-c (template_decl_for_candidates): Rename to get_temploid,
        only get template info for member functions of a class template
        specialization.
        (joust): Handle member functions of class template specializations
        separately from function templates. This matches the new wording in
        the TS.
        * gcc/cp/logic.cc (match_terms): Make inline.
        (subsumes_constraints): Rename to subsumes_constraints_nonnull.
        * gcc/cp/pt.c (is_compatible_template_arg): Use subsumes.
        (more_specialized_fn): Use usubsumes_constraints.
        (more_specialized_class): Use more_constrained.
        * gcc/cp/constraint.cc (more_constraints): Removed.
        (more_constrained): New.

2014-07-11  Andrew Sutton  <andrew.n.sut...@gmail.com>
        * gcc/cp/typeck.c (cp_build_function_call_vec): Emit diagnostic
        at the input location.
        * gcc/cp/error.c (dump_template_decl): Constraints are never invalid
        in this way. Also fixes brace warning.

Andrew Sutton
Index: error.c
===================================================================
--- error.c	(revision 212456)
+++ error.c	(working copy)
@@ -1280,10 +1280,7 @@ dump_template_decl (cxx_pretty_printer *
 
           if (flag_concepts)
             if (tree ci = get_constraints (t))
-                if (ci != error_mark_node)
-                  pp_cxx_requires_clause (pp, CI_LEADING_REQS (ci));
-                else
-                  pp_cxx_ws_string (pp, "<invalid-constraints>");
+              pp_cxx_requires_clause (pp, CI_LEADING_REQS (ci));
 
 	  pp_cxx_whitespace (pp);
 	}
Index: typeck.c
===================================================================
--- typeck.c	(revision 212456)
+++ typeck.c	(working copy)
@@ -3463,8 +3463,8 @@ cp_build_function_call_vec (tree functio
         if (tree ci = get_constraints (function))
           if (!check_constraints (ci))
             {
+              error ("cannot call function %qD", function);
               location_t loc = DECL_SOURCE_LOCATION (function);
-              error_at (loc, "cannot call function %qD", function);
               diagnose_constraints (loc, function, NULL_TREE);
               return error_mark_node;
             }
Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 212456)
+++ cp-tree.h	(working copy)
@@ -6423,8 +6423,8 @@ extern bool check_template_constraints
 extern tree subst_template_constraints          (tree, tree);
 extern bool equivalent_constraints              (tree, tree);
 extern bool equivalently_constrained            (tree, tree);
-extern bool more_constraints                    (tree, tree);
-extern bool more_constrained                    (tree, tree);
+extern bool subsumes_constraints                (tree, tree);
+extern int more_constrained                     (tree, tree);
 
 extern void diagnose_constraints                (location_t, tree, tree);
 
Index: call.c
===================================================================
--- call.c	(revision 212456)
+++ call.c	(working copy)
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "print-tree.h"
 #include "stor-layout.h"
 #include "trans-mem.h"
 #include "stringpool.h"
@@ -8731,20 +8732,22 @@ add_warning (struct z_candidate *winner,
   winner->warnings = cw;
 }
 
-// Returns the template declaration associated with the candidate
-// function. For actual templates, this is directly associated
-// with the candidate. For temploids, we return the template
-// associated with the specialization.
+// When a CANDidate function is a member function of a class template
+// specialization, return the temploid describing that function.
+// Returns NULL_TREE otherwise.
 static inline tree
-template_decl_for_candidate (struct z_candidate *cand)
+get_temploid (struct z_candidate *cand)
 {
- tree r = cand->template_decl;
-  tree d = cand->fn;
-  if (!r && DECL_P (d) && DECL_USE_TEMPLATE (d))
-    r = DECL_TI_TEMPLATE (d);
-  if (r && TREE_CODE (r) == TEMPLATE_INFO)
-    r = TI_TEMPLATE (r);
-  return r;
+  gcc_assert (cand);
+  tree t = NULL_TREE;
+  if (!cand->template_decl)
+    {
+      if (DECL_P (cand->fn) && DECL_USE_TEMPLATE (cand->fn))
+        t = DECL_TI_TEMPLATE (cand->fn);
+      if (t && TREE_CODE (t) == TEMPLATE_INFO)
+        t = TI_TEMPLATE (t);
+    }
+    return t;
 }
 
 /* Compare two candidates for overloading as described in
@@ -8763,9 +8766,9 @@ joust (struct z_candidate *cand1, struct
   size_t i;
   size_t len;
 
-  // Get the actual template decls associated with the candidates.
-  tree tmpl1 = template_decl_for_candidate (cand1);
-  tree tmpl2 = template_decl_for_candidate (cand2);
+  // Try to get a temploid describing each candidate. 
+  tree m1 = get_temploid (cand1);
+  tree m2 = get_temploid (cand2);
 
   /* Candidates that involve bad conversions are always worse than those
      that don't.  */
@@ -8969,6 +8972,39 @@ joust (struct z_candidate *cand1, struct
      more specialized than the template for F2 according to the partial
      ordering rules.  */
 
+  if (cand1->template_decl && cand2->template_decl)
+    {
+      winner = more_specialized_fn
+        (TI_TEMPLATE (cand1->template_decl),
+         TI_TEMPLATE (cand2->template_decl),
+         /* [temp.func.order]: The presence of unused ellipsis and default
+            arguments has no effect on the partial ordering of function
+            templates.   add_function_candidate() will not have
+            counted the "this" argument for constructors.  */
+         cand1->num_convs + DECL_CONSTRUCTOR_P (cand1->fn));
+      if (winner)
+        return winner;
+    }
+
+    // C++ Concepts
+    // or, if not that,
+    // F1 and F2 are member functions of a class template specialization
+    // T, and M1 and M2 are member functions in the template of T
+    // corresponding to F1 and F2, and M1 is more constrained according
+    // to the partial ordering rules for constraints.
+    if (m1 && m2)
+      {
+        winner = more_constrained (m1, m2);
+        if (winner)
+          return winner;
+      }
+
+#if 0
+  /* or, if not that,
+     F1 and F2 are template functions and the function template for F1 is
+     more specialized than the template for F2 according to the partial
+     ordering rules.  */
+
   if (tmpl1 && tmpl2)
     {
       /* [temp.func.order]: The presence of unused ellipsis and default
@@ -8980,6 +9016,7 @@ joust (struct z_candidate *cand1, struct
       if (winner)
 	return winner;
     }
+#endif
 
   /* Check whether we can discard a builtin candidate, either because we
      have two identical ones or matching builtin and non-builtin candidates.
Index: logic.cc
===================================================================
--- logic.cc	(revision 212456)
+++ logic.cc	(working copy)
@@ -426,7 +426,7 @@ bool subsumes_or(tree, tree);
 //    * __is_same_as |- __is_convertible_to
 //    * __is_same_as |- __is_derived_from
 //    * Any other built-in predicates?
-bool
+inline bool
 match_terms (tree a, tree c)
 {
   return cp_tree_equal (a, c);
@@ -498,7 +498,7 @@ subsumes_prop (tree as, tree c)
 // This is done by checking that the RIGHT requirements follow from
 // each of the LEFT subgoals.
 bool
-subsumes_constraints (tree left, tree right)
+subsumes_constraints_nonnull (tree left, tree right)
 {
   gcc_assert (check_constraint_info (left));
   gcc_assert (check_constraint_info (right));
@@ -527,7 +527,7 @@ subsumes (tree left, tree right)
     return false;
   if (!right)
     return true;
-  return subsumes_constraints (left, right);
+  return subsumes_constraints_nonnull (left, right);
 }
 
 
Index: pt.c
===================================================================
--- pt.c	(revision 212456)
+++ pt.c	(working copy)
@@ -6603,7 +6603,7 @@ is_compatible_template_arg (tree parm, t
         return false;
     }
 
-  return more_constraints (parm_cons, arg_cons);
+  return subsumes (parm_cons, arg_cons);
 }
 
 // Convert a placeholder argument into a binding to the original
@@ -19052,8 +19052,8 @@ more_specialized_fn (tree pat1, tree pat
   // All things still being equal, determine if one is more constrained.
   if (lose1 == lose2)
     {
-      lose1 = !more_constrained (pat1, pat2);
-      lose2 = !more_constrained (pat2, pat1);
+      lose1 = !subsumes_constraints (pat1, pat2);
+      lose2 = !subsumes_constraints (pat2, pat1);
     }
 
   if (lose1 == lose2)
@@ -19140,11 +19140,10 @@ more_specialized_class (tree tmpl, tree
         return -1;
     }
 
-  if (more_constrained (tmpl1, tmpl2))
-    ++winner;
-  if (more_constrained (tmpl2, tmpl1))
-    --winner;
-
+  // If still tied at this point, the most specialized is also
+  // the most constrained. 
+  if (!winner)
+    return more_constrained (tmpl1, tmpl2);
   return winner;
 }
 
Index: constraint.cc
===================================================================
--- constraint.cc	(revision 212456)
+++ constraint.cc	(working copy)
@@ -1344,20 +1344,29 @@ equivalently_constrained (tree a, tree b
   return equivalent_constraints (get_constraints (a), get_constraints (b));
 }
 
-// Returns true when the A contains more atomic properties than B.
-bool
-more_constraints (tree a, tree b)
-{
-  return subsumes (a, b);
-}
-
 // Returns true when the template declaration A's constraints subsume
 // those of the template declaration B.
 bool 
-more_constrained (tree a, tree b)
+subsumes_constraints (tree a, tree b)
 {
   gcc_assert (TREE_CODE (a) == TREE_CODE (b));
-  return more_constraints (get_constraints (a), get_constraints (b));
+  return subsumes (get_constraints (a), get_constraints (b));
+}
+
+// Determines which of the templates, A or B, is more constrained. 
+// That is, which template's constraints subsume but are not subsumed 
+// by the other's?
+//
+// Returns 1 if A is more constrained than B, -1 if B is more constrained
+// than A, and 0 otherwise.
+int
+more_constrained (tree a, tree b) {
+  int winner = 0;
+  if (subsumes_constraints (a, b))
+    ++winner;
+  if (subsumes_constraints (b, a))
+    --winner;
+  return winner;
 }
 
 

Reply via email to