aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/method.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-02-11 12:04:37 +0100
committerJason Merrill <jason@redhat.com>2020-02-12 01:07:41 +0100
commitd6ef77e023cfe0bb3b12b88ae46b77da356d7f85 (patch)
treea70bf6c80ef0ce4f40fb73e7428ec56e9d3d80b7 /gcc/cp/method.c
parent9a5338e57db1cda13fa788b0e0debbcf99a475d6 (diff)
downloadgcc-d6ef77e023cfe0bb3b12b88ae46b77da356d7f85.zip
gcc-d6ef77e023cfe0bb3b12b88ae46b77da356d7f85.tar.gz
gcc-d6ef77e023cfe0bb3b12b88ae46b77da356d7f85.tar.bz2
c++: Fix implicit friend operator==.
It seems that in writing testcases for the operator<=> proposal I didn't include any tests for implicitly declared friend operator==, and consequently it didn't work. 2020-02-11 Jason Merrill <jason@redhat.com> PR c++/93675 * class.c (add_implicitly_declared_members): Use do_friend. * method.c (implicitly_declare_fn): Fix friend handling. (decl_remember_implicit_trigger_p): New. (synthesize_method): Use it. * decl2.c (mark_used): Use it.
Diffstat (limited to 'gcc/cp/method.c')
-rw-r--r--gcc/cp/method.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index cfc37bc..790d570 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1463,6 +1463,22 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
--cp_unevaluated_operand;
}
+/* True iff DECL is an implicitly-declared special member function with no real
+ source location, so we can use its DECL_SOURCE_LOCATION to remember where we
+ triggered its synthesis. */
+
+bool
+decl_remember_implicit_trigger_p (tree decl)
+{
+ if (!DECL_ARTIFICIAL (decl))
+ return false;
+ special_function_kind sfk = special_function_p (decl);
+ /* Inherited constructors have the location of their using-declaration, and
+ operator== has the location of the corresponding operator<=>. */
+ return (sfk != sfk_inheriting_constructor
+ && sfk != sfk_comparison);
+}
+
/* Synthesize FNDECL, a non-static member function. */
void
@@ -1479,7 +1495,7 @@ synthesize_method (tree fndecl)
/* Reset the source location, we might have been previously
deferred, and thus have saved where we were first needed. */
- if (DECL_ARTIFICIAL (fndecl) && !DECL_INHERITED_CTOR (fndecl))
+ if (decl_remember_implicit_trigger_p (fndecl))
DECL_SOURCE_LOCATION (fndecl)
= DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl)));
@@ -2717,9 +2733,15 @@ implicitly_declare_fn (special_function_kind kind, tree type,
type_set_nontrivial_flag (type, kind);
/* Create the function. */
- tree this_type = cp_build_qualified_type (type, this_quals);
- fn_type = build_method_type_directly (this_type, return_type,
- parameter_types);
+ if (friend_p)
+ fn_type = build_function_type (return_type, parameter_types);
+ else
+ {
+ tree this_type = cp_build_qualified_type (type, this_quals);
+ fn_type = build_method_type_directly (this_type, return_type,
+ parameter_types);
+ }
+
if (raises)
{
if (raises != error_mark_node)
@@ -2794,12 +2816,19 @@ implicitly_declare_fn (special_function_kind kind, tree type,
inheriting constructor doesn't satisfy the requirements. */
constexpr_p = DECL_DECLARED_CONSTEXPR_P (inherited_ctor);
}
- /* Add the "this" parameter. */
- this_parm = build_this_parm (fn, fn_type, this_quals);
- DECL_CHAIN (this_parm) = DECL_ARGUMENTS (fn);
- DECL_ARGUMENTS (fn) = this_parm;
- grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
+ if (friend_p)
+ DECL_CONTEXT (fn) = DECL_CONTEXT (pattern_fn);
+ else
+ {
+ /* Add the "this" parameter. */
+ this_parm = build_this_parm (fn, fn_type, this_quals);
+ DECL_CHAIN (this_parm) = DECL_ARGUMENTS (fn);
+ DECL_ARGUMENTS (fn) = this_parm;
+
+ grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
+ }
+
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_DEFAULTED_FN (fn) = 1;