On Mon, Jun 22, 2026 at 12:18:26PM -0400, Jason Merrill wrote:
> On 6/22/26 12:08 PM, Marek Polacek wrote:
> > On Fri, Jun 19, 2026 at 01:44:23PM -0400, Jason Merrill wrote:
> > > On 6/18/26 6:09 PM, Marek Polacek wrote:
> > > > FWIW, Jakub seems to agree with this patch in the PR.
> > > > 
> > > > Tested reflect/* on x86_64-pc-linux-gnu, ok for trunk/16?
> > > > 
> > > > -- >8 --
> > > > members_of doesn't append the call operator of a closure type
> > > > to ELTS in class_members_of and so the assert in the test doesn't
> > > > pass.
> > > > 
> > > >         PR c++/125889
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > >         * reflect.cc (class_members_of): Also append LAMBDA_FUNCTION_P
> > > >         from the implicitly_declared vector.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > >         * g++.dg/reflect/members_of16.C: New test.
> > > > ---
> > > >    gcc/cp/reflect.cc                           | 7 +++++++
> > > >    gcc/testsuite/g++.dg/reflect/members_of16.C | 8 ++++++++
> > > >    2 files changed, 15 insertions(+)
> > > >    create mode 100644 gcc/testsuite/g++.dg/reflect/members_of16.C
> > > > 
> > > > diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
> > > > index 8dccf5e99a0..f15be65c246 100644
> > > > --- a/gcc/cp/reflect.cc
> > > > +++ b/gcc/cp/reflect.cc
> > > > @@ -7077,6 +7077,13 @@ class_members_of (location_t loc, const 
> > > > constexpr_ctx *ctx, tree r,
> > > >                                     get_reflection_raw (loc, m));
> > > >             break;
> > > >           }
> > > > +      for (tree m : implicitly_declared)
> > > > +       if (LAMBDA_FUNCTION_P (m))
> > > > +         {
> > > > +           CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
> > > > +                                   get_reflection_raw (loc, m));
> > > > +           break;
> > > > +         }
> > > >        }
> > > >      return elts;
> > > >    }
> > > > diff --git a/gcc/testsuite/g++.dg/reflect/members_of16.C 
> > > > b/gcc/testsuite/g++.dg/reflect/members_of16.C
> > > > new file mode 100644
> > > > index 00000000000..f23d979e639
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/g++.dg/reflect/members_of16.C
> > > > @@ -0,0 +1,8 @@
> > > > +// PR c++/125889
> > > > +// { dg-do compile { target c++26 } }
> > > > +// { dg-additional-options "-freflection" }
> > > > +
> > > > +#include <meta>
> > > > +
> > > > +using L = decltype([]{});
> > > > +static_assert(std::meta::members_of(^^L, 
> > > > std::meta::access_context::unchecked()).size() > 0);
> > > 
> > > It seems desirable to check specifically for the call operator, since "It 
> > > is
> > > implementation-defined whether declarations of other members of a closure
> > > type Q are Q-members-of-eligible."
> > 
> > I can check if we have meta::is_operator_function.  Or do you want me
> > to check something else as well?
> 
> Under the above quote it doesn't seem portable to assume the call operator
> is at index 0, but I guess it's OK with a comment.

This is true; I've added a comment.  The correct way would be to
scan the elements members_of gave us.
 
> Incidentally, I'm surprised the standard doesn't specify that the conversion
> function (https://eel.is/c++draft/expr.prim#lambda.closure-11) is
> members-of-eligible.

I assume that's due to "The function call operator or the function call operator
template are direct members of the closure type" not present for the conversion
fn.  Perhaps the problem is that the conversion fn is in the lambda only
conditionally.

Here's v3:

-- >8 --
members_of doesn't append the call operator of a closure type
to ELTS in class_members_of and so the assert in the test doesn't
pass.

        PR c++/125889

gcc/cp/ChangeLog:

        * reflect.cc (class_members_of): Also append LAMBDA_FUNCTION_P
        from the implicitly_declared vector.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/members_of16.C: New test.
---
 gcc/cp/reflect.cc                           |  7 +++++++
 gcc/testsuite/g++.dg/reflect/members_of16.C | 14 ++++++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/reflect/members_of16.C

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 8dccf5e99a0..f15be65c246 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -7077,6 +7077,13 @@ class_members_of (location_t loc, const constexpr_ctx 
*ctx, tree r,
                                    get_reflection_raw (loc, m));
            break;
          }
+      for (tree m : implicitly_declared)
+       if (LAMBDA_FUNCTION_P (m))
+         {
+           CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
+                                   get_reflection_raw (loc, m));
+           break;
+         }
     }
   return elts;
 }
diff --git a/gcc/testsuite/g++.dg/reflect/members_of16.C 
b/gcc/testsuite/g++.dg/reflect/members_of16.C
new file mode 100644
index 00000000000..5a59c69728b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/members_of16.C
@@ -0,0 +1,14 @@
+// PR c++/125889
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+using L = decltype([]{});
+/* There should be at least operator().  */
+static_assert(members_of(^^L, std::meta::access_context::unchecked()).size() > 
0);
+/* This is lazy; there can be more members than the call operator:
+   "It is implementation-defined whether declarations of other members of
+   a closure type Q are Q-members-of-eligible."  At least we'll know when
+   something changes, though.  */
+static_assert(is_operator_function(members_of(^^L, 
std::meta::access_context::unchecked())[0]));

base-commit: 2918eed569574b0c2136256b9898a3287135a899
-- 
2.54.0

Reply via email to