Am 2024-09-04 um 19:12 schrieb Jakub Jelinek:
On Wed, Sep 04, 2024 at 12:34:04PM -0400, Jason Merrill wrote:
So, one possibility would be to call save_expr unconditionally in
get_member_function_from_ptrfunc as well.
Or build a TARGET_EXPR (force_target_expr or similar).
Yes. I don't have a strong preference between the two.
Here is a patch that uses save_expr but uses it still conditionally,
doesn't make sense to use it for the common case of just decls, there is
nothing to unshare in that case.
Passed the test, ok if it passes full bootstrap/regtest?
2024-09-04 Jakub Jelinek <ja...@redhat.com>
PR c++/116449
* typeck.cc (get_member_function_from_ptrfunc): Use save_expr
on instance_ptr and function even if it doesn't have side-effects,
as long as it isn't a decl.
* g++.dg/ubsan/pr116449.C: New test.
--- gcc/cp/typeck.cc.jj 2024-09-02 17:07:30.115098114 +0200
+++ gcc/cp/typeck.cc 2024-09-04 19:08:24.127490242 +0200
@@ -4188,10 +4188,21 @@ get_member_function_from_ptrfunc (tree *
if (!nonvirtual && is_dummy_object (instance_ptr))
nonvirtual = true;
- if (TREE_SIDE_EFFECTS (instance_ptr))
- instance_ptr = instance_save_expr = save_expr (instance_ptr);
+ /* Use save_expr even when instance_ptr doesn't have side-effects,
+ unless it is a simple decl (save_expr won't do anything on
+ constants), so that we don't ubsan instrument the expression
+ multiple times. See PR116449. */
+ if (TREE_SIDE_EFFECTS (instance_ptr) || !DECL_P (instance_ptr))
+ {
+ instance_save_expr = save_expr (instance_ptr);
+ if (instance_save_expr == instance_ptr)
+ instance_save_expr = NULL_TREE;
+ else
+ instance_ptr = instance_save_expr;
+ }
- if (TREE_SIDE_EFFECTS (function))
+ /* See above comment. */
+ if (TREE_SIDE_EFFECTS (function) || !DECL_P (function))
function = save_expr (function);
Hmm, it just occured to me, how about adding !NONVIRTUAL here? When
NONVIRTUAL is true, there is no conditional stmt at all, or?
Franz