Re: [v2 of PATCH 13/14] c-format.c: handle location wrappers

2017-12-20 Thread Jason Merrill
On Wed, Dec 20, 2017 at 12:33 PM, David Malcolm  wrote:
> On Tue, 2017-12-19 at 14:55 -0500, Jason Merrill wrote:
>> On 12/17/2017 11:29 AM, David Malcolm wrote:
>> > On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
>> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
>> > > > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
>> > > > +
>> > > >   if (VAR_P (format_tree))
>> > > > {
>> > > >   /* Pull out a constant value if the front end
>> > > > didn't.  */
>> > >
>> > > It seems like we want fold_for_warn here instead of the special
>> > > variable
>> > > handling.  That probably makes sense for the other places you
>> > > change in
>> > > this patch, too.
>> >
>> > Here's an updated version of the patch which uses fold_for_warn,
>> > rather than STRIP_ANY_LOCATION_WRAPPER.
>> >
>> > In one place it was necessary to add a STRIP_NOPS, since the
>> > fold_for_warn can add a cast around a:
>> >ADDR_EXPR  (
>> >  STRING_CST)
>> > turning it into a:
>> >NOP_EXPR (
>> >  ADDR_EXPR  (
>> >STRING_CST))
>>
>> Hmm, that seems like a bug.  fold_for_warn shouldn't change the type of
>> the result.
>
> In a similar vein, is the result of decl_constant_value (decl) required
> to be the same type as that of the decl?
>
> What's happening for this testcase (g++.dg/warn/Wformat-1.C) is that we
> have a VAR_DECL with a DECL_INITIAL, but the types of the two don't
> quite match up.
>
> decl_constant_value returns an unshare_expr clone of the DECL_INITIAL,
> and this is what's returned from fold_for_warn.
>
> Am I right in thinking
>
> (a) that the bug here is that a DECL_INITIAL ought to have the same
> type as its decl, and so there's a missing cast where that gets
> set up, or

This seems right.

> (b) should decl_constant_value handle such cases, and introduce a cast
> if it uncovers them?

decl_constant_value should probably assert that the types match closely enough.

Jason


Re: [v2 of PATCH 13/14] c-format.c: handle location wrappers

2017-12-20 Thread David Malcolm
On Tue, 2017-12-19 at 14:55 -0500, Jason Merrill wrote:
> On 12/17/2017 11:29 AM, David Malcolm wrote:
> > On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
> > > On 11/10/2017 04:45 PM, David Malcolm wrote:
> > > > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> > > > +
> > > >   if (VAR_P (format_tree))
> > > > {
> > > >   /* Pull out a constant value if the front end
> > > > didn't.  */
> > > 
> > > It seems like we want fold_for_warn here instead of the special
> > > variable
> > > handling.  That probably makes sense for the other places you
> > > change in
> > > this patch, too.
> > 
> > Here's an updated version of the patch which uses fold_for_warn,
> > rather than STRIP_ANY_LOCATION_WRAPPER.
> > 
> > In one place it was necessary to add a STRIP_NOPS, since the
> > fold_for_warn can add a cast around a:
> >ADDR_EXPR  (
> >  STRING_CST)
> > turning it into a:
> >NOP_EXPR (
> >  ADDR_EXPR  (
> >STRING_CST))
> 
> Hmm, that seems like a bug.  fold_for_warn shouldn't change the type
> of 
> the result.

In a similar vein, is the result of decl_constant_value (decl) required
to be the same type as that of the decl?

What's happening for this testcase (g++.dg/warn/Wformat-1.C) is that we
have a VAR_DECL with a DECL_INITIAL, but the types of the two don't
quite match up.

decl_constant_value returns an unshare_expr clone of the DECL_INITIAL,
and this is what's returned from fold_for_warn.

Am I right in thinking

(a) that the bug here is that a DECL_INITIAL ought to have the same
type as its decl, and so there's a missing cast where that gets
set up, or

(b) should decl_constant_value handle such cases, and introduce a cast
if it uncovers them?

Thanks
Dave



> > +  format_tree = fold_for_warn (format_tree);
> > +
> > if (VAR_P (format_tree))
> >   {
> > /* Pull out a constant value if the front end didn't.  */
> 
> I was suggesting dropping the if (VAR_P... block, since pulling out
> the 
> constant value should now be covered by fold_for_warn.
> 
> > -format_tree = TREE_OPERAND (format_tree, 0);
> > +{
> > +  format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
> > +}
> 
> Why the added braces?

(I messed up; will be fixed in the next version)


Re: [v2 of PATCH 13/14] c-format.c: handle location wrappers

2017-12-19 Thread Jason Merrill

On 12/17/2017 11:29 AM, David Malcolm wrote:

On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:

On 11/10/2017 04:45 PM, David Malcolm wrote:

+  STRIP_ANY_LOCATION_WRAPPER (format_tree);
+
  if (VAR_P (format_tree))
{
  /* Pull out a constant value if the front end didn't.  */


It seems like we want fold_for_warn here instead of the special variable
handling.  That probably makes sense for the other places you change in
this patch, too.


Here's an updated version of the patch which uses fold_for_warn,
rather than STRIP_ANY_LOCATION_WRAPPER.

In one place it was necessary to add a STRIP_NOPS, since the
fold_for_warn can add a cast around a:
   ADDR_EXPR  (
 STRING_CST)
turning it into a:
   NOP_EXPR (
 ADDR_EXPR  (
   STRING_CST))


Hmm, that seems like a bug.  fold_for_warn shouldn't change the type of 
the result.



+  format_tree = fold_for_warn (format_tree);
+
if (VAR_P (format_tree))
  {
/* Pull out a constant value if the front end didn't.  */


I was suggesting dropping the if (VAR_P... block, since pulling out the 
constant value should now be covered by fold_for_warn.



-format_tree = TREE_OPERAND (format_tree, 0);
+{
+  format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
+}


Why the added braces?

Jason


[v2 of PATCH 13/14] c-format.c: handle location wrappers

2017-12-17 Thread David Malcolm
On Mon, 2017-12-11 at 18:45 -0500, Jason Merrill wrote:
> On 11/10/2017 04:45 PM, David Malcolm wrote:
> > gcc/c-family/ChangeLog:
> >* c-format.c (check_format_arg): Strip any location wrapper
> > around
> >format_tree.
> > ---
> >gcc/c-family/c-format.c | 9 -
> >1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
> > index 164d035..6b436ec 100644
> > --- a/gcc/c-family/c-format.c
> > +++ b/gcc/c-family/c-format.c
> > @@ -1536,6 +1536,8 @@ check_format_arg (void *ctx, tree
> > format_tree,
> >
> >  location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree,
> > input_location);
> >
> > +  STRIP_ANY_LOCATION_WRAPPER (format_tree);
> > +
> >  if (VAR_P (format_tree))
> >{
> >  /* Pull out a constant value if the front end didn't.  */
>
> It seems like we want fold_for_warn here instead of the special
> variable
> handling.  That probably makes sense for the other places you change
> in
> this patch, too.
>
> Jason

Here's an updated version of the patch which uses fold_for_warn,
rather than STRIP_ANY_LOCATION_WRAPPER.

In one place it was necessary to add a STRIP_NOPS, since the
fold_for_warn can add a cast around a:
  ADDR_EXPR  (
STRING_CST)
turning it into a:
  NOP_EXPR (
ADDR_EXPR  (
  STRING_CST))
which without a STRIP_NOPS leads to a bail-out here:
  1596if (TREE_CODE (format_tree) != ADDR_EXPR)
  1597  {
  1598res->number_non_literal++;
  1599return;
  1600  }
and thus -Wformat-security not recognizing string literals.

Successfully bootstrapped®rtested on x86_64-pc-linux-gnu, as
part of the kit.

Is this OK for trunk, assuming the rest of the kit is approved?

gcc/c-family/ChangeLog:
* c-format.c (check_format_arg): Strip any location wrapper around
format_tree.
---
 gcc/c-family/c-format.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 164d035..47aca55 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -1536,6 +1536,8 @@ check_format_arg (void *ctx, tree format_tree,
 
   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
 
+  format_tree = fold_for_warn (format_tree);
+
   if (VAR_P (format_tree))
 {
   /* Pull out a constant value if the front end didn't.  */
@@ -1591,13 +1593,14 @@ check_format_arg (void *ctx, tree format_tree,
}
   offset = int_cst_value (arg1);
 }
+  STRIP_NOPS (format_tree);
   if (TREE_CODE (format_tree) != ADDR_EXPR)
 {
   res->number_non_literal++;
   return;
 }
   res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
-  format_tree = TREE_OPERAND (format_tree, 0);
+  format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
   if (format_types[info->format_type].flags 
   & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
 {
@@ -1634,7 +1637,9 @@ check_format_arg (void *ctx, tree format_tree,
   if (TREE_CODE (format_tree) == ARRAY_REF
   && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
   && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
-format_tree = TREE_OPERAND (format_tree, 0);
+{
+  format_tree = fold_for_warn (TREE_OPERAND (format_tree, 0));
+}
   if (offset < 0)
 {
   res->number_non_literal++;
-- 
1.8.5.3