aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2024-01-10 23:18:23 -0500
committerJason Merrill <jason@redhat.com>2024-01-12 09:11:24 -0500
commita0e3d2ff6219d860c5108b3d1ff25a05a9a5559f (patch)
treefd065d1200ec0ee56357b890e9ea43e2cf201219 /gcc/cp
parent846794ead2982fc85a3b1a83bbb831fa096b2b7c (diff)
downloadgcc-a0e3d2ff6219d860c5108b3d1ff25a05a9a5559f.zip
gcc-a0e3d2ff6219d860c5108b3d1ff25a05a9a5559f.tar.gz
gcc-a0e3d2ff6219d860c5108b3d1ff25a05a9a5559f.tar.bz2
c++: cand_parms_match and reversed candidates
When considering whether the candidate parameters match, according to the language we're considering the synthesized reversed candidate, so we should compare the parameters in swapped order. In this situation it doesn't make sense to consider whether object parameters correspond, since we're comparing an object parameter to a non-object parameter, so I generalized xobj_iobj_parameters_correspond accordingly. As I refine cand_parms_match, more behaviors need to differ between its original use to compare the original templates for two candidates, and the later use to decide whether to compare constraints. So now there's a parameter to select between the semantics. gcc/cp/ChangeLog: * call.cc (reversed_match): New. (enum class pmatch): New enum. (cand_parms_match): Add match_kind parm. (object_parms_correspond): Add fn parms. (joust): Adjust. * class.cc (xobj_iobj_parameters_correspond): Rename to... (iobj_parm_corresponds_to): ...this. Take the other type instead of a second function. (object_parms_correspond): Adjust. * cp-tree.h (iobj_parm_corresponds_to): Declare. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-memfun4.C: Change expected reversed handling.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/call.cc76
-rw-r--r--gcc/cp/class.cc32
-rw-r--r--gcc/cp/cp-tree.h1
3 files changed, 69 insertions, 40 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 6f024b8..1f5ff41 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12713,7 +12713,7 @@ class_of_implicit_object (z_candidate *cand)
[basic.scope.scope]. */
static bool
-object_parms_correspond (z_candidate *c1, z_candidate *c2)
+object_parms_correspond (z_candidate *c1, tree fn1, z_candidate *c2, tree fn2)
{
tree context = class_of_implicit_object (c1);
tree ctx2 = class_of_implicit_object (c2);
@@ -12727,43 +12727,80 @@ object_parms_correspond (z_candidate *c1, z_candidate *c2)
but it can occur with reversed operators. */
return false;
- return object_parms_correspond (c1->fn, c2->fn, context);
+ return object_parms_correspond (fn1, fn2, context);
+}
+
+/* Return whether the first parameter of C1 matches the second parameter
+ of C2. */
+
+static bool
+reversed_match (z_candidate *c1, z_candidate *c2)
+{
+ tree fn1 = c1->fn;
+ tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (c2->fn));
+ tree parm2 = TREE_VALUE (TREE_CHAIN (parms2));
+ if (DECL_IOBJ_MEMBER_FUNCTION_P (fn1))
+ {
+ tree ctx = class_of_implicit_object (c1);
+ return iobj_parm_corresponds_to (fn1, parm2, ctx);
+ }
+ else
+ {
+ tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
+ tree parm1 = TREE_VALUE (parms1);
+ return same_type_p (parm1, parm2);
+ }
}
/* True if the defining declarations of the two candidates have equivalent
- parameters. */
+ parameters. MATCH_KIND controls whether we're trying to compare the
+ original declarations (for a warning) or the actual candidates. */
+
+enum class pmatch { original, current };
static bool
-cand_parms_match (z_candidate *c1, z_candidate *c2)
+cand_parms_match (z_candidate *c1, z_candidate *c2, pmatch match_kind)
{
tree fn1 = c1->fn;
tree fn2 = c2->fn;
- if (fn1 == fn2)
+ bool reversed = (match_kind == pmatch::current
+ && c1->reversed () != c2->reversed ());
+ if (fn1 == fn2 && !reversed)
return true;
if (identifier_p (fn1) || identifier_p (fn2))
return false;
- /* We don't look at c1->template_decl because that's only set for primary
- templates, not e.g. non-template member functions of class templates. */
- tree t1 = most_general_template (fn1);
- tree t2 = most_general_template (fn2);
- if (t1 || t2)
+ if (match_kind == pmatch::original)
{
- if (!t1 || !t2)
- return false;
- if (t1 == t2)
- return true;
- fn1 = DECL_TEMPLATE_RESULT (t1);
- fn2 = DECL_TEMPLATE_RESULT (t2);
+ /* We don't look at c1->template_decl because that's only set for
+ primary templates, not e.g. non-template member functions of
+ class templates. */
+ tree t1 = most_general_template (fn1);
+ tree t2 = most_general_template (fn2);
+ if (t1 || t2)
+ {
+ if (!t1 || !t2)
+ return false;
+ if (t1 == t2)
+ return true;
+ fn1 = DECL_TEMPLATE_RESULT (t1);
+ fn2 = DECL_TEMPLATE_RESULT (t2);
+ }
}
+
+ else if (reversed)
+ return (reversed_match (c1, c2)
+ && reversed_match (c2, c1));
+
tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
+
if (!(DECL_FUNCTION_MEMBER_P (fn1)
&& DECL_FUNCTION_MEMBER_P (fn2)))
/* Early escape. */;
/* CWG2789 is not adequate, it should specify corresponding object
parameters, not same typed object parameters. */
- else if (!object_parms_correspond (c1, c2))
+ else if (!object_parms_correspond (c1, fn1, c2, fn2))
return false;
else
{
@@ -12938,7 +12975,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
this approach to resolving the ambiguity, so pedwarn. */
if ((complain & tf_warning_or_error)
&& (cand1->reversed () != cand2->reversed ())
- && cand_parms_match (cand1, cand2))
+ && cand_parms_match (cand1, cand2, pmatch::original))
{
struct z_candidate *w, *l;
if (cand2->reversed ())
@@ -13139,8 +13176,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
if (flag_concepts && DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& !cand1->template_decl && !cand2->template_decl
- && cand1->reversed () == cand2->reversed ()
- && cand_parms_match (cand1, cand2))
+ && cand_parms_match (cand1, cand2, pmatch::current))
{
winner = more_constrained (cand1->fn, cand2->fn);
if (winner)
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 3374756..556943c 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -1019,24 +1019,13 @@ modify_vtable_entry (tree t,
}
-/* Check if the object parameters of an xobj and iobj member function
- correspond. CONTEXT is the class that an implicit object parameter
- refers to. */
+/* Check if the object parameter of an iobj member function corresponds to
+ another parameter type. CONTEXT is the class that the implicit object
+ parameter is considered to refer to. */
-static bool
-xobj_iobj_parameters_correspond (tree fn1, tree fn2, tree context)
+bool
+iobj_parm_corresponds_to (tree iobj_fn, tree xobj_param, tree context)
{
- gcc_assert (DECL_IOBJ_MEMBER_FUNCTION_P (fn1)
- || DECL_IOBJ_MEMBER_FUNCTION_P (fn2));
- gcc_assert (DECL_XOBJ_MEMBER_FUNCTION_P (fn1)
- || DECL_XOBJ_MEMBER_FUNCTION_P (fn2));
- gcc_assert (fn1 != fn2);
-
- tree xobj_fn = DECL_XOBJ_MEMBER_FUNCTION_P (fn1) ? fn1 : fn2;
- /* A reference, pointer, or something else. */
- tree xobj_param = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (xobj_fn)));
-
- tree iobj_fn = DECL_IOBJ_MEMBER_FUNCTION_P (fn1) ? fn1 : fn2;
tree iobj_fn_type = TREE_TYPE (iobj_fn);
/* If the iobj member function was introduced with a using declaration, the
@@ -1253,11 +1242,14 @@ object_parms_correspond (tree fn, tree method, tree context)
if (!same_type_p (fn_param, method_param))
return false;
}
- else if (DECL_XOBJ_MEMBER_FUNCTION_P (fn)
- || DECL_XOBJ_MEMBER_FUNCTION_P (method))
- return xobj_iobj_parameters_correspond (fn, method, context);
else
- gcc_unreachable ();
+ {
+ tree xobj_fn = DECL_XOBJ_MEMBER_FUNCTION_P (fn) ? fn : method;
+ tree iobj_fn = xobj_fn != fn ? fn : method;
+ tree xobj_param = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (xobj_fn)));
+
+ return iobj_parm_corresponds_to (iobj_fn, xobj_param, context);
+ }
return true;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 83009fc..d9b14d7 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6854,6 +6854,7 @@ extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
extern tree get_vtable_decl (tree, int);
extern bool object_parms_correspond (tree, tree, tree);
+extern bool iobj_parm_corresponds_to (tree, tree, tree);
extern bool add_method (tree, tree, bool);
extern tree declared_access (tree);
extern bool maybe_push_used_methods (tree);