[v8,1/4] c++: P0847R7 (deducing this) - prerequisite changes. [PR102609]

Message ID qFJs-vqcMVgr5VFvNrULQ3BL2GM2v_qgabqCA6KH3aDONEBK2La5VDARf_AJplVr5hafQ2T7SO6eQLh3omCRDfONNa2_p_mcsZWmPmM0Ajc=@protonmail.com
State Unresolved
Headers
Series [v8,1/4] c++: P0847R7 (deducing this) - prerequisite changes. [PR102609] |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

waffl3x Jan. 7, 2024, midnight UTC
  Bootstrapped and tested on x86_64-linux with no regressions.

I'm considering this finished, I have CWG2586 working but I have not
included it in this version of the patch. I was not happy with the
amount of work I had done on it. I will try to get it finished before
we get cut off, and I'm pretty sure I can. I just don't want to risk
missing the boat for the whole patch just for that.

There aren't too many changes from v7, it's mostly just cleaned up.
There are a few though, so do take a look, if there's anything severe I
can rush to fix it if necessary.

That's all, hopefully all is good, fingers crossed.

Alex
  

Comments

Jason Merrill Jan. 9, 2024, 8:58 p.m. UTC | #1
On 1/6/24 19:00, waffl3x wrote:
> Bootstrapped and tested on x86_64-linux with no regressions.
> 
> I'm considering this finished, I have CWG2586 working but I have not
> included it in this version of the patch. I was not happy with the
> amount of work I had done on it. I will try to get it finished before
> we get cut off, and I'm pretty sure I can. I just don't want to risk
> missing the boat for the whole patch just for that.
> 
> There aren't too many changes from v7, it's mostly just cleaned up.
> There are a few though, so do take a look, if there's anything severe I
> can rush to fix it if necessary.
> 
> That's all, hopefully all is good, fingers crossed.

Great.  Given where we are in the release cycle, I'm thinking to put 
these with only minimal changes and then do any further adjustments 
afterward.

For this first one, I needed to fix the commit message to wrap at 75 
columns so that it fits in 80 columns with the initial padding added by 
'git log'.  I also needed to adjust the ChangeLog entry to please git 
gcc-verify.  And I changed the credit note to a Co-authored-by.

The other commit messages only needed wrapping.

Thanks!

Jason
  
waffl3x Jan. 9, 2024, 9:26 p.m. UTC | #2
On Tuesday, January 9th, 2024 at 1:58 PM, Jason Merrill <jason@redhat.com> wrote:


> 
> 
> On 1/6/24 19:00, waffl3x wrote:
> 
> > Bootstrapped and tested on x86_64-linux with no regressions.
> > 
> > I'm considering this finished, I have CWG2586 working but I have not
> > included it in this version of the patch. I was not happy with the
> > amount of work I had done on it. I will try to get it finished before
> > we get cut off, and I'm pretty sure I can. I just don't want to risk
> > missing the boat for the whole patch just for that.
> > 
> > There aren't too many changes from v7, it's mostly just cleaned up.
> > There are a few though, so do take a look, if there's anything severe I
> > can rush to fix it if necessary.
> > 
> > That's all, hopefully all is good, fingers crossed.
> 
> 
> Great. Given where we are in the release cycle, I'm thinking to put
> these with only minimal changes and then do any further adjustments
> afterward.
> 
> For this first one, I needed to fix the commit message to wrap at 75
> columns so that it fits in 80 columns with the initial padding added by
> 'git log'. I also needed to adjust the ChangeLog entry to please git
> gcc-verify. And I changed the credit note to a Co-authored-by.
> 
> The other commit messages only needed wrapping.
> 
> Thanks!
> 
> Jason

Sounds good to me, it's been a pleasure working with you. If there's
anything you would like me to do differently for future patches just
let me know. For now, I think I will take a break.

Alex
  
Jason Merrill Jan. 9, 2024, 9:56 p.m. UTC | #3
On 1/9/24 15:58, Jason Merrill wrote:
> On 1/6/24 19:00, waffl3x wrote:
>> Bootstrapped and tested on x86_64-linux with no regressions.
>>
>> I'm considering this finished, I have CWG2586 working but I have not
>> included it in this version of the patch. I was not happy with the
>> amount of work I had done on it. I will try to get it finished before
>> we get cut off, and I'm pretty sure I can. I just don't want to risk
>> missing the boat for the whole patch just for that.
>>
>> There aren't too many changes from v7, it's mostly just cleaned up.
>> There are a few though, so do take a look, if there's anything severe I
>> can rush to fix it if necessary.
>>
>> That's all, hopefully all is good, fingers crossed.
> 
> Great.  Given where we are in the release cycle, I'm thinking to put 
> these with only minimal changes and then do any further adjustments 
> afterward.
> 
> For this first one, I needed to fix the commit message to wrap at 75 
> columns so that it fits in 80 columns with the initial padding added by 
> 'git log'.  I also needed to adjust the ChangeLog entry to please git 
> gcc-verify.  And I changed the credit note to a Co-authored-by.
> 
> The other commit messages only needed wrapping.

I just pushed your patches along with these two follow-ons:
  
waffl3x Jan. 9, 2024, 10:34 p.m. UTC | #4
On Tuesday, January 9th, 2024 at 2:56 PM, Jason Merrill <jason@redhat.com> wrote:


> 
> 
> On 1/9/24 15:58, Jason Merrill wrote:
> 
> > On 1/6/24 19:00, waffl3x wrote:
> > 
> > > Bootstrapped and tested on x86_64-linux with no regressions.
> > > 
> > > I'm considering this finished, I have CWG2586 working but I have not
> > > included it in this version of the patch. I was not happy with the
> > > amount of work I had done on it. I will try to get it finished before
> > > we get cut off, and I'm pretty sure I can. I just don't want to risk
> > > missing the boat for the whole patch just for that.
> > > 
> > > There aren't too many changes from v7, it's mostly just cleaned up.
> > > There are a few though, so do take a look, if there's anything severe I
> > > can rush to fix it if necessary.
> > > 
> > > That's all, hopefully all is good, fingers crossed.
> > 
> > Great. Given where we are in the release cycle, I'm thinking to put
> > these with only minimal changes and then do any further adjustments
> > afterward.
> > 
> > For this first one, I needed to fix the commit message to wrap at 75
> > columns so that it fits in 80 columns with the initial padding added by
> > 'git log'. I also needed to adjust the ChangeLog entry to please git
> > gcc-verify. And I changed the credit note to a Co-authored-by.
> > 
> > The other commit messages only needed wrapping.
> 
> 
> I just pushed your patches along with these two follow-ons:

Is the type of an implicit object parameter specified elsewhere? I have
looked for it more than once and I could only find that passage, but I
guess [over.match.funcs-1] is what I missed here, so
[over.match.funcs-4] doesn't apply elsewhere.

I have no objection to changing the comment in
iobj_xobj_parameters_correspond if you have a better idea on how to fix
the bug that inspired that comment. Especially since the standard is on
your side for it.

In this case, perhaps the comment should instead say something along
the lines of "this function does not account for using declarations."
That does get a little hairy though if both an iobj and xobj member
function are introduced by a using declaration. Perhaps we should just
optionally take a type that we can compare against? That sounds really
icky, maybe the solution you have in mind will work just fine.

BTW, I definitely assumed TYPE_MAIN_VARIANT was what I wanted in other
places in the patch, so there might be latent errors waiting to happen.
It's probably fine because those areas where I used them are pretty
well tested, but I thought it would be worth mentioning just in case.

I'm very excited to see this get through, thanks again for all the help
and patience.

Alex
  
Jason Merrill Jan. 9, 2024, 10:52 p.m. UTC | #5
On 1/9/24 17:34, waffl3x wrote:
> On Tuesday, January 9th, 2024 at 2:56 PM, Jason Merrill <jason@redhat.com> wrote:
>> On 1/9/24 15:58, Jason Merrill wrote:
>>> On 1/6/24 19:00, waffl3x wrote:
>>>
>>>> Bootstrapped and tested on x86_64-linux with no regressions.
>>>>
>>>> I'm considering this finished, I have CWG2586 working but I have not
>>>> included it in this version of the patch. I was not happy with the
>>>> amount of work I had done on it. I will try to get it finished before
>>>> we get cut off, and I'm pretty sure I can. I just don't want to risk
>>>> missing the boat for the whole patch just for that.
>>>>
>>>> There aren't too many changes from v7, it's mostly just cleaned up.
>>>> There are a few though, so do take a look, if there's anything severe I
>>>> can rush to fix it if necessary.
>>>>
>>>> That's all, hopefully all is good, fingers crossed.
>>>
>>> Great. Given where we are in the release cycle, I'm thinking to put
>>> these with only minimal changes and then do any further adjustments
>>> afterward.
>>>
>>> For this first one, I needed to fix the commit message to wrap at 75
>>> columns so that it fits in 80 columns with the initial padding added by
>>> 'git log'. I also needed to adjust the ChangeLog entry to please git
>>> gcc-verify. And I changed the credit note to a Co-authored-by.
>>>
>>> The other commit messages only needed wrapping.
>>
>> I just pushed your patches along with these two follow-ons:
> 
> Is the type of an implicit object parameter specified elsewhere? I have
> looked for it more than once and I could only find that passage, but I
> guess [over.match.funcs-1] is what I missed here, so
> [over.match.funcs-4] doesn't apply elsewhere.

That's the only definition I know of.  And indeed my statement was 
wrong, it also affects the considerations in add_method.  But I still 
think it would be more complicated in more places to deal with proxy 
FUNCTION_DECLs (like we do for inheriting constructors).

> I have no objection to changing the comment in
> iobj_xobj_parameters_correspond if you have a better idea on how to fix
> the bug that inspired that comment. Especially since the standard is on
> your side for it.
> 
> In this case, perhaps the comment should instead say something along
> the lines of "this function does not account for using declarations."
> That does get a little hairy though if both an iobj and xobj member
> function are introduced by a using declaration. Perhaps we should just
> optionally take a type that we can compare against? That sounds really
> icky, maybe the solution you have in mind will work just fine.
> 
> BTW, I definitely assumed TYPE_MAIN_VARIANT was what I wanted in other
> places in the patch, so there might be latent errors waiting to happen.
> It's probably fine because those areas where I used them are pretty
> well tested, but I thought it would be worth mentioning just in case.

The uses in copy_fn_p seem a little dubious, but there were already 
similar ones there, so I think it should be OK.

> I'm very excited to see this get through, thanks again for all the help
> and patience.

Thank you for all your work!

Jason
  
waffl3x Jan. 9, 2024, 11:59 p.m. UTC | #6
On Tuesday, January 9th, 2024 at 3:52 PM, Jason Merrill <jason@redhat.com> wrote:


> 
> 
> On 1/9/24 17:34, waffl3x wrote:
> 
> > On Tuesday, January 9th, 2024 at 2:56 PM, Jason Merrill jason@redhat.com wrote:
> > 
> > 
> > Is the type of an implicit object parameter specified elsewhere? I have
> > looked for it more than once and I could only find that passage, but I
> > guess [over.match.funcs-1] is what I missed here, so
> > [over.match.funcs-4] doesn't apply elsewhere.
> 
> 
> That's the only definition I know of. And indeed my statement was
> wrong, it also affects the considerations in add_method. But I still
> think it would be more complicated in more places to deal with proxy
> FUNCTION_DECLs (like we do for inheriting constructors).

You would know the code base better than I, so you're probably right.
The code in add_method probably already handles it just fine, the only
caveat being that it needs corresponding object parameters when
deciding to discard an overload introduced by a using declaration...
uhoh yeah that might not be okay. This probably results in ambiguous
overload resolution, I'll throw together a test case to see if I can
confirm this...

struct B {
  void f() {}
};

struct S : B {
  using B::f;
  void f(this S&) {}
};

int main() {
  S s{};
  s.f();
}

And yep, you're right, add_method is going to need to care about this
too. In the above test case, the call to f is incorrectly ambiguous.
The overload of f introduced by the using declaration should have been
discarded as the object parameters should correspond.

struct S;

struct B {
  void g(this S&) {}
};

struct S : B {
  using B::g;
  void g() {}
};

int main()
{
  S s{};
  s.g();
}

While this case works correctly, the overload of g introduced by the
using declaration is correctly discarded.

Hopefully it's not too annoying to solve, I'm not exactly sure how to
go about it (other than the method you've already turned down) so I'll
leave it to you.

Alex
  
Patrick Palka Jan. 10, 2024, 5:15 p.m. UTC | #7
Congratulations on landing this impressive work in GCC 14!

On Sun, 7 Jan 2024, waffl3x wrote:

> Bootstrapped and tested on x86_64-linux with no regressions.
> 
> I'm considering this finished, I have CWG2586 working but I have not
> included it in this version of the patch. I was not happy with the
> amount of work I had done on it. I will try to get it finished before
> we get cut off, and I'm pretty sure I can. I just don't want to risk
> missing the boat for the whole patch just for that.
> 
> There aren't too many changes from v7, it's mostly just cleaned up.
> There are a few though, so do take a look, if there's anything severe I
> can rush to fix it if necessary.
> 
> That's all, hopefully all is good, fingers crossed.
> 
> Alex
  

Patch

From cd122053dfad741a7d90adcd45929af768ce643f Mon Sep 17 00:00:00 2001
From: Waffl3x <waffl3x@protonmail.com>
Date: Sun, 31 Dec 2023 03:16:36 -0700
Subject: [PATCH 1/4] C++23 P0847R7 (deducing this) - prerequisite changes.
 [PR102609]

Adds the xobj_flag member to lang_decl_fn and a corresponding member access
macro and predicate to support the addition of explicit object member
functions. Additionally, since explicit object member functions are also
non-static member functions, we need to change uses of
DECL_NONSTATIC_MEMBER_FUNCTION_P to clarify whether they intend to include or
exclude them.

Many of these alterations are authored by Jason Merril.

	PR c++/102609

gcc/cp/ChangeLog:

	PR c++/102609
	C++23 P0847R7 (deducing this) - prerequisite changes. [PR102609]
	* cp-tree.h (struct lang_decl_fn): New data member.
	(DECL_NONSTATIC_MEMBER_FUNCTION_P): Poison.
	(DECL_IOBJ_MEMBER_FUNCTION_P): Define.
	(DECL_FUNCTION_XOBJ_FLAG): Define.
	(DECL_XOBJ_MEMBER_FUNCTION_P): Define.
	(DECL_OBJECT_MEMBER_FUNCTION_P): Define.
	(DECL_FUNCTION_MEMBER_P): Don't use DECL_NONSTATIC_MEMBER_FUNCTION_P.
	(DECL_CONST_MEMFUNC_P): Likewise.
	(DECL_VOLATILE_MEMFUNC_P): Likewise.
	(DECL_NONSTATIC_MEMBER_P): Likewise.
        * module.cc (trees_out::lang_decl_bools): Handle xobj_flag.
        (trees_in::lang_decl_bools): Handle xobj_flag.
	* call.cc (build_this_conversion):
	(add_function_candidate):
	(add_template_candidate_real):
	(add_candidates):
	(maybe_warn_class_memaccess):
	(cand_parms_match):
	(joust):
	(do_warn_dangling_reference): Don't use it.
	* class.cc (finalize_literal_type_property):
	(finish_struct):
	(resolve_address_of_overloaded_function):
	* constexpr.cc (is_valid_constexpr_fn):
	(cxx_bind_parameters_in_call):
	* contracts.cc (build_contract_condition_function):
	* cp-objcp-common.cc (cp_decl_dwarf_attribute):
	* cxx-pretty-print.cc (cxx_pretty_printer::postfix_expression):
	(cxx_pretty_printer::declaration_specifiers):
	(cxx_pretty_printer::direct_declarator):
	* decl.cc (cp_finish_decl):
	(grok_special_member_properties):
	(start_preparsed_function):
	(record_key_method_defined):
	* decl2.cc (cp_handle_deprecated_or_unavailable):
	* init.cc (find_uninit_fields_r):
	(build_offset_ref):
	* lambda.cc (lambda_expr_this_capture):
	(maybe_generic_this_capture):
	(nonlambda_method_basetype):
	* mangle.cc (write_nested_name):
	* method.cc (early_check_defaulted_comparison):
	(skip_artificial_parms_for):
	(num_artificial_parms_for):
	* module.cc (trees_out::lang_decl_bools):
	(trees_in::lang_decl_bools):
	* pt.cc (is_specialization_of_friend):
	(determine_specialization):
	(copy_default_args_to_explicit_spec):
	(check_explicit_specialization):
	(tsubst_contract_attribute):
	(check_non_deducible_conversions):
	(more_specialized_fn):
	(maybe_instantiate_noexcept):
	(register_parameter_specializations):
	(value_dependent_expression_p):
	* search.cc (shared_member_p):
	(lookup_member):
	(field_access_p):
	* semantics.cc (finish_omp_declare_simd_methods):
	* tree.cc (lvalue_kind):
	* typeck.cc (invalid_nonstatic_memfn_p): Don't use
	DECL_NONSTATIC_MEMBER_FUNCTION_P.

libcc1/ChangeLog:

	PR c++/102609
	C++23 P0847R7 (deducing this) - prerequisite changes. [PR102609]
	* libcp1plugin.cc (plugin_pragma_push_user_expression): Don't use
	DECL_NONSTATIC_MEMBER_FUNCTION_P.

Signed-off-by: Waffl3x <waffl3x@protonmail.com>
---
 gcc/cp/call.cc             | 25 +++++++++++++------------
 gcc/cp/class.cc            |  6 +++---
 gcc/cp/constexpr.cc        |  4 ++--
 gcc/cp/contracts.cc        |  6 +++---
 gcc/cp/cp-objcp-common.cc  |  4 ++--
 gcc/cp/cp-tree.h           | 37 ++++++++++++++++++++++++++++++-------
 gcc/cp/cxx-pretty-print.cc |  6 +++---
 gcc/cp/decl.cc             |  8 ++++----
 gcc/cp/decl2.cc            |  2 +-
 gcc/cp/init.cc             |  4 ++--
 gcc/cp/lambda.cc           |  9 +++++----
 gcc/cp/mangle.cc           |  4 ++--
 gcc/cp/method.cc           |  8 ++++----
 gcc/cp/module.cc           |  6 ++++--
 gcc/cp/pt.cc               | 38 +++++++++++++++++++-------------------
 gcc/cp/search.cc           |  5 +++--
 gcc/cp/semantics.cc        |  2 +-
 gcc/cp/tree.cc             |  2 +-
 gcc/cp/typeck.cc           |  2 +-
 libcc1/libcp1plugin.cc     |  2 +-
 20 files changed, 104 insertions(+), 76 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 6ac87a298b2..46f2ccdfc48 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -2309,7 +2309,7 @@  build_this_conversion (tree fn, tree ctype,
 		       tree& parmtype, tree& argtype, tree& arg,
 		       int flags, tsubst_flags_t complain)
 {
-  gcc_assert (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+  gcc_assert (DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 	      && !DECL_CONSTRUCTOR_P (fn));
 
   /* The type of the implicit object parameter ('this') for
@@ -2522,7 +2522,7 @@  add_function_candidate (struct z_candidate **candidates,
 	{
 	  tree parmtype = TREE_VALUE (parmnode);
 	  if (i == 0
-	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+	      && DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 	      && !DECL_CONSTRUCTOR_P (fn))
 	    t = build_this_conversion (fn, ctype, parmtype, argtype, arg,
 				       flags, complain);
@@ -3479,7 +3479,7 @@  add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
 
   /* We don't do deduction on the in-charge parameter, the VTT
      parameter or 'this'.  */
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (tmpl))
     {
       if (first_arg_without_in_chrg != NULL_TREE)
 	first_arg_without_in_chrg = NULL_TREE;
@@ -3589,7 +3589,7 @@  add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
       convs = alloc_conversions (nargs);
 
       if (shortcut_bad_convs
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl)
+	  && DECL_IOBJ_MEMBER_FUNCTION_P (tmpl)
 	  && !DECL_CONSTRUCTOR_P (tmpl))
 	{
 	  /* Check the 'this' conversion before proceeding with deduction.
@@ -6617,7 +6617,7 @@  add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
       tree fn_first_arg = NULL_TREE;
       const vec<tree, va_gc> *fn_args = args;
 
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+      if (DECL_OBJECT_MEMBER_FUNCTION_P (fn))
 	{
 	  /* Figure out where the object arg comes from.  If this
 	     function is a non-static member and we didn't get an
@@ -10784,7 +10784,8 @@  maybe_warn_class_memaccess (location_t loc, tree fndecl,
      type.  If so, and if the class has no non-trivial bases or members,
      be more permissive.  */
   if (current_function_decl
-      && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl)
+      && DECL_OBJECT_MEMBER_FUNCTION_P (current_function_decl)
+      /* ??? is_object_parameter?  */
       && is_this_parameter (tree_strip_nop_conversions (dest)))
     {
       tree ctx = DECL_CONTEXT (current_function_decl);
@@ -12684,8 +12685,8 @@  cand_parms_match (z_candidate *c1, z_candidate *c2)
   tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
   if (DECL_FUNCTION_MEMBER_P (fn1)
       && DECL_FUNCTION_MEMBER_P (fn2)
-      && (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn1)
-	  != DECL_NONSTATIC_MEMBER_FUNCTION_P (fn2)))
+      && (DECL_STATIC_FUNCTION_P (fn1)
+	  != DECL_STATIC_FUNCTION_P (fn2)))
     {
       /* Ignore 'this' when comparing the parameters of a static member
 	 function with those of a non-static one.  */
@@ -12870,7 +12871,7 @@  joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
 			  print_z_candidate (input_location,
 					     N_("candidate 2:"), l);
 			  if (w->fn == l->fn
-			      && DECL_NONSTATIC_MEMBER_FUNCTION_P (w->fn)
+			      && DECL_IOBJ_MEMBER_FUNCTION_P (w->fn)
 			      && (type_memfn_quals (TREE_TYPE (w->fn))
 				  & TYPE_QUAL_CONST) == 0)
 			    {
@@ -14019,7 +14020,7 @@  do_warn_dangling_reference (tree expr, bool arg_p)
 	       because R refers to one of the int elements of V, not to
 	       a temporary object.  Member operator* may return a reference
 	       but probably not to one of its arguments.  */
-	    || (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+	    || (DECL_OBJECT_MEMBER_FUNCTION_P (fndecl)
 		&& DECL_OVERLOADED_OPERATOR_P (fndecl)
 		&& DECL_OVERLOADED_OPERATOR_IS (fndecl, INDIRECT_REF)))
 	  return NULL_TREE;
@@ -14045,7 +14046,7 @@  do_warn_dangling_reference (tree expr, bool arg_p)
 	    tree arg = CALL_EXPR_ARG (expr, i);
 	    /* Check that this argument initializes a reference, except for
 	       the argument initializing the object of a member function.  */
-	    if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+	    if (!DECL_IOBJ_MEMBER_FUNCTION_P (fndecl)
 		&& !TYPE_REF_P (TREE_TYPE (arg)))
 	      continue;
 	    STRIP_NOPS (arg);
@@ -14065,7 +14066,7 @@  do_warn_dangling_reference (tree expr, bool arg_p)
 	       const S& s = S().self();
 	     where 's' dangles.  If we've gotten here, the object this function
 	     is invoked on is not a temporary.  */
-	    if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl))
+	    if (DECL_OBJECT_MEMBER_FUNCTION_P (fndecl))
 	      break;
 	  }
 	return NULL_TREE;
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 1954e0a5ed3..692b238dd7e 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5968,7 +5968,7 @@  finalize_literal_type_property (tree t)
     for (fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn))
       if (TREE_CODE (fn) == FUNCTION_DECL
 	  && DECL_DECLARED_CONSTEXPR_P (fn)
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+	  && DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 	  && !DECL_CONSTRUCTOR_P (fn))
 	{
 	  DECL_DECLARED_CONSTEXPR_P (fn) = false;
@@ -7932,7 +7932,7 @@  finish_struct (tree t, tree attributes)
   if (flag_openmp)
     for (tree decl = TYPE_FIELDS (t); decl; decl = DECL_CHAIN (decl))
       if (TREE_CODE (decl) == FUNCTION_DECL
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+	  && DECL_OBJECT_MEMBER_FUNCTION_P (decl))
 	if (tree attr = lookup_attribute ("omp declare variant base",
 					  DECL_ATTRIBUTES (decl)))
 	  omp_declare_variant_finalize (decl, attr);
@@ -8727,7 +8727,7 @@  resolve_address_of_overloaded_function (tree target_type,
   /* Good, exactly one match.  Now, convert it to the correct type.  */
   fn = TREE_PURPOSE (matches);
 
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+  if (DECL_OBJECT_MEMBER_FUNCTION_P (fn)
       && !(complain & tf_ptrmem_ok) && !flag_ms_extensions)
     {
       static int explained;
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index eff43a42353..b12473c44af 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -291,7 +291,7 @@  is_valid_constexpr_fn (tree fun, bool complain)
 
       /* C++14 DR 1684 removed this restriction.  */
       if (cxx_dialect < cxx14
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
+	  && DECL_IOBJ_MEMBER_FUNCTION_P (fun)
 	  && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun)))
 	{
 	  ret = false;
@@ -1886,7 +1886,7 @@  cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
 					  non_constant_p, overflow_p);
       /* Check we aren't dereferencing a null pointer when calling a non-static
 	 member function, which is undefined behaviour.  */
-      if (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
+      if (i == 0 && DECL_OBJECT_MEMBER_FUNCTION_P (fun)
 	  && integer_zerop (arg)
 	  /* But ignore calls from within compiler-generated code, to handle
 	     cases like lambda function pointer conversion operator thunks
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index 035ca4827e7..c505b67d339 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -1398,7 +1398,7 @@  build_contract_condition_function (tree fndecl, bool pre)
 {
   if (TREE_TYPE (fndecl) == error_mark_node)
     return error_mark_node;
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (fndecl)
       && !TYPE_METHOD_BASETYPE (TREE_TYPE (fndecl)))
     return error_mark_node;
 
@@ -1421,7 +1421,7 @@  build_contract_condition_function (tree fndecl, bool pre)
       arg_type && arg_type != void_list_node;
       arg_type = TREE_CHAIN (arg_type))
     {
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+      if (DECL_IOBJ_MEMBER_FUNCTION_P (fndecl)
 	  && TYPE_ARG_TYPES (TREE_TYPE (fn)) == arg_type)
       {
 	class_type = TREE_TYPE (TREE_VALUE (arg_type));
@@ -1451,7 +1451,7 @@  build_contract_condition_function (tree fndecl, bool pre)
     }
 
   TREE_TYPE (fn) = build_function_type (value_type, arg_types);
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (fndecl))
     TREE_TYPE (fn) = build_method_type (class_type, TREE_TYPE (fn));
 
   DECL_NAME (fn) = copy_node (DECL_NAME (fn));
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index ee88df5767b..3970c4cddd5 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -349,7 +349,7 @@  cp_decl_dwarf_attribute (const_tree decl, int attr)
 
     case DW_AT_reference:
       if (TREE_CODE (decl) == FUNCTION_DECL
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+	  && DECL_IOBJ_MEMBER_FUNCTION_P (decl)
 	  && FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
 	  && !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
 	return 1;
@@ -357,7 +357,7 @@  cp_decl_dwarf_attribute (const_tree decl, int attr)
 
     case DW_AT_rvalue_reference:
       if (TREE_CODE (decl) == FUNCTION_DECL
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+	  && DECL_IOBJ_MEMBER_FUNCTION_P (decl)
 	  && FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
 	  && FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
 	return 1;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1979572c365..41d480f8e6e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2962,8 +2962,9 @@  struct GTY(()) lang_decl_fn {
   unsigned coroutine_p : 1;
   unsigned implicit_constexpr : 1;
   unsigned escalated_p : 1;
+  unsigned xobj_func : 1;
 
-  unsigned spare : 8;
+  unsigned spare : 7;
 
   /* 32-bits padding on 64-bit host.  */
 
@@ -3361,33 +3362,55 @@  struct GTY(()) lang_decl {
 #define DECL_STATIC_FUNCTION_P(NODE) \
   (LANG_DECL_FN_CHECK (NODE)->static_function)
 
-/* Nonzero for FUNCTION_DECL means that this decl is a non-static
+/* Nonzero for FUNCTION_DECL means that this decl is a non-static member
+   function.  C++23 explicit object member functions are also considered
+   non-static, but most former uses of this macro meant implicit object member
+   function.  Instead of this macro, use DECL_IOBJ_MEMBER_FUNCTION_P or
+   DECL_OBJECT_MEMBER_FUNCTION_P.  */
+#define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) did_you_mean_object_or_iobj
+
+/* Nonzero for FUNCTION_DECL means that this decl is an implicit object
    member function.  */
-#define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) \
+#define DECL_IOBJ_MEMBER_FUNCTION_P(NODE) \
   (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)
 
+/* Simple member access, only valid for FUNCTION_DECL nodes.  */
+#define DECL_FUNCTION_XOBJ_FLAG(NODE)	\
+  (LANG_DECL_FN_CHECK (NODE)->xobj_func)
+
+/* Nonzero if NODE is an xobj member function,
+   safely evaluates to false for all non FUNCTION_DECL nodes.  */
+#define DECL_XOBJ_MEMBER_FUNCTION_P(NODE)		\
+  (TREE_CODE (STRIP_TEMPLATE (NODE)) == FUNCTION_DECL	\
+   && DECL_FUNCTION_XOBJ_FLAG (NODE) == 1)
+
+/* Nonzero if NODE is a member function with an object argument,
+   in other words, a non-static member function.  */
+#define DECL_OBJECT_MEMBER_FUNCTION_P(NODE) \
+  (DECL_IOBJ_MEMBER_FUNCTION_P (NODE) || DECL_XOBJ_MEMBER_FUNCTION_P (NODE))
+
 /* Nonzero for FUNCTION_DECL means that this decl is a member function
    (static or non-static).  */
 #define DECL_FUNCTION_MEMBER_P(NODE) \
-  (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE))
+  (DECL_OBJECT_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE)) \
 
 /* Nonzero for FUNCTION_DECL means that this member function
    has `this' as const X *const.  */
 #define DECL_CONST_MEMFUNC_P(NODE)					 \
-  (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)				 \
+  (DECL_IOBJ_MEMBER_FUNCTION_P (NODE)				 \
    && CP_TYPE_CONST_P (TREE_TYPE (TREE_VALUE				 \
 				  (TYPE_ARG_TYPES (TREE_TYPE (NODE))))))
 
 /* Nonzero for FUNCTION_DECL means that this member function
    has `this' as volatile X *const.  */
 #define DECL_VOLATILE_MEMFUNC_P(NODE)					 \
-  (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)				 \
+  (DECL_IOBJ_MEMBER_FUNCTION_P (NODE)				 \
    && CP_TYPE_VOLATILE_P (TREE_TYPE (TREE_VALUE				 \
 				  (TYPE_ARG_TYPES (TREE_TYPE (NODE))))))
 
 /* Nonzero for a DECL means that this member is a non-static member.  */
 #define DECL_NONSTATIC_MEMBER_P(NODE)		\
-  (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)	\
+  (DECL_OBJECT_MEMBER_FUNCTION_P (NODE)	\
    || TREE_CODE (NODE) == FIELD_DECL)
 
 /* Nonzero for a FIELD_DECL means that this member object type
diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
index 6a82358f370..53c0722d2f3 100644
--- a/gcc/cp/cxx-pretty-print.cc
+++ b/gcc/cp/cxx-pretty-print.cc
@@ -553,7 +553,7 @@  cxx_pretty_printer::postfix_expression (tree t)
 	   instantiation time.  */
 	if (TREE_CODE (fun) != FUNCTION_DECL)
 	  ;
-	else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun))
+	else if (DECL_OBJECT_MEMBER_FUNCTION_P (fun))
 	  {
 	    tree object = (code == AGGR_INIT_EXPR
 			   ? (AGGR_INIT_VIA_CTOR_P (t)
@@ -1342,7 +1342,7 @@  cxx_pretty_printer::declaration_specifiers (tree t)
 	 do not have a type-specifier in their return types.  */
       if (DECL_CONSTRUCTOR_P (t) || DECL_CONV_FN_P (t))
 	function_specifier (t);
-      else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
+      else if (DECL_IOBJ_MEMBER_FUNCTION_P (t))
 	declaration_specifiers (TREE_TYPE (TREE_TYPE (t)));
       else
         c_pretty_printer::declaration_specifiers (t);
@@ -1700,7 +1700,7 @@  cxx_pretty_printer::direct_declarator (tree t)
       expression (t);
       pp_cxx_parameter_declaration_clause (this, t);
 
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
+      if (DECL_IOBJ_MEMBER_FUNCTION_P (t))
 	{
 	  padding = pp_before;
 	  pp_cxx_cv_qualifier_seq (this, pp_cxx_implicit_parameter_type (t));
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 27f17808934..b5b23b86b62 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8526,7 +8526,7 @@  cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       && TREE_CODE (decl) == FUNCTION_DECL
       /* #pragma omp declare variant on methods handled in finish_struct
 	 instead.  */
-      && (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+      && (!DECL_OBJECT_MEMBER_FUNCTION_P (decl)
 	  || COMPLETE_TYPE_P (DECL_CONTEXT (decl))))
     if (tree attr = lookup_attribute ("omp declare variant base",
 				      DECL_ATTRIBUTES (decl)))
@@ -15516,7 +15516,7 @@  grok_special_member_properties (tree decl)
   tree class_type;
 
   if (TREE_CODE (decl) == USING_DECL
-      || !DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+      || !DECL_OBJECT_MEMBER_FUNCTION_P (decl))
     return;
 
   class_type = DECL_CONTEXT (decl);
@@ -17706,7 +17706,7 @@  start_preparsed_function (tree decl1, tree attrs, int flags)
   /* Start the statement-tree, start the tree now.  */
   DECL_SAVED_TREE (decl1) = push_stmt_list ();
 
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (decl1))
     {
       /* We know that this was set up by `grokclassfn'.  We do not
 	 wait until `store_parm_decls', since evil parse errors may
@@ -18175,7 +18175,7 @@  outer_curly_brace_block (tree fndecl)
 static void
 record_key_method_defined (tree fndecl)
 {
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+  if (DECL_OBJECT_MEMBER_FUNCTION_P (fndecl)
       && DECL_VIRTUAL_P (fndecl)
       && !processing_template_decl)
     {
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 0850d3f5bce..c8eddf4cc26 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -5625,7 +5625,7 @@  cp_handle_deprecated_or_unavailable (tree decl, tsubst_flags_t complain)
   if (cxx_dialect >= cxx11
       && DECL_P (decl)
       && DECL_ARTIFICIAL (decl)
-      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+      && DECL_IOBJ_MEMBER_FUNCTION_P (decl)
       && copy_fn_p (decl))
     {
       /* Don't warn if the flag was disabled around the class definition
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 6444f0a8518..fb5f404805b 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -866,7 +866,7 @@  find_uninit_fields_r (tree *tp, int *walk_subtrees, void *data)
   else if (code == CALL_EXPR)
     {
       tree fn = get_callee_fndecl (init);
-      if (fn && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+      if (fn && DECL_IOBJ_MEMBER_FUNCTION_P (fn))
 	{
 	  tree op = CALL_EXPR_ARG (init, 0);
 	  if (TREE_CODE (op) == ADDR_EXPR)
@@ -2477,7 +2477,7 @@  build_offset_ref (tree type, tree member, bool address_p,
 
 	   -- in a mem-initializer for a constructor for that class or for
 	   a class derived from that class (_class.base.init_).  */
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
+      if (DECL_OBJECT_MEMBER_FUNCTION_P (member))
 	{
 	  /* Build a representation of the qualified name suitable
 	     for use as the operand to "&" -- even though the "&" is
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 5990a6de736..fc6a0708b66 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -834,8 +834,9 @@  lambda_expr_this_capture (tree lambda, int add_capture_p)
 
 	  if (!LAMBDA_FUNCTION_P (containing_function))
 	    {
-	      /* We found a non-lambda function.  */
-	      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function))
+	      /* We found a non-lambda function.
+		 There is no this pointer in xobj member functions.  */
+	      if (DECL_IOBJ_MEMBER_FUNCTION_P (containing_function))
 		/* First parameter is 'this'.  */
 		init = DECL_ARGUMENTS (containing_function);
 	      break;
@@ -969,7 +970,7 @@  maybe_generic_this_capture (tree object, tree fns)
 	for (lkp_iterator iter (fns); iter; ++iter)
 	  if (((!id_expr && TREE_CODE (*iter) != USING_DECL)
 	       || TREE_CODE (*iter) == TEMPLATE_DECL)
-	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (*iter))
+	      && DECL_IOBJ_MEMBER_FUNCTION_P (*iter))
 	    {
 	      /* Found a non-static member.  Capture this.  */
 	      lambda_expr_this_capture (lam, /*maybe*/-1);
@@ -1012,7 +1013,7 @@  nonlambda_method_basetype (void)
 
       tree fn = TYPE_CONTEXT (type);
       if (!fn || TREE_CODE (fn) != FUNCTION_DECL
-	  || !DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+	  || !DECL_IOBJ_MEMBER_FUNCTION_P (fn))
 	/* No enclosing non-lambda method.  */
 	return NULL_TREE;
       if (!LAMBDA_FUNCTION_P (fn))
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 365d470f46e..99fabbf3587 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1231,9 +1231,9 @@  write_nested_name (const tree decl)
 
   write_char ('N');
 
-  /* Write CV-qualifiers, if this is a member function.  */
+  /* Write CV-qualifiers, if this is an iobj member function.  */
   if (TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+      && DECL_IOBJ_MEMBER_FUNCTION_P (decl))
     {
       if (DECL_VOLATILE_MEMFUNC_P (decl))
 	write_char ('V');
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index f645066077f..d6ad5aa41d6 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1187,7 +1187,7 @@  early_check_defaulted_comparison (tree fn)
 	ok = false;
     }
 
-  bool mem = DECL_NONSTATIC_MEMBER_FUNCTION_P (fn);
+  bool mem = DECL_IOBJ_MEMBER_FUNCTION_P (fn);
   if (mem && type_memfn_quals (TREE_TYPE (fn)) != TYPE_QUAL_CONST)
     {
       error_at (loc, "defaulted %qD must be %<const%>", fn);
@@ -1230,7 +1230,7 @@  early_check_defaulted_comparison (tree fn)
 
   if (saw_bad || (saw_byval && saw_byref))
     {
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+      if (DECL_IOBJ_MEMBER_FUNCTION_P (fn))
 	error_at (loc, "defaulted member %qD must have parameter type "
 		  "%<const %T&%>", fn, ctx);
       else if (saw_bad)
@@ -3606,7 +3606,7 @@  lazily_declare_fn (special_function_kind sfk, tree type)
 tree
 skip_artificial_parms_for (const_tree fn, tree list)
 {
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (fn))
     list = TREE_CHAIN (list);
   else
     return list;
@@ -3626,7 +3626,7 @@  num_artificial_parms_for (const_tree fn)
 {
   int count = 0;
 
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (fn))
     count++;
   else
     return 0;
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 0bd46414da9..2d0c0a3eaab 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -5683,8 +5683,9 @@  trees_out::lang_decl_bools (tree t)
       WB (lang->u.fn.has_dependent_explicit_spec_p);
       WB (lang->u.fn.immediate_fn_p);
       WB (lang->u.fn.maybe_deleted);
-      WB (lang->u.fn.escalated_p);
       /* We do not stream lang->u.fn.implicit_constexpr.  */
+      WB (lang->u.fn.escalated_p);
+      WB (lang->u.fn.xobj_func);
       goto lds_min;
 
     case lds_decomp:  /* lang_decl_decomp.  */
@@ -5753,8 +5754,9 @@  trees_in::lang_decl_bools (tree t)
       RB (lang->u.fn.has_dependent_explicit_spec_p);
       RB (lang->u.fn.immediate_fn_p);
       RB (lang->u.fn.maybe_deleted);
-      RB (lang->u.fn.escalated_p);
       /* We do not stream lang->u.fn.implicit_constexpr.  */
+      RB (lang->u.fn.escalated_p);
+      RB (lang->u.fn.xobj_func);
       goto lds_min;
 
     case lds_decomp:  /* lang_decl_decomp.  */
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 2817657a8bb..72eb124d116 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1446,9 +1446,9 @@  is_specialization_of_friend (tree decl, tree friend_decl)
 	     `this' parameter.  */
 	  friend_args_type = TYPE_ARG_TYPES (friend_type);
 	  decl_args_type = TYPE_ARG_TYPES (decl_type);
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend_decl))
+	  if (DECL_IOBJ_MEMBER_FUNCTION_P (friend_decl))
 	    friend_args_type = TREE_CHAIN (friend_args_type);
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+	  if (DECL_IOBJ_MEMBER_FUNCTION_P (decl))
 	    decl_args_type = TREE_CHAIN (decl_args_type);
 
 	  return compparms (decl_args_type, friend_args_type);
@@ -2236,7 +2236,7 @@  determine_specialization (tree template_id,
 	     that the const qualification is the same.  Since
 	     get_bindings does not try to merge the "this" parameter,
 	     we must do the comparison explicitly.  */
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+	  if (DECL_IOBJ_MEMBER_FUNCTION_P (fn))
 	    {
 	      if (!same_type_p (TREE_VALUE (fn_arg_types),
 				TREE_VALUE (decl_arg_types)))
@@ -2359,14 +2359,14 @@  determine_specialization (tree template_id,
 	  /* Adjust the type of DECL in case FN is a static member.  */
 	  decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
 	  if (DECL_STATIC_FUNCTION_P (fn)
-	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+	      && DECL_IOBJ_MEMBER_FUNCTION_P (decl))
 	    decl_arg_types = TREE_CHAIN (decl_arg_types);
 
 	  if (!compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
 			 decl_arg_types))
             continue;
 
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+	  if (DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 	      && (type_memfn_rqual (TREE_TYPE (decl))
 		  != type_memfn_rqual (TREE_TYPE (fn))))
 	    continue;
@@ -2552,7 +2552,7 @@  copy_default_args_to_explicit_spec (tree decl)
   old_type = TREE_TYPE (decl);
   spec_types = TYPE_ARG_TYPES (old_type);
 
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (decl))
     {
       /* Remove the this pointer, but remember the object's type for
 	 CV quals.  */
@@ -3137,7 +3137,7 @@  check_explicit_specialization (tree declarator,
 	     make DECL a static member function as well.  */
 	  if (DECL_FUNCTION_TEMPLATE_P (tmpl)
 	      && DECL_STATIC_FUNCTION_P (tmpl)
-	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+	      && DECL_IOBJ_MEMBER_FUNCTION_P (decl))
 	    revert_static_member_fn (decl);
 
 	  /* If this is a specialization of a member template of a
@@ -11814,7 +11814,7 @@  tsubst_contract_attribute (tree decl, tree t, tree args,
   /* For member functions, make this available for semantic analysis.  */
   tree save_ccp = current_class_ptr;
   tree save_ccr = current_class_ref;
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (decl))
     {
       tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
       tree this_type = TREE_TYPE (TREE_VALUE (arg_types));
@@ -22087,7 +22087,7 @@  check_non_deducible_conversions (tree parms, const tree *args, unsigned nargs,
 {
   /* Non-constructor methods need to leave a conversion for 'this', which
      isn't included in nargs here.  */
-  unsigned offset = (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+  unsigned offset = (DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 		     && !DECL_CONSTRUCTOR_P (fn));
 
   for (unsigned ia = 0;
@@ -25314,16 +25314,16 @@  more_specialized_fn (tree pat1, tree pat2, int len)
 	 I think think the old G++ behavior of just skipping the object
 	 parameter when comparing to a static member function was better, so
 	 let's stick with that for now.  This is CWG2834.  --jason 2023-12 */
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1)) /* FIXME or explicit */
+      if (DECL_OBJECT_MEMBER_FUNCTION_P (decl1))
 	{
 	  len--; /* LEN is the number of significant arguments for DECL1 */
 	  args1 = TREE_CHAIN (args1);
 	}
-      else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2)) /* FIXME or explicit */
+      else if (DECL_OBJECT_MEMBER_FUNCTION_P (decl2))
 	args2 = TREE_CHAIN (args2);
     }
-  else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1) /* FIXME implicit only */
-	   && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
+  else if (DECL_IOBJ_MEMBER_FUNCTION_P (decl1)
+	   && DECL_IOBJ_MEMBER_FUNCTION_P (decl2))
     {
       /* Note DR2445 also (IMO wrongly) removed the "only one" above, which
 	 would break e.g.  cpp1y/lambda-generic-variadic5.C.  */
@@ -25331,12 +25331,12 @@  more_specialized_fn (tree pat1, tree pat2, int len)
       args1 = TREE_CHAIN (args1);
       args2 = TREE_CHAIN (args2);
     }
-  else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1) /* FIXME implicit only */
-	   || DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
+  else if (DECL_IOBJ_MEMBER_FUNCTION_P (decl1)
+	   || DECL_IOBJ_MEMBER_FUNCTION_P (decl2))
     {
       /* The other is a non-member or explicit object member function;
 	 rewrite the implicit object parameter to a reference.  */
-      tree ns = DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2) ? decl2 : decl1;
+      tree ns = DECL_IOBJ_MEMBER_FUNCTION_P (decl2) ? decl2 : decl1;
       tree &nsargs = ns == decl2 ? args2 : args1;
       tree obtype = TREE_TYPE (TREE_VALUE (nsargs));
 
@@ -26669,7 +26669,7 @@  maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
 	  push_deferring_access_checks (dk_no_deferred);
 	  input_location = DECL_SOURCE_LOCATION (fn);
 
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+	  if (DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 	      && !DECL_LOCAL_DECL_P (fn))
 	    {
 	      /* If needed, set current_class_ptr for the benefit of
@@ -26732,7 +26732,7 @@  register_parameter_specializations (tree pattern, tree inst)
 {
   tree tmpl_parm = DECL_ARGUMENTS (pattern);
   tree spec_parm = DECL_ARGUMENTS (inst);
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (inst))
+  if (DECL_IOBJ_MEMBER_FUNCTION_P (inst))
     {
       register_local_specialization (spec_parm, tmpl_parm);
       spec_parm = skip_artificial_parms_for (inst, spec_parm);
@@ -28075,7 +28075,7 @@  value_dependent_expression_p (tree expression)
 	       cause the call to be considered value-dependent.  We also
 	       look through it in potential_constant_expression.  */
 	    if (i == 0 && fn && DECL_DECLARED_CONSTEXPR_P (fn)
-		&& DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+		&& DECL_IOBJ_MEMBER_FUNCTION_P (fn)
 		&& TREE_CODE (op) == ADDR_EXPR)
 	      op = TREE_OPERAND (op, 0);
 	    if (value_dependent_expression_p (op))
diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index ac79b625b6e..3473d66b88c 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -1008,7 +1008,7 @@  shared_member_p (tree t)
 	    /* Conservatively assume a dependent using-declaration
 	       might resolve to a non-static member.  */
 	    return false;
-	  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+	  if (DECL_OBJECT_MEMBER_FUNCTION_P (decl))
 	    return false;
 	}
       return true;
@@ -1264,7 +1264,7 @@  lookup_member (tree xbasetype, tree name, int protect, bool want_type,
       decl = strip_using_decl (decl);
       /* A dependent USING_DECL will be checked after tsubsting.  */
       if (TREE_CODE (decl) != USING_DECL
-	  && !DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+	  && !DECL_IOBJ_MEMBER_FUNCTION_P (decl)
 	  && !perform_or_defer_access_check (basetype_path, decl, decl,
 					     complain, afi))
 	return error_mark_node;
@@ -1737,6 +1737,7 @@  field_access_p (tree component_ref, tree field_decl, tree field_type)
     return false;
 
   tree ptr = STRIP_NOPS (TREE_OPERAND (indirect_ref, 0));
+  /* ??? is_object_parameter?  */
   if (!is_this_parameter (ptr))
     return false;
 
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 64839b1ac87..3bc426fa130 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -6645,7 +6645,7 @@  finish_omp_declare_simd_methods (tree t)
   for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
     {
       if (TREE_CODE (x) == USING_DECL
-	  || !DECL_NONSTATIC_MEMBER_FUNCTION_P (x))
+	  || !DECL_IOBJ_MEMBER_FUNCTION_P (x))
 	continue;
       tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
       if (!ods || !TREE_VALUE (ods))
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index d17b9b34891..80596e3d976 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -298,7 +298,7 @@  lvalue_kind (const_tree ref)
     case FUNCTION_DECL:
       /* All functions (except non-static-member functions) are
 	 lvalues.  */
-      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
+      return (DECL_IOBJ_MEMBER_FUNCTION_P (ref)
 	      ? clk_none : clk_ordinary);
 
     case BASELINK:
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index a6e2f4ee7da..2abf9f3b905 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -2352,7 +2352,7 @@  invalid_nonstatic_memfn_p (location_t loc, tree expr, tsubst_flags_t complain)
   if (is_overloaded_fn (expr) && !really_overloaded_fn (expr))
     expr = get_first_fn (expr);
   if (TREE_TYPE (expr)
-      && DECL_NONSTATIC_MEMBER_FUNCTION_P (expr))
+      && DECL_IOBJ_MEMBER_FUNCTION_P (expr))
     {
       if (complain & tf_error)
 	{
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index 3c8e9e8b436..108d5786167 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -468,7 +468,7 @@  plugin_pragma_push_user_expression (cpp_reader *)
 	}
     }
 
-  if (unchanged_cfun || DECL_NONSTATIC_MEMBER_FUNCTION_P (changed_func_decl))
+  if (unchanged_cfun || DECL_OBJECT_MEMBER_FUNCTION_P (changed_func_decl))
     {
       /* Check whether the oracle supplies us with a "this", and if
 	 so, arrange for data members and this itself to be
-- 
2.43.0