Message ID | 20211018081258.GV304296@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Diagnose taking address of an immediate member function [PR102753] | expand |
On 10/18/21 04:12, Jakub Jelinek wrote: > Hi! > > The following testcase ICEs, because while we have in cp_build_addr_expr_1 > diagnostics for taking address of an immediate function (and as an exception > deal with build_address from immediate invocation), I forgot to diagnose > taking address of a member function which is done in a different place. > I hope (s.*&S::foo) () is not an immediate invocation like > (*&foo) () is not, so this patch just diagnoses taking address of a member > function when not in immediate context. > > Bootstrapped/regtested on x86_64-linux and i686-linux (without go, > that seem to have some evrp issue when building libgo on both), ok for > trunk? > > 2021-10-18 Jakub Jelinek <jakub@redhat.com> > > PR c++/102753 > * typeck.c (cp_build_addr_expr_1): Diagnose taking address of > an immediate method. Use t instead of TREE_OPERAND (arg, 1). > > * g++.dg/cpp2a/consteval20.C: New test. > > --- gcc/cp/typeck.c.jj 2021-10-05 09:53:55.382734051 +0200 > +++ gcc/cp/typeck.c 2021-10-15 19:28:38.034213437 +0200 > @@ -6773,9 +6773,21 @@ cp_build_addr_expr_1 (tree arg, bool str > return error_mark_node; > } > > + if (TREE_CODE (t) == FUNCTION_DECL > + && DECL_IMMEDIATE_FUNCTION_P (t) > + && cp_unevaluated_operand == 0 > + && (current_function_decl == NULL_TREE > + || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))) This doesn't cover some of the other cases of immediate context; we should probably factor most of immediate_invocation_p out into a function called something like in_immediate_context and use it here, and in several other places as well. > + { > + if (complain & tf_error) > + error_at (loc, "taking address of an immediate function %qD", > + t); > + return error_mark_node; > + } > + > type = build_ptrmem_type (context_for_name_lookup (t), > TREE_TYPE (t)); > - t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); > + t = make_ptrmem_cst (type, t); > return t; > } > > --- gcc/testsuite/g++.dg/cpp2a/consteval20.C.jj 2021-10-15 19:40:38.691900472 +0200 > +++ gcc/testsuite/g++.dg/cpp2a/consteval20.C 2021-10-15 19:49:15.281508419 +0200 > @@ -0,0 +1,24 @@ > +// PR c++/102753 > +// { dg-do compile { target c++20 } } > + > +struct S { > + consteval int foo () const { return 42; } > +}; > + > +constexpr S s; > + > +int > +bar () > +{ > + return (s.*&S::foo) (); // { dg-error "taking address of an immediate function" } > +} > + > +constexpr auto a = &S::foo; // { dg-error "taking address of an immediate function" } > + > +consteval int > +baz () > +{ > + return (s.*&S::foo) (); > +} > + > +static_assert (baz () == 42); > > Jakub >
--- gcc/cp/typeck.c.jj 2021-10-05 09:53:55.382734051 +0200 +++ gcc/cp/typeck.c 2021-10-15 19:28:38.034213437 +0200 @@ -6773,9 +6773,21 @@ cp_build_addr_expr_1 (tree arg, bool str return error_mark_node; } + if (TREE_CODE (t) == FUNCTION_DECL + && DECL_IMMEDIATE_FUNCTION_P (t) + && cp_unevaluated_operand == 0 + && (current_function_decl == NULL_TREE + || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))) + { + if (complain & tf_error) + error_at (loc, "taking address of an immediate function %qD", + t); + return error_mark_node; + } + type = build_ptrmem_type (context_for_name_lookup (t), TREE_TYPE (t)); - t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); + t = make_ptrmem_cst (type, t); return t; } --- gcc/testsuite/g++.dg/cpp2a/consteval20.C.jj 2021-10-15 19:40:38.691900472 +0200 +++ gcc/testsuite/g++.dg/cpp2a/consteval20.C 2021-10-15 19:49:15.281508419 +0200 @@ -0,0 +1,24 @@ +// PR c++/102753 +// { dg-do compile { target c++20 } } + +struct S { + consteval int foo () const { return 42; } +}; + +constexpr S s; + +int +bar () +{ + return (s.*&S::foo) (); // { dg-error "taking address of an immediate function" } +} + +constexpr auto a = &S::foo; // { dg-error "taking address of an immediate function" } + +consteval int +baz () +{ + return (s.*&S::foo) (); +} + +static_assert (baz () == 42);