On 6/22/26 2:14 PM, Marek Polacek wrote:
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.
Well yes, but I wonder why it isn't present.
Perhaps the problem is that the conversion fn is in the lambda only
conditionally.
That doesn't seem like a reason not to include it when it is there.
Perhaps there were some implementation issues in other implementations?
I don't remember, and don't feel like doing wiki archaeology just now.
Here's v3:
OK.
-- >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