On Tue, Jan 25, 2022 at 05:35:20PM -0700, Martin Sebor wrote:
> On 1/25/22 16:33, Marek Polacek via Gcc-patches wrote:
> > Here, -Wuse-after-free warns about using 'this' which, on ARM, cdtors
> > return, as mandated by the EABI.  To be entirely correct, it only
> > requires it for C1 and C2 ctors and D2 and D1 dtors, but I don't feel
> > like changing that now and possibly running into issues later on.
> > 
> > This patch uses suppress_warning on 'this' for certain cdtor_returns_this
> > cases in the C++ FE, and then warn_invalid_pointer makes use of this
> > information and doesn't warn.
> > 
> > In my first attempt I tried suppress_warning the MODIFY_EXPR or RETURN_EXPR
> > we build in build_delete_destructor_body, but the complication is that
> > the suppress_warning bits don't always survive gimplification; see e.g.
> > gimplify_modify_expr where we do
> > 
> >   6130       if (COMPARISON_CLASS_P (*from_p))
> >   6131         copy_warning (assign, *from_p);
> > 
> > but here we're not dealing with a comparison.  Removing that check
> > regresses uninit-pr74762.C.  Adding copy_warning (assign, *expr_p)
> > regresses c-c++-common/uninit-17.c.
> > 
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> 
> Thanks for picking this up!
> 
> My only concern with suppressing the warning for the pointer rather
> than just for the return statement is that it not lead to false
> negatives.  I played with the patch a little, trying to trigger one
> but couldn't so it might be unfounded.  Still, I'd expect targeting
> the statement to be a simpler change (the warning already checks
> for the suppression bit on the statement).  Did you try it?
 
I did -- that is the "In my first attempt..." paragraph in my patch
(we don't use copy_warning to propagate the suppress_warning bits).
Maybe it'd be a more correct way to approach this, that is, somehow
tweak gimplify_modify_expr to copy_warning for this special case.

> For reference, one of the test cases I tried is below.  It would
> be good to  add it to the test suite to make sure the bug is caught
> (there's a duplicate warning there that should at some point get
> squashed).
> 
> struct A
> {
>   virtual ~A ();
>   void f ();
> };
> 
> A::~A ()
> {
>   operator delete (this);
>   f ();
> }

Sure, happy to add it.

> Martin
> 
> > 
> >     PR target/104213
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * decl.cc (finish_constructor_body): Suppress -Wuse-after-free.
> >     (finish_destructor_body): Likewise.
> >     * optimize.cc (build_delete_destructor_body): Likewise.
> > 
> > gcc/ChangeLog:
> > 
> >     * gimple-ssa-warn-access.cc (pass_waccess::warn_invalid_pointer): Don't
> >     warn when the SSA_NAME_VAR of REF has supressed -Wuse-after-free.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * g++.dg/warn/Wuse-after-free2.C: New test.
> > ---
> >   gcc/cp/decl.cc                               |  2 ++
> >   gcc/cp/optimize.cc                           |  1 +
> >   gcc/gimple-ssa-warn-access.cc                | 14 +++++++++++---
> >   gcc/testsuite/g++.dg/warn/Wuse-after-free2.C | 10 ++++++++++
> >   4 files changed, 24 insertions(+), 3 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/warn/Wuse-after-free2.C
> > 
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 22d3dd1e2ad..6534a7fd320 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -17315,6 +17315,7 @@ finish_constructor_body (void)
> >         add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label));
> >         val = DECL_ARGUMENTS (current_function_decl);
> > +      suppress_warning (val, OPT_Wuse_after_free);
> >         val = build2 (MODIFY_EXPR, TREE_TYPE (val),
> >                 DECL_RESULT (current_function_decl), val);
> >         /* Return the address of the object.  */
> > @@ -17408,6 +17409,7 @@ finish_destructor_body (void)
> >         tree val;
> >         val = DECL_ARGUMENTS (current_function_decl);
> > +      suppress_warning (val, OPT_Wuse_after_free);
> >         val = build2 (MODIFY_EXPR, TREE_TYPE (val),
> >                 DECL_RESULT (current_function_decl), val);
> >         /* Return the address of the object.  */
> > diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc
> > index 4ad3f1dc9aa..13ab8b7361e 100644
> > --- a/gcc/cp/optimize.cc
> > +++ b/gcc/cp/optimize.cc
> > @@ -166,6 +166,7 @@ build_delete_destructor_body (tree delete_dtor, tree 
> > complete_dtor)
> >     if (targetm.cxx.cdtor_returns_this ())
> >       {
> >         tree val = DECL_ARGUMENTS (delete_dtor);
> > +      suppress_warning (val, OPT_Wuse_after_free);
> >         val = build2 (MODIFY_EXPR, TREE_TYPE (val),
> >                       DECL_RESULT (delete_dtor), val);
> >         add_stmt (build_stmt (0, RETURN_EXPR, val));
> > diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
> > index 8bc33eeb6fa..484bcd34c25 100644
> > --- a/gcc/gimple-ssa-warn-access.cc
> > +++ b/gcc/gimple-ssa-warn-access.cc
> > @@ -3880,9 +3880,17 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple 
> > *use_stmt,
> >                                 bool maybe, bool equality /* = false */)
> >   {
> >     /* Avoid printing the unhelpful "<unknown>" in the diagnostics.  */
> > -  if (ref && TREE_CODE (ref) == SSA_NAME
> > -      && (!SSA_NAME_VAR (ref) || DECL_ARTIFICIAL (SSA_NAME_VAR (ref))))
> > -    ref = NULL_TREE;
> > +  if (ref && TREE_CODE (ref) == SSA_NAME)
> > +    {
> > +      tree var = SSA_NAME_VAR (ref);
> > +      if (!var)
> > +   ref = NULL_TREE;
> > +      /* Don't warn for cases like when a cdtor returns 'this' on ARM.  */
> > +      else if (warning_suppressed_p (var, OPT_Wuse_after_free))
> > +   return;
> > +      else if (DECL_ARTIFICIAL (var))
> > +   ref = NULL_TREE;
> > +    }
> >     location_t use_loc = gimple_location (use_stmt);
> >     if (use_loc == UNKNOWN_LOCATION)
> > diff --git a/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C 
> > b/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C
> > new file mode 100644
> > index 00000000000..6d5f2bf01b5
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C
> > @@ -0,0 +1,10 @@
> > +// PR target/104213
> > +// { dg-do compile }
> > +// { dg-options "-Wuse-after-free" }
> > +
> > +class C
> > +{
> > +    virtual ~C();
> > +};
> > +
> > +C::~C() {} // { dg-bogus "used after" }
> > 
> > base-commit: aeac414923aa1e87986c7fc6f9b921d89a9b86cf
> 

Marek

Reply via email to