diff options
author | Jason Merrill <jason@redhat.com> | 2020-02-11 12:04:37 +0100 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-02-12 01:07:41 +0100 |
commit | d6ef77e023cfe0bb3b12b88ae46b77da356d7f85 (patch) | |
tree | a70bf6c80ef0ce4f40fb73e7428ec56e9d3d80b7 /gcc/cp/method.c | |
parent | 9a5338e57db1cda13fa788b0e0debbcf99a475d6 (diff) | |
download | gcc-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.c | 47 |
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; |