* [PATCH] c++: mark TARGET_EXPRs for function arguments eliding [PR114707]
@ 2024-05-23 14:41 Marek Polacek
2024-05-23 20:04 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Marek Polacek @ 2024-05-23 14:41 UTC (permalink / raw)
To: Jason Merrill, GCC Patches
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
Coming back to our discussion in
<https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
TARGET_EXPRs that initialize a function argument are not marked
TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
on the floor. To work around it, I added a pset to
replace_placeholders_for_class_temp_r, but it would be best to just rely
on TARGET_EXPR_ELIDING_P.
This patch changes the diagnostic we emit in constexpr-diag1.C: instead
of:
constexpr-diag1.C:20:21: error: temporary of non-literal type 'B' in a constant expression
we say:
constexpr-diag1.C:20:23: error: call to non-'constexpr' function 'B::B()'
PR c++/114707
gcc/cp/ChangeLog:
* call.cc (convert_for_arg_passing): Call set_target_expr_eliding.
* typeck2.cc (replace_placeholders_for_class_temp_r): Don't use pset.
(digest_nsdmi_init): Call cp_walk_tree_without_duplicates instead of
cp_walk_tree.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/constexpr-diag1.C: Adjust dg-error.
---
gcc/cp/call.cc | 3 +++
gcc/cp/typeck2.cc | 20 ++++----------------
gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C | 2 +-
3 files changed, 8 insertions(+), 17 deletions(-)
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index ed68eb3c568..750ecf60fd9 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9437,6 +9437,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
if (complain & tf_warning)
warn_for_address_of_packed_member (type, val);
+ /* gimplify_arg elides TARGET_EXPRs that initialize a function argument. */
+ set_target_expr_eliding (val);
+
return val;
}
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 06bad4d3303..7782f38da43 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1409,16 +1409,14 @@ digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain)
in the context of guaranteed copy elision). */
static tree
-replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
+replace_placeholders_for_class_temp_r (tree *tp, int *, void *)
{
tree t = *tp;
- auto pset = static_cast<hash_set<tree> *>(data);
/* We're looking for a TARGET_EXPR nested in the whole expression. */
if (TREE_CODE (t) == TARGET_EXPR
/* That serves as temporary materialization, not an initializer. */
- && !TARGET_EXPR_ELIDING_P (t)
- && !pset->add (t))
+ && !TARGET_EXPR_ELIDING_P (t))
{
tree init = TARGET_EXPR_INITIAL (t);
while (TREE_CODE (init) == COMPOUND_EXPR)
@@ -1433,16 +1431,6 @@ replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
gcc_checking_assert (!find_placeholders (init));
}
}
- /* TARGET_EXPRs initializing function arguments are not marked as eliding,
- even though gimplify_arg drops them on the floor. Don't go replacing
- placeholders in them. */
- else if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
- for (int i = 0; i < call_expr_nargs (t); ++i)
- {
- tree arg = get_nth_callarg (t, i);
- if (TREE_CODE (arg) == TARGET_EXPR && !TARGET_EXPR_ELIDING_P (arg))
- pset->add (arg);
- }
return NULL_TREE;
}
@@ -1490,8 +1478,8 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain)
temporary materialization does not occur when initializing an object
from a prvalue of the same type, therefore we must not replace the
placeholder with a temporary object so that it can be elided. */
- hash_set<tree> pset;
- cp_walk_tree (&init, replace_placeholders_for_class_temp_r, &pset, nullptr);
+ cp_walk_tree_without_duplicates (&init, replace_placeholders_for_class_temp_r,
+ nullptr);
return init;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
index ccb8d81adca..da6fc2030bc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
@@ -17,4 +17,4 @@ constexpr int b = A<B>().f(); // { dg-error "" }
template <class T>
constexpr int f (T t) { return 42; }
-constexpr int x = f(B()); // { dg-error "non-literal" }
+constexpr int x = f(B()); // { dg-error "call to non-.constexpr." }
base-commit: 2b2476d4d18c92b8aba3567ebccd2100c2f7c258
--
2.45.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: mark TARGET_EXPRs for function arguments eliding [PR114707]
2024-05-23 14:41 [PATCH] c++: mark TARGET_EXPRs for function arguments eliding [PR114707] Marek Polacek
@ 2024-05-23 20:04 ` Jason Merrill
2024-05-24 0:32 ` [PATCH v2] " Marek Polacek
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2024-05-23 20:04 UTC (permalink / raw)
To: Marek Polacek, GCC Patches
On 5/23/24 10:41, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> -- >8 --
> Coming back to our discussion in
> <https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
> TARGET_EXPRs that initialize a function argument are not marked
> TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
> on the floor.
But only if TREE_TYPE (TARGET_EXPR_INITIAL is non-void, I think we
should check that here too to be parallel.
Perhaps most/all affected TARGET_EXPRs will have been handled earlier in
the function under the TREE_ADDRESSABLE check, but I wouldn't rely on
that without an assert.
> To work around it, I added a pset to
> replace_placeholders_for_class_temp_r, but it would be best to just rely
> on TARGET_EXPR_ELIDING_P.
>
> This patch changes the diagnostic we emit in constexpr-diag1.C: instead
> of:
>
> constexpr-diag1.C:20:21: error: temporary of non-literal type 'B' in a constant expression
>
> we say:
>
> constexpr-diag1.C:20:23: error: call to non-'constexpr' function 'B::B()'
>
> PR c++/114707
>
> gcc/cp/ChangeLog:
>
> * call.cc (convert_for_arg_passing): Call set_target_expr_eliding.
> * typeck2.cc (replace_placeholders_for_class_temp_r): Don't use pset.
> (digest_nsdmi_init): Call cp_walk_tree_without_duplicates instead of
> cp_walk_tree.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp0x/constexpr-diag1.C: Adjust dg-error.
> ---
> gcc/cp/call.cc | 3 +++
> gcc/cp/typeck2.cc | 20 ++++----------------
> gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C | 2 +-
> 3 files changed, 8 insertions(+), 17 deletions(-)
>
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index ed68eb3c568..750ecf60fd9 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -9437,6 +9437,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
> if (complain & tf_warning)
> warn_for_address_of_packed_member (type, val);
>
> + /* gimplify_arg elides TARGET_EXPRs that initialize a function argument. */
> + set_target_expr_eliding (val);
> +
> return val;
> }
>
> diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
> index 06bad4d3303..7782f38da43 100644
> --- a/gcc/cp/typeck2.cc
> +++ b/gcc/cp/typeck2.cc
> @@ -1409,16 +1409,14 @@ digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain)
> in the context of guaranteed copy elision). */
>
> static tree
> -replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
> +replace_placeholders_for_class_temp_r (tree *tp, int *, void *)
> {
> tree t = *tp;
> - auto pset = static_cast<hash_set<tree> *>(data);
>
> /* We're looking for a TARGET_EXPR nested in the whole expression. */
> if (TREE_CODE (t) == TARGET_EXPR
> /* That serves as temporary materialization, not an initializer. */
> - && !TARGET_EXPR_ELIDING_P (t)
> - && !pset->add (t))
> + && !TARGET_EXPR_ELIDING_P (t))
> {
> tree init = TARGET_EXPR_INITIAL (t);
> while (TREE_CODE (init) == COMPOUND_EXPR)
> @@ -1433,16 +1431,6 @@ replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
> gcc_checking_assert (!find_placeholders (init));
> }
> }
> - /* TARGET_EXPRs initializing function arguments are not marked as eliding,
> - even though gimplify_arg drops them on the floor. Don't go replacing
> - placeholders in them. */
> - else if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
> - for (int i = 0; i < call_expr_nargs (t); ++i)
> - {
> - tree arg = get_nth_callarg (t, i);
> - if (TREE_CODE (arg) == TARGET_EXPR && !TARGET_EXPR_ELIDING_P (arg))
> - pset->add (arg);
> - }
>
> return NULL_TREE;
> }
> @@ -1490,8 +1478,8 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain)
> temporary materialization does not occur when initializing an object
> from a prvalue of the same type, therefore we must not replace the
> placeholder with a temporary object so that it can be elided. */
> - hash_set<tree> pset;
> - cp_walk_tree (&init, replace_placeholders_for_class_temp_r, &pset, nullptr);
> + cp_walk_tree_without_duplicates (&init, replace_placeholders_for_class_temp_r,
> + nullptr);
>
> return init;
> }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
> index ccb8d81adca..da6fc2030bc 100644
> --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
> +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
> @@ -17,4 +17,4 @@ constexpr int b = A<B>().f(); // { dg-error "" }
>
> template <class T>
> constexpr int f (T t) { return 42; }
> -constexpr int x = f(B()); // { dg-error "non-literal" }
> +constexpr int x = f(B()); // { dg-error "call to non-.constexpr." }
>
> base-commit: 2b2476d4d18c92b8aba3567ebccd2100c2f7c258
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] c++: mark TARGET_EXPRs for function arguments eliding [PR114707]
2024-05-23 20:04 ` Jason Merrill
@ 2024-05-24 0:32 ` Marek Polacek
2024-05-24 14:01 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Marek Polacek @ 2024-05-24 0:32 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Thu, May 23, 2024 at 04:04:13PM -0400, Jason Merrill wrote:
> On 5/23/24 10:41, Marek Polacek wrote:
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > -- >8 --
> > Coming back to our discussion in
> > <https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
> > TARGET_EXPRs that initialize a function argument are not marked
> > TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
> > on the floor.
>
> But only if TREE_TYPE (TARGET_EXPR_INITIAL is non-void, I think we should
> check that here too to be parallel.
Ah yes, definitely.
> Perhaps most/all affected TARGET_EXPRs will have been handled earlier in the
> function under the TREE_ADDRESSABLE check, but I wouldn't rely on that
> without an assert.
So like this or you want an assert somewhere too? dg.exp passed.
-- >8 --
Coming back to our discussion in
<https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
TARGET_EXPRs that initialize a function argument are not marked
TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
on the floor. To work around it, I added a pset to
replace_placeholders_for_class_temp_r, but it would be best to just rely
on TARGET_EXPR_ELIDING_P.
PR c++/114707
gcc/cp/ChangeLog:
* call.cc (convert_for_arg_passing): Call set_target_expr_eliding.
* typeck2.cc (replace_placeholders_for_class_temp_r): Don't use pset.
(digest_nsdmi_init): Call cp_walk_tree_without_duplicates instead of
cp_walk_tree.
---
gcc/cp/call.cc | 6 ++++++
gcc/cp/typeck2.cc | 20 ++++----------------
2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index ed68eb3c568..35c024f2c7c 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9437,6 +9437,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
if (complain & tf_warning)
warn_for_address_of_packed_member (type, val);
+ /* gimplify_arg elides TARGET_EXPRs that initialize a function argument. */
+ if (TREE_CODE (val) == TARGET_EXPR)
+ if (tree init = TARGET_EXPR_INITIAL (val))
+ if (!VOID_TYPE_P (TREE_TYPE (init)))
+ set_target_expr_eliding (val);
+
return val;
}
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 06bad4d3303..7782f38da43 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1409,16 +1409,14 @@ digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain)
in the context of guaranteed copy elision). */
static tree
-replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
+replace_placeholders_for_class_temp_r (tree *tp, int *, void *)
{
tree t = *tp;
- auto pset = static_cast<hash_set<tree> *>(data);
/* We're looking for a TARGET_EXPR nested in the whole expression. */
if (TREE_CODE (t) == TARGET_EXPR
/* That serves as temporary materialization, not an initializer. */
- && !TARGET_EXPR_ELIDING_P (t)
- && !pset->add (t))
+ && !TARGET_EXPR_ELIDING_P (t))
{
tree init = TARGET_EXPR_INITIAL (t);
while (TREE_CODE (init) == COMPOUND_EXPR)
@@ -1433,16 +1431,6 @@ replace_placeholders_for_class_temp_r (tree *tp, int *, void *data)
gcc_checking_assert (!find_placeholders (init));
}
}
- /* TARGET_EXPRs initializing function arguments are not marked as eliding,
- even though gimplify_arg drops them on the floor. Don't go replacing
- placeholders in them. */
- else if (TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == AGGR_INIT_EXPR)
- for (int i = 0; i < call_expr_nargs (t); ++i)
- {
- tree arg = get_nth_callarg (t, i);
- if (TREE_CODE (arg) == TARGET_EXPR && !TARGET_EXPR_ELIDING_P (arg))
- pset->add (arg);
- }
return NULL_TREE;
}
@@ -1490,8 +1478,8 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain)
temporary materialization does not occur when initializing an object
from a prvalue of the same type, therefore we must not replace the
placeholder with a temporary object so that it can be elided. */
- hash_set<tree> pset;
- cp_walk_tree (&init, replace_placeholders_for_class_temp_r, &pset, nullptr);
+ cp_walk_tree_without_duplicates (&init, replace_placeholders_for_class_temp_r,
+ nullptr);
return init;
}
base-commit: ee492101c2e51b58e926307448d35f539aec0b2c
--
2.45.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] c++: mark TARGET_EXPRs for function arguments eliding [PR114707]
2024-05-24 0:32 ` [PATCH v2] " Marek Polacek
@ 2024-05-24 14:01 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2024-05-24 14:01 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 5/23/24 20:32, Marek Polacek wrote:
> On Thu, May 23, 2024 at 04:04:13PM -0400, Jason Merrill wrote:
>> On 5/23/24 10:41, Marek Polacek wrote:
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>>>
>>> -- >8 --
>>> Coming back to our discussion in
>>> <https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
>>> TARGET_EXPRs that initialize a function argument are not marked
>>> TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
>>> on the floor.
>>
>> But only if TREE_TYPE (TARGET_EXPR_INITIAL is non-void, I think we should
>> check that here too to be parallel.
>
> Ah yes, definitely.
>
>> Perhaps most/all affected TARGET_EXPRs will have been handled earlier in the
>> function under the TREE_ADDRESSABLE check, but I wouldn't rely on that
>> without an assert.
>
> So like this or you want an assert somewhere too? dg.exp passed.
>
> -- >8 --
> Coming back to our discussion in
> <https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649426.html>:
> TARGET_EXPRs that initialize a function argument are not marked
> TARGET_EXPR_ELIDING_P even though gimplify_arg drops such TARGET_EXPRs
> on the floor. To work around it, I added a pset to
> replace_placeholders_for_class_temp_r, but it would be best to just rely
> on TARGET_EXPR_ELIDING_P.
>
> PR c++/114707
>
> gcc/cp/ChangeLog:
>
> * call.cc (convert_for_arg_passing): Call set_target_expr_eliding.
> * typeck2.cc (replace_placeholders_for_class_temp_r): Don't use pset.
> (digest_nsdmi_init): Call cp_walk_tree_without_duplicates instead of
> cp_walk_tree.
> ---
> gcc/cp/call.cc | 6 ++++++
> gcc/cp/typeck2.cc | 20 ++++----------------
> 2 files changed, 10 insertions(+), 16 deletions(-)
>
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index ed68eb3c568..35c024f2c7c 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -9437,6 +9437,12 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
> if (complain & tf_warning)
> warn_for_address_of_packed_member (type, val);
>
> + /* gimplify_arg elides TARGET_EXPRs that initialize a function argument. */
> + if (TREE_CODE (val) == TARGET_EXPR)
> + if (tree init = TARGET_EXPR_INITIAL (val))
> + if (!VOID_TYPE_P (TREE_TYPE (init)))
You can simplify this test to 'if (SIMPLE_TARGET_EXPR_P ...'. OK with
that change.
Jason
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-05-24 14:01 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-23 14:41 [PATCH] c++: mark TARGET_EXPRs for function arguments eliding [PR114707] Marek Polacek
2024-05-23 20:04 ` Jason Merrill
2024-05-24 0:32 ` [PATCH v2] " Marek Polacek
2024-05-24 14:01 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).