[PATCH] tree-optimization/104475 - bogus -Wstringop-overflow
Richard Biener
rguenther@suse.de
Wed Jan 18 08:06:34 GMT 2023
On Tue, 17 Jan 2023, Jason Merrill wrote:
> On 12/7/22 06:25, Richard Biener wrote:
> > The following avoids a bogus -Wstringop-overflow diagnostic by
> > properly recognizing that &d->m_mutex cannot be nullptr in C++
> > even if m_mutex is at offset zero. The frontend already diagnoses
> > a &d->m_mutex != nullptr comparison and the following transfers
> > this knowledge to the middle-end which sees &d->m_mutex as
> > simple pointer arithmetic. The new ADDR_NONZERO flag on an
> > ADDR_EXPR is used to carry this information and it's checked in
> > the tree_expr_nonzero_p API which causes this to be folded early.
> >
> > To avoid the bogus diagnostic this avoids separating the nullptr
> > path via jump-threading by eliminating the nullptr check.
> >
> > I'd appreciate C++ folks picking this up and put the flag on
> > the appropriate ADDR_EXPRs - I've tried avoiding to put it on
> > all of them and didn't try hard to mimick what -Waddress warns
> > on (the code is big, maybe some refactoring would help but also
> > not sure what exactly the C++ standard constraints are here).
>
> This is allowed by the standard, at least after CWG2535, but we need to check
> -fsanitize=null before asserting that the address is non-null. With that
> elaboration, a flag on the ADDR_EXPR may not be a convenient way to express
> the property?
Adding a flag on the ADDR_EXPR was mostly out of caution for other
languages that do not have this guarantee (it seems C has a similar
guarantee at least) and for the middle-end (accidentially) producing
such expressions. That is, I intended to set the flag on ADDR_EXPRs
written by the user as opposed to those created artificially.
I noticed the &* contraction rule and wondered how to conservatively
enforce that - I suppose we'd rely on the frontend to never actually
produce the ADDR_EXPR here.
That said, we could re-define GENERIC/GIMPLE here to the extent
that ADDR_EXPR of a COMPONENT_REF (or all handled components?)
is never nullptr when the target specifies nullptr is not a valid
object address. We currently already assert there's a valid
object for &p->x if x lives at non-zero offset, so the case we
fail to handle is specifically _only_ the one the component is
at offset zero. Note &p->x != (void *)4 isn't currently optimized
when x is at offset 4 even though *p would be at address zero
and -Waddress also doesn't diagnose this case - we could
canonicalize this to to p != (void *)0 but then we cannot
treat this as false anymore because of the address-taking of a component.
Richard.
> > Bootstrapped and tested on x86_64-unknown-linux-gnu.
> >
> > Thanks,
> > Richard.
> >
> > PR tree-optimization/104475
> > gcc/
> > * tree-core.h: Document use of nothrow_flag on ADDR_EXPR.
> > * tree.h (ADDR_NONZERO): New.
> > * fold-const.cc (tree_single_nonzero_warnv_p): Check
> > ADDR_NONZERO.
> >
> > gcc/cp/
> > * typeck.cc (cp_build_addr_expr_1): Set ADDR_NONZERO
> > on the built address if it is of a COMPONENT_REF.
> >
> > * g++.dg/opt/pr104475.C: New testcase.
> > ---
> > gcc/cp/typeck.cc | 3 +++
> > gcc/fold-const.cc | 4 +++-
> > gcc/testsuite/g++.dg/opt/pr104475.C | 12 ++++++++++++
> > gcc/tree-core.h | 3 +++
> > gcc/tree.h | 4 ++++
> > 5 files changed, 25 insertions(+), 1 deletion(-)
> > create mode 100644 gcc/testsuite/g++.dg/opt/pr104475.C
> >
> > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> > index 7dfe5acc67e..3563750803e 100644
> > --- a/gcc/cp/typeck.cc
> > +++ b/gcc/cp/typeck.cc
> > @@ -7232,6 +7232,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue,
> > tsubst_flags_t complain)
> > gcc_assert (same_type_ignoring_top_level_qualifiers_p
> > (TREE_TYPE (object), decl_type_context (field)));
> > val = build_address (arg);
> > + if (TREE_CODE (val) == ADDR_EXPR
> > + && TREE_CODE (TREE_OPERAND (val, 0)) == COMPONENT_REF)
> > + ADDR_NONZERO (val) = 1;
> > }
> >
> > if (TYPE_PTR_P (argtype)
> > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> > index e80be8049e1..cdfe3f50ae3 100644
> > --- a/gcc/fold-const.cc
> > +++ b/gcc/fold-const.cc
> > @@ -15308,8 +15308,10 @@ tree_single_nonzero_warnv_p (tree t, bool
> > *strict_overflow_p)
> >
> > case ADDR_EXPR:
> > {
> > - tree base = TREE_OPERAND (t, 0);
> > + if (ADDR_NONZERO (t))
> > + return true;
> > + tree base = TREE_OPERAND (t, 0);
> > if (!DECL_P (base))
> > base = get_base_address (base);
> > diff --git a/gcc/testsuite/g++.dg/opt/pr104475.C
> > b/gcc/testsuite/g++.dg/opt/pr104475.C
> > new file mode 100644
> > index 00000000000..013c70302c6
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/opt/pr104475.C
> > @@ -0,0 +1,12 @@
> > +// { dg-do compile }
> > +// { dg-require-effective-target c++11 }
> > +// { dg-options "-O -Waddress -fdump-tree-original" }
> > +
> > +struct X { int i; };
> > +
> > +bool foo (struct X *p)
> > +{
> > + return &p->i != nullptr; /* { dg-warning "never be NULL" } */
> > +}
> > +
> > +/* { dg-final { scan-tree-dump "return <retval> = 1;" "original" } } */
> > diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> > index e146b133dbd..303e25b5df6 100644
> > --- a/gcc/tree-core.h
> > +++ b/gcc/tree-core.h
> > @@ -1376,6 +1376,9 @@ struct GTY(()) tree_base {
> > TREE_THIS_NOTRAP in
> > INDIRECT_REF, MEM_REF, TARGET_MEM_REF, ARRAY_REF,
> > ARRAY_RANGE_REF
> > + ADDR_NONZERO in
> > + ADDR_EXPR
> > +
> > SSA_NAME_IN_FREE_LIST in
> > SSA_NAME
> > diff --git a/gcc/tree.h b/gcc/tree.h
> > index 23223ca0c87..1c810c0b21b 100644
> > --- a/gcc/tree.h
> > +++ b/gcc/tree.h
> > @@ -876,6 +876,10 @@ extern void omp_clause_range_check_failed (const_tree,
> > const char *, int,
> > (TREE_CHECK5 (NODE, INDIRECT_REF, MEM_REF, TARGET_MEM_REF, ARRAY_REF,
> > \
> > ARRAY_RANGE_REF)->base.nothrow_flag)
> > +/* Nozero means this ADDR_EXPR is not equal to NULL. */
> > +#define ADDR_NONZERO(NODE) \
> > + (TREE_CHECK (NODE, ADDR_EXPR)->base.nothrow_flag)
> > +
> > /* In a VAR_DECL, PARM_DECL or FIELD_DECL, or any kind of ..._REF node,
> > nonzero means it may not be the lhs of an assignment.
> > Nonzero in a FUNCTION_DECL means this function should be treated
>
>
>
--
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
HRB 36809 (AG Nuernberg)
More information about the Gcc-patches
mailing list