* [PATCH] tree-optimization/104475 - bogus -Wstringop-overflow
@ 2022-12-07 11:25 Richard Biener
2023-01-17 17:37 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Richard Biener @ 2022-12-07 11:25 UTC (permalink / raw)
To: gcc-patches; +Cc: jason, Jakub Jelinek
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).
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
--
2.35.3
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tree-optimization/104475 - bogus -Wstringop-overflow
2022-12-07 11:25 [PATCH] tree-optimization/104475 - bogus -Wstringop-overflow Richard Biener
@ 2023-01-17 17:37 ` Jason Merrill
2023-01-18 8:06 ` Richard Biener
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2023-01-17 17:37 UTC (permalink / raw)
To: Richard Biener, gcc-patches; +Cc: Jakub Jelinek
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?
> 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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tree-optimization/104475 - bogus -Wstringop-overflow
2023-01-17 17:37 ` Jason Merrill
@ 2023-01-18 8:06 ` Richard Biener
2023-01-19 20:53 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Richard Biener @ 2023-01-18 8:06 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches, Jakub Jelinek
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)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tree-optimization/104475 - bogus -Wstringop-overflow
2023-01-18 8:06 ` Richard Biener
@ 2023-01-19 20:53 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2023-01-19 20:53 UTC (permalink / raw)
To: Richard Biener; +Cc: gcc-patches, Jakub Jelinek
On 1/18/23 03:06, Richard Biener wrote:
> 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 (accidentally) 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.
Makes sense.
> That said, we could re-define GENERIC/GIMPLE here to the extent
> that ADDR_EXPR of a COMPONENT_REF (or all handled components?)
Not ARRAY_REF, I think; in C++ &p[0] (i.e. p+0) seems well-formed for
null p, though any other index is undefined.
> 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.
Any thoughts about where the -fsanitize=null check goes?
> 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
>>
>>
>>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-01-19 20:53 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-07 11:25 [PATCH] tree-optimization/104475 - bogus -Wstringop-overflow Richard Biener
2023-01-17 17:37 ` Jason Merrill
2023-01-18 8:06 ` Richard Biener
2023-01-19 20:53 ` 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).