On Wednesday, March 4th, 2026 at 9:48 PM, Marek Polacek <[email protected]> wrote:
> On Wed, Mar 04, 2026 at 09:26:32PM +0000, Boris Staletic wrote: > > On Wednesday, March 4th, 2026 at 8:29 PM, Jakub Jelinek <[email protected]> > > wrote: > > > > > On Wed, Mar 04, 2026 at 03:21:26PM -0500, Jason Merrill wrote: > > > > On 3/4/26 2:35 PM, Boris Staletic wrote: > > > > > Bootstrapped and tested on tested on x86_64-pc-linux-gnu. > > > > > For the patch I did run the entire `make check`. > > > > > > > > > > I don't think the error message is great, > > > > > but I'm not sure how to improve it. > > > > > I did try `%D` to format the scope as well, > > > > > but that fails when the reflected entity has TU scope. > > > > > > > > No need, I think; for decls outside the global namespace printing the > > > > spliced decl will print its scope without needing to repeat it. But > > > > let's > > > > use %q#D instead of %<%D%>, 'q' to add quotes and # to add > > > > decl-specifiers. > > > > And you might add > > > > > > > > inform (DECL_SOURCE_LOCATION (decl), "declared here"); > > > > > > > > after the error. > > > > Done. > > > > > > > > But in that case also > > > auto_diagnostic_group d; > > > > Done. > > > > > to group error and inform together. > > > > > > Jakub > > > > > > > > > > Here's the v2. > > -- >8 -- > > We have to allow splicing "regular" variables > > (i.e. VAR_P (name) == true), because of static data members. > > The rest of the finish_class_member_access_expr() assumes that, > > if there's a scope, it is of a class type (i.e. `CLASS_TYPE_P (scope)`). > > > > For that reason, checking that `CLASS_TYPE_P (scope)` holds (and erroring > > otherwise), is necessary. > > > > Signed-off-by: Boris Staletic <[email protected]> > > > > PR c++/123726 > > > > gcc/cp/ChangeLog: > > > > * typeck.cc: (finish_class_member_access_expr): Check if > > Extra ':' after typeck.cc. Fixed. > > > the scope of the spliced entity in a member access expression > > is of a class type. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/reflect/member21.C: New test. > > --- > > gcc/cp/typeck.cc | 14 +++++++++++++- > > gcc/testsuite/g++.dg/reflect/member21.C | 13 +++++++++++++ > > 2 files changed, 26 insertions(+), 1 deletion(-) > > create mode 100644 gcc/testsuite/g++.dg/reflect/member21.C > > > > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc > > index 79eb3b5ba2..afe8a1ddf6 100644 > > --- a/gcc/cp/typeck.cc > > +++ b/gcc/cp/typeck.cc > > @@ -3600,7 +3600,19 @@ finish_class_member_access_expr (cp_expr object, > > tree name, bool template_p, > > || TREE_CODE (name) == CONST_DECL > > || TREE_CODE (name) == FUNCTION_DECL > > || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (name)))) > > - scope = context_for_name_lookup (OVL_FIRST (name)); > > + { > > + scope = context_for_name_lookup (OVL_FIRST (name)); > > + if (!CLASS_TYPE_P (scope)) > > + { > > + auto_diagnostic_group d; > > I think I'd move this auto_diagnostic_group into the following block. > Yeah... noticed immediately after sending v2. Fixed now. > > + if (complain & tf_error) > > + { > > + error ("%q#D is not a member of %qT", name, object_type); > > + inform (DECL_SOURCE_LOCATION (name), "declared here"); > > + } > > + return error_mark_node; > > + } > > + } > > > > if (TREE_CODE (name) == TEMPLATE_ID_EXPR) > > { > > diff --git a/gcc/testsuite/g++.dg/reflect/member21.C > > b/gcc/testsuite/g++.dg/reflect/member21.C > > new file mode 100644 > > index 0000000000..2b6222ec1a > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/reflect/member21.C > > @@ -0,0 +1,13 @@ > > Add > // PR c++/123726 Added. > > Otherwise I'm OK with the patch, thanks! > > > +// { dg-do compile { target c++26 } } > > +// { dg-additional-options "-freflection" } > > + > > +struct S {}; > > +int x; > > +void f() {} > > + > > +int main() { > > + S s; > > + s.[:^^x:]; // { dg-error "not a member of .S." } > > + s.[:^^s:]; // { dg-error "not a member of .S." } > > + s.[:^^f:]; // { dg-error "not a member of .S." } > > +} > > -- > > 2.51.1 > > > > Marek > > Here's the v3. -- >8 -- We have to allow splicing "regular" variables (i.e. VAR_P (name) == true), because of static data members. The rest of the finish_class_member_access_expr() assumes that, if there's a scope, it is of a class type (i.e. `CLASS_TYPE_P (scope)`). For that reason, checking that `CLASS_TYPE_P (scope)` holds (and erroring otherwise), is necessary. Signed-off-by: Boris Staletic <[email protected]> PR c++/123726 gcc/cp/ChangeLog: * typeck.cc (finish_class_member_access_expr): Check if the scope of the spliced entity in a member access expression is of a class type. gcc/testsuite/ChangeLog: * g++.dg/reflect/member21.C: New test. --- gcc/cp/typeck.cc | 14 +++++++++++++- gcc/testsuite/g++.dg/reflect/member21.C | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/reflect/member21.C diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 79eb3b5ba2..fd6f92bc27 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -3600,7 +3600,19 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p, || TREE_CODE (name) == CONST_DECL || TREE_CODE (name) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (name)))) - scope = context_for_name_lookup (OVL_FIRST (name)); + { + scope = context_for_name_lookup (OVL_FIRST (name)); + if (!CLASS_TYPE_P (scope)) + { + if (complain & tf_error) + { + auto_diagnostic_group d; + error ("%q#D is not a member of %qT", name, object_type); + inform (DECL_SOURCE_LOCATION (name), "declared here"); + } + return error_mark_node; + } + } if (TREE_CODE (name) == TEMPLATE_ID_EXPR) { diff --git a/gcc/testsuite/g++.dg/reflect/member21.C b/gcc/testsuite/g++.dg/reflect/member21.C new file mode 100644 index 0000000000..1173ebf298 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/member21.C @@ -0,0 +1,14 @@ +// PR c++/123726 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +struct S {}; +int x; +void f() {} + +int main() { + S s; + s.[:^^x:]; // { dg-error "not a member of .S." } + s.[:^^s:]; // { dg-error "not a member of .S." } + s.[:^^f:]; // { dg-error "not a member of .S." } +} -- 2.51.1
