Ping.

On Thu, Oct 08, 2020 at 11:04:40AM -0400, Marek Polacek via Gcc-patches wrote:
> Ping for the C parts.
> 
> On Mon, Sep 28, 2020 at 02:15:41PM -0400, Marek Polacek via Gcc-patches wrote:
> > On Tue, Sep 22, 2020 at 04:07:41PM -0400, Jason Merrill wrote:
> > > On 9/22/20 1:29 PM, Marek Polacek wrote:
> > > > Ping.
> > > 
> > > The C++ change is OK.
> > 
> > Ping for the C parts.
> > 
> > > > On Tue, Sep 15, 2020 at 04:33:05PM -0400, Marek Polacek via Gcc-patches 
> > > > wrote:
> > > > > On Tue, Sep 15, 2020 at 09:04:41AM +0200, Jakub Jelinek via 
> > > > > Gcc-patches wrote:
> > > > > > On Mon, Sep 14, 2020 at 09:30:44PM -0400, Marek Polacek via 
> > > > > > Gcc-patches wrote:
> > > > > > > --- a/gcc/c/c-tree.h
> > > > > > > +++ b/gcc/c/c-tree.h
> > > > > > > @@ -147,6 +147,11 @@ struct c_expr
> > > > > > >        etc), so we stash a copy here.  */
> > > > > > >     source_range src_range;
> > > > > > > +  /* True iff the sizeof expression was enclosed in parentheses.
> > > > > > > +     NB: This member is currently only initialized when 
> > > > > > > .original_code
> > > > > > > +     is a SIZEOF_EXPR.  ??? Add a default constructor to this 
> > > > > > > class.  */
> > > > > > > +  bool parenthesized_p;
> > > > > > > +
> > > > > > >     /* Access to the first and last locations within the source 
> > > > > > > spelling
> > > > > > >        of this expression.  */
> > > > > > >     location_t get_start () const { return src_range.m_start; }
> > > > > > 
> > > > > > I think a magic tree code would be better, c_expr is used in too 
> > > > > > many places
> > > > > > and returned by many functions, so it is copied over and over.
> > > > > > Even if you must add it, it would be better to change the struct 
> > > > > > layout,
> > > > > > because right now there are fields: tree, location_t, tree, 
> > > > > > 2xlocation_t,
> > > > > > which means 32-bit gap on 64-bit hosts before the second tree, so 
> > > > > > the new
> > > > > > field would fit in there.  But, if it is mostly uninitialized, it 
> > > > > > is kind of
> > > > > > unclean.
> > > > > 
> > > > > Ok, here's a version with PAREN_SIZEOF_EXPR.  It doesn't require 
> > > > > changes to
> > > > > c_expr, but adding a new tree code is always a pain...
> > > > > 
> > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> > > > > 
> > > > > -- >8 --
> > > > > This patch implements a new warning, -Wsizeof-array-div.  It warns 
> > > > > about
> > > > > code like
> > > > > 
> > > > >    int arr[10];
> > > > >    sizeof (arr) / sizeof (short);
> > > > > 
> > > > > where we have a division of two sizeof expressions, where the first
> > > > > argument is an array, and the second sizeof does not equal the size
> > > > > of the array element.  See e.g. 
> > > > > <https://www.viva64.com/en/examples/v706/>.
> > > > > 
> > > > > Clang makes it possible to suppress the warning by parenthesizing the
> > > > > second sizeof like this:
> > > > > 
> > > > >    sizeof (arr) / (sizeof (short));
> > > > > 
> > > > > so I followed suit.  In the C++ FE this was rather easy, because
> > > > > finish_parenthesized_expr already set TREE_NO_WARNING.  In the C FE
> > > > > I've added a new tree code, PAREN_SIZEOF_EXPR, to discern between the
> > > > > non-() and () versions.
> > > > > 
> > > > > This warning is enabled by -Wall.  An example of the output:
> > > > > 
> > > > > x.c:5:23: warning: expression does not compute the number of elements 
> > > > > in this array; element type is ‘int’, not ‘short int’ 
> > > > > [-Wsizeof-array-div]
> > > > >      5 |   return sizeof (arr) / sizeof (short);
> > > > >        |          ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
> > > > > x.c:5:25: note: add parentheses around ‘sizeof (short int)’ to 
> > > > > silence this warning
> > > > >      5 |   return sizeof (arr) / sizeof (short);
> > > > >        |                         ^~~~~~~~~~~~~~
> > > > >        |                         (             )
> > > > > x.c:4:7: note: array ‘arr’ declared here
> > > > >      4 |   int arr[10];
> > > > >        |       ^~~
> > > > > 
> > > > > gcc/c-family/ChangeLog:
> > > > > 
> > > > >       PR c++/91741
> > > > >       * c-common.c (verify_tree): Handle PAREN_SIZEOF_EXPR.
> > > > >       (c_common_init_ts): Likewise.
> > > > >       * c-common.def (PAREN_SIZEOF_EXPR): New tree code.
> > > > >       * c-common.h (maybe_warn_sizeof_array_div): Declare.
> > > > >       * c-warn.c (sizeof_pointer_memaccess_warning): Unwrap NOP_EXPRs.
> > > > >       (maybe_warn_sizeof_array_div): New function.
> > > > >       * c.opt (Wsizeof-array-div): New option.
> > > > > 
> > > > > gcc/c/ChangeLog:
> > > > > 
> > > > >       PR c++/91741
> > > > >       * c-parser.c (c_parser_binary_expression): Implement 
> > > > > -Wsizeof-array-div.
> > > > >       (c_parser_postfix_expression): Set PAREN_SIZEOF_EXPR.
> > > > >       (c_parser_expr_list): Handle PAREN_SIZEOF_EXPR like SIZEOF_EXPR.
> > > > >       * c-tree.h (char_type_p): Declare.
> > > > >       * c-typeck.c (char_type_p): No longer static.
> > > > > 
> > > > > gcc/cp/ChangeLog:
> > > > > 
> > > > >       PR c++/91741
> > > > >       * typeck.c (cp_build_binary_op): Implement -Wsizeof-array-div.
> > > > > 
> > > > > gcc/ChangeLog:
> > > > > 
> > > > >       PR c++/91741
> > > > >       * doc/invoke.texi: Document -Wsizeof-array-div.
> > > > > 
> > > > > gcc/testsuite/ChangeLog:
> > > > > 
> > > > >       PR c++/91741
> > > > >       * c-c++-common/Wsizeof-pointer-div.c: Add dg-warning.
> > > > >       * c-c++-common/Wsizeof-array-div1.c: New test.
> > > > >       * g++.dg/warn/Wsizeof-array-div1.C: New test.
> > > > >       * g++.dg/warn/Wsizeof-array-div2.C: New test.
> > > > > ---
> > > > >   gcc/c-family/c-common.c                       |  2 +
> > > > >   gcc/c-family/c-common.def                     |  3 +
> > > > >   gcc/c-family/c-common.h                       |  1 +
> > > > >   gcc/c-family/c-warn.c                         | 47 ++++++++++++++++
> > > > >   gcc/c-family/c.opt                            |  5 ++
> > > > >   gcc/c/c-parser.c                              | 48 ++++++++++------
> > > > >   gcc/c/c-tree.h                                |  1 +
> > > > >   gcc/c/c-typeck.c                              |  2 +-
> > > > >   gcc/cp/typeck.c                               | 10 +++-
> > > > >   gcc/doc/invoke.texi                           | 19 +++++++
> > > > >   .../c-c++-common/Wsizeof-array-div1.c         | 56 
> > > > > +++++++++++++++++++
> > > > >   .../c-c++-common/Wsizeof-pointer-div.c        |  2 +-
> > > > >   .../g++.dg/warn/Wsizeof-array-div1.C          | 37 ++++++++++++
> > > > >   .../g++.dg/warn/Wsizeof-array-div2.C          | 15 +++++
> > > > >   14 files changed, 226 insertions(+), 22 deletions(-)
> > > > >   create mode 100644 gcc/testsuite/c-c++-common/Wsizeof-array-div1.c
> > > > >   create mode 100644 gcc/testsuite/g++.dg/warn/Wsizeof-array-div1.C
> > > > >   create mode 100644 gcc/testsuite/g++.dg/warn/Wsizeof-array-div2.C
> > > > > 
> > > > > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> > > > > index 873bea9e2b2..b0a71d10e19 100644
> > > > > --- a/gcc/c-family/c-common.c
> > > > > +++ b/gcc/c-family/c-common.c
> > > > > @@ -1854,6 +1854,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, 
> > > > > struct tlist **pno_sp,
> > > > >       {
> > > > >       case CONSTRUCTOR:
> > > > >       case SIZEOF_EXPR:
> > > > > +    case PAREN_SIZEOF_EXPR:
> > > > >         return;
> > > > >       case COMPOUND_EXPR:
> > > > > @@ -8124,6 +8125,7 @@ void
> > > > >   c_common_init_ts (void)
> > > > >   {
> > > > >     MARK_TS_EXP (SIZEOF_EXPR);
> > > > > +  MARK_TS_EXP (PAREN_SIZEOF_EXPR);
> > > > >     MARK_TS_EXP (C_MAYBE_CONST_EXPR);
> > > > >     MARK_TS_EXP (EXCESS_PRECISION_EXPR);
> > > > >   }
> > > > > diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
> > > > > index 7ceb9a22bd4..06f112e5683 100644
> > > > > --- a/gcc/c-family/c-common.def
> > > > > +++ b/gcc/c-family/c-common.def
> > > > > @@ -55,6 +55,9 @@ DEFTREECODE (USERDEF_LITERAL, "userdef_literal", 
> > > > > tcc_exceptional, 3)
> > > > >      or for the purpose of -Wsizeof-pointer-memaccess warning.  */
> > > > >   DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1)
> > > > > +/* Like above, but enclosed in parentheses.  Used to suppress 
> > > > > warnings.  */
> > > > > +DEFTREECODE (PAREN_SIZEOF_EXPR, "paren_sizeof_expr", tcc_expression, 
> > > > > 1)
> > > > > +
> > > > >   /*
> > > > >   Local variables:
> > > > >   mode:c
> > > > > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> > > > > index 4fc64bc4aa6..443aaa2ca9c 100644
> > > > > --- a/gcc/c-family/c-common.h
> > > > > +++ b/gcc/c-family/c-common.h
> > > > > @@ -1321,6 +1321,7 @@ extern void c_do_switch_warnings (splay_tree, 
> > > > > location_t, tree, tree, bool);
> > > > >   extern void warn_for_omitted_condop (location_t, tree);
> > > > >   extern bool warn_for_restrict (unsigned, tree *, unsigned);
> > > > >   extern void warn_for_address_or_pointer_of_packed_member (tree, 
> > > > > tree);
> > > > > +extern void maybe_warn_sizeof_array_div (location_t, tree, tree, 
> > > > > tree, tree);
> > > > >   /* Places where an lvalue, or modifiable lvalue, may be required.
> > > > >      Used to select diagnostic messages in lvalue_error and
> > > > > diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
> > > > > index c32d8228b5c..6fdada5f9b7 100644
> > > > > --- a/gcc/c-family/c-warn.c
> > > > > +++ b/gcc/c-family/c-warn.c
> > > > > @@ -3099,3 +3099,50 @@ warn_for_address_or_pointer_of_packed_member 
> > > > > (tree type, tree rhs)
> > > > >     check_and_warn_address_or_pointer_of_packed_member (type, rhs);
> > > > >   }
> > > > > +
> > > > > +/* Warn about divisions of two sizeof operators when the first one 
> > > > > is applied
> > > > > +   to an array and the divisor does not equal the size of the array 
> > > > > element.
> > > > > +   For instance:
> > > > > +
> > > > > +     sizeof (ARR) / sizeof (OP)
> > > > > +
> > > > > +   ARR is the array argument of the first sizeof, ARR_TYPE is its 
> > > > > ARRAY_TYPE.
> > > > > +   OP1 is the whole second SIZEOF_EXPR, or its argument; TYPE1 is 
> > > > > the type
> > > > > +   of the second argument.  */
> > > > > +
> > > > > +void
> > > > > +maybe_warn_sizeof_array_div (location_t loc, tree arr, tree arr_type,
> > > > > +                          tree op1, tree type1)
> > > > > +{
> > > > > +  tree elt_type = TREE_TYPE (arr_type);
> > > > > +
> > > > > +  if (!warn_sizeof_array_div
> > > > > +      /* Don't warn on multidimensional arrays.  */
> > > > > +      || TREE_CODE (elt_type) == ARRAY_TYPE)
> > > > > +    return;
> > > > > +
> > > > > +  if (!tree_int_cst_equal (TYPE_SIZE (elt_type), TYPE_SIZE (type1)))
> > > > > +    {
> > > > > +      auto_diagnostic_group d;
> > > > > +      if (warning_at (loc, OPT_Wsizeof_array_div,
> > > > > +                   "expression does not compute the number of "
> > > > > +                   "elements in this array; element type is "
> > > > > +                   "%qT, not %qT", elt_type, type1))
> > > > > +     {
> > > > > +       if (EXPR_HAS_LOCATION (op1))
> > > > > +         {
> > > > > +           location_t op1_loc = EXPR_LOCATION (op1);
> > > > > +           gcc_rich_location richloc (op1_loc);
> > > > > +           richloc.add_fixit_insert_before (op1_loc, "(");
> > > > > +           richloc.add_fixit_insert_after (op1_loc, ")");
> > > > > +           inform (&richloc, "add parentheses around %qE to "
> > > > > +                   "silence this warning", op1);
> > > > > +         }
> > > > > +       else
> > > > > +         inform (loc, "add parentheses around the second %<sizeof%> "
> > > > > +                 "to silence this warning");
> > > > > +       if (DECL_P (arr))
> > > > > +         inform (DECL_SOURCE_LOCATION (arr), "array %qD declared 
> > > > > here", arr);
> > > > > +     }
> > > > > +    }
> > > > > +}
> > > > > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> > > > > index c1d8fd336e8..9ab44550140 100644
> > > > > --- a/gcc/c-family/c.opt
> > > > > +++ b/gcc/c-family/c.opt
> > > > > @@ -799,6 +799,11 @@ Wsizeof-pointer-div
> > > > >   C ObjC C++ ObjC++ Var(warn_sizeof_pointer_div) Warning 
> > > > > LangEnabledBy(C ObjC C++ ObjC++,Wall)
> > > > >   Warn about suspicious divisions of two sizeof expressions that 
> > > > > don't work correctly with pointers.
> > > > > +Wsizeof-array-div
> > > > > +C ObjC C++ ObjC++ Var(warn_sizeof_array_div) Warning LangEnabledBy(C 
> > > > > ObjC C++ ObjC++,Wall)
> > > > > +Warn about divisions of two sizeof operators when the first one is 
> > > > > applied
> > > > > +to an array and the divisor does not equal the size of the array 
> > > > > element.
> > > > > +
> > > > >   Wsizeof-pointer-memaccess
> > > > >   C ObjC C++ ObjC++ Var(warn_sizeof_pointer_memaccess) Warning 
> > > > > LangEnabledBy(C ObjC C++ ObjC++,Wall)
> > > > >   Warn about suspicious length parameters to certain string functions 
> > > > > if the argument uses sizeof.
> > > > > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> > > > > index a8bc301ffad..148832d388b 100644
> > > > > --- a/gcc/c/c-parser.c
> > > > > +++ b/gcc/c/c-parser.c
> > > > > @@ -7870,7 +7870,7 @@ c_parser_binary_expression (c_parser *parser, 
> > > > > struct c_expr *after,
> > > > >       enum tree_code op;
> > > > >       /* The source location of this operation.  */
> > > > >       location_t loc;
> > > > > -    /* The sizeof argument if expr.original_code == SIZEOF_EXPR.  */
> > > > > +    /* The sizeof argument if expr.original_code == 
> > > > > {PAREN_,}SIZEOF_EXPR.  */
> > > > >       tree sizeof_arg;
> > > > >     } stack[NUM_PRECS];
> > > > >     int sp;
> > > > > @@ -7888,9 +7888,11 @@ c_parser_binary_expression (c_parser *parser, 
> > > > > struct c_expr *after,
> > > > >       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value      
> > > > >       \
> > > > >                                         == truthvalue_true_node);     
> > > > >       \
> > > > >       break;                                                          
> > > > >       \
> > > > > -      case TRUNC_DIV_EXPR:                                           
> > > > >       \
> > > > > -     if (stack[sp - 1].expr.original_code == SIZEOF_EXPR             
> > > > >       \
> > > > > -         && stack[sp].expr.original_code == SIZEOF_EXPR)             
> > > > >       \
> > > > > +      case TRUNC_DIV_EXPR:                                           
> > > > >       \
> > > > > +     if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR            
> > > > >       \
> > > > > +          || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR)  
> > > > >       \
> > > > > +         && (stack[sp].expr.original_code == SIZEOF_EXPR             
> > > > >       \
> > > > > +             || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR))  
> > > > >       \
> > > > >         {                                                             
> > > > >       \
> > > > >           tree type0 = stack[sp - 1].sizeof_arg;                      
> > > > >       \
> > > > >           tree type1 = stack[sp].sizeof_arg;                          
> > > > >       \
> > > > > @@ -7904,18 +7906,23 @@ c_parser_binary_expression (c_parser *parser, 
> > > > > struct c_expr *after,
> > > > >               && !(TREE_CODE (first_arg) == PARM_DECL                 
> > > > >       \
> > > > >                    && C_ARRAY_PARAMETER (first_arg)                   
> > > > >       \
> > > > >                    && warn_sizeof_array_argument))                    
> > > > >       \
> > > > > -           {                                                         
> > > > > \
> > > > > -             auto_diagnostic_group d;                                
> > > > >         \
> > > > > -             if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, 
> > > > > \
> > > > > -                               "division %<sizeof (%T) / sizeof 
> > > > > (%T)%> " \
> > > > > -                               "does not compute the number of array 
> > > > > " \
> > > > > -                               "elements",                           
> > > > > \
> > > > > -                               type0, type1))                        
> > > > > \
> > > > > -               if (DECL_P (first_arg))                               
> > > > > \
> > > > > -                 inform (DECL_SOURCE_LOCATION (first_arg),           
> > > > > \
> > > > > -                           "first %<sizeof%> operand was declared 
> > > > > here"); \
> > > > > -           }                                                         
> > > > > \
> > > > > -       }                                                             
> > > > > \
> > > > > +           {                                                         
> > > > >       \
> > > > > +             auto_diagnostic_group d;                                
> > > > >       \
> > > > > +             if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, 
> > > > >       \
> > > > > +                               "division %<sizeof (%T) / sizeof 
> > > > > (%T)%> "   \
> > > > > +                               "does not compute the number of array 
> > > > > "     \
> > > > > +                               "elements",                           
> > > > >       \
> > > > > +                               type0, type1))                        
> > > > >       \
> > > > > +               if (DECL_P (first_arg))                               
> > > > >       \
> > > > > +                 inform (DECL_SOURCE_LOCATION (first_arg),           
> > > > >       \
> > > > > +                           "first %<sizeof%> operand was declared 
> > > > > here");  \
> > > > > +           }                                                         
> > > > >       \
> > > > > +         else if (TREE_CODE (type0) == ARRAY_TYPE                    
> > > > >       \
> > > > > +                  && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE 
> > > > > (type0)))  \
> > > > > +                  && stack[sp].expr.original_code != 
> > > > > PAREN_SIZEOF_EXPR)    \
> > > > > +           maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, 
> > > > > type0,   \
> > > > > +                                        stack[sp].sizeof_arg, 
> > > > > type1);      \
> > > > > +       }                                                             
> > > > >       \
> > > > >       break;                                                          
> > > > >       \
> > > > >         default:                                                      
> > > > >               \
> > > > >       break;                                                          
> > > > >       \
> > > > > @@ -9171,6 +9178,9 @@ c_parser_postfix_expression (c_parser *parser)
> > > > >         if (expr.original_code != C_MAYBE_CONST_EXPR
> > > > >             && expr.original_code != SIZEOF_EXPR)
> > > > >           expr.original_code = ERROR_MARK;
> > > > > +       /* Remember that we saw ( ) around the sizeof.  */
> > > > > +       if (expr.original_code == SIZEOF_EXPR)
> > > > > +         expr.original_code = PAREN_SIZEOF_EXPR;
> > > > >         /* Don't change EXPR.ORIGINAL_TYPE.  */
> > > > >         location_t loc_close_paren = c_parser_peek_token 
> > > > > (parser)->location;
> > > > >         set_c_expr_source_range (&expr, loc_open_paren, 
> > > > > loc_close_paren);
> > > > > @@ -10786,7 +10796,8 @@ c_parser_expr_list (c_parser *parser, bool 
> > > > > convert_p, bool fold_p,
> > > > >     if (locations)
> > > > >       locations->safe_push (expr.get_location ());
> > > > >     if (sizeof_arg != NULL
> > > > > -      && expr.original_code == SIZEOF_EXPR)
> > > > > +      && (expr.original_code == SIZEOF_EXPR
> > > > > +       || expr.original_code == PAREN_SIZEOF_EXPR))
> > > > >       {
> > > > >         sizeof_arg[0] = c_last_sizeof_arg;
> > > > >         sizeof_arg_loc[0] = c_last_sizeof_loc;
> > > > > @@ -10809,7 +10820,8 @@ c_parser_expr_list (c_parser *parser, bool 
> > > > > convert_p, bool fold_p,
> > > > >       locations->safe_push (expr.get_location ());
> > > > >         if (++idx < 3
> > > > >         && sizeof_arg != NULL
> > > > > -       && expr.original_code == SIZEOF_EXPR)
> > > > > +       && (expr.original_code == SIZEOF_EXPR
> > > > > +           || expr.original_code == PAREN_SIZEOF_EXPR))
> > > > >       {
> > > > >         sizeof_arg[idx] = c_last_sizeof_arg;
> > > > >         sizeof_arg_loc[idx] = c_last_sizeof_loc;
> > > > > diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
> > > > > index 10938cf0857..5b3751efb3a 100644
> > > > > --- a/gcc/c/c-tree.h
> > > > > +++ b/gcc/c/c-tree.h
> > > > > @@ -664,6 +664,7 @@ extern location_t c_last_sizeof_loc;
> > > > >   extern struct c_switch *c_switch_stack;
> > > > > +extern bool char_type_p (tree);
> > > > >   extern tree c_objc_common_truthvalue_conversion (location_t, tree);
> > > > >   extern tree require_complete_type (location_t, tree);
> > > > >   extern bool same_translation_unit_p (const_tree, const_tree);
> > > > > diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
> > > > > index bb27099bfe1..8caf3dbf6db 100644
> > > > > --- a/gcc/c/c-typeck.c
> > > > > +++ b/gcc/c/c-typeck.c
> > > > > @@ -3719,7 +3719,7 @@ parser_build_unary_op (location_t loc, enum 
> > > > > tree_code code, struct c_expr arg)
> > > > >   /* Returns true if TYPE is a character type, *not* including 
> > > > > wchar_t.  */
> > > > > -static bool
> > > > > +bool
> > > > >   char_type_p (tree type)
> > > > >   {
> > > > >     return (type == char_type_node
> > > > > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> > > > > index 9166156a5d5..7705f15c25f 100644
> > > > > --- a/gcc/cp/typeck.c
> > > > > +++ b/gcc/cp/typeck.c
> > > > > @@ -4706,14 +4706,13 @@ cp_build_binary_op (const op_location_t 
> > > > > &location,
> > > > >       {
> > > > >         tree type0 = TREE_OPERAND (op0, 0);
> > > > >         tree type1 = TREE_OPERAND (op1, 0);
> > > > > -       tree first_arg = type0;
> > > > > +       tree first_arg = tree_strip_any_location_wrapper (type0);
> > > > >         if (!TYPE_P (type0))
> > > > >           type0 = TREE_TYPE (type0);
> > > > >         if (!TYPE_P (type1))
> > > > >           type1 = TREE_TYPE (type1);
> > > > >         if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE 
> > > > > (type0), type1))
> > > > >           {
> > > > > -           STRIP_ANY_LOCATION_WRAPPER (first_arg);
> > > > >             if (!(TREE_CODE (first_arg) == PARM_DECL
> > > > >                   && DECL_ARRAY_PARAMETER_P (first_arg)
> > > > >                   && warn_sizeof_array_argument)
> > > > > @@ -4729,6 +4728,13 @@ cp_build_binary_op (const op_location_t 
> > > > > &location,
> > > > >                             "first %<sizeof%> operand was declared 
> > > > > here");
> > > > >               }
> > > > >           }
> > > > > +       else if (TREE_CODE (type0) == ARRAY_TYPE
> > > > > +                && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE 
> > > > > (type0)))
> > > > > +                /* Set by finish_parenthesized_expr.  */
> > > > > +                && !TREE_NO_WARNING (op1)
> > > > > +                && (complain & tf_warning))
> > > > > +         maybe_warn_sizeof_array_div (location, first_arg, type0,
> > > > > +                                      op1, non_reference (type1));
> > > > >       }
> > > > >         if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
> > > > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > > > > index 6d9ff2c3362..97fef872a54 100644
> > > > > --- a/gcc/doc/invoke.texi
> > > > > +++ b/gcc/doc/invoke.texi
> > > > > @@ -362,6 +362,7 @@ Objective-C and Objective-C++ Dialects}.
> > > > >   -Wno-shift-overflow  -Wshift-overflow=@var{n} @gol
> > > > >   -Wsign-compare  -Wsign-conversion @gol
> > > > >   -Wno-sizeof-array-argument @gol
> > > > > +-Wsizeof-array-div @gol
> > > > >   -Wsizeof-pointer-div  -Wsizeof-pointer-memaccess @gol
> > > > >   -Wstack-protector  -Wstack-usage=@var{byte-size}  -Wstrict-aliasing 
> > > > > @gol
> > > > >   -Wstrict-aliasing=n  -Wstrict-overflow  -Wstrict-overflow=@var{n} 
> > > > > @gol
> > > > > @@ -5255,6 +5256,7 @@ Options} and @ref{Objective-C and Objective-C++ 
> > > > > Dialect Options}.
> > > > >   -Wreturn-type  @gol
> > > > >   -Wsequence-point  @gol
> > > > >   -Wsign-compare @r{(only in C++)}  @gol
> > > > > +-Wsizeof-array-div @gol
> > > > >   -Wsizeof-pointer-div @gol
> > > > >   -Wsizeof-pointer-memaccess @gol
> > > > >   -Wstrict-aliasing  @gol
> > > > > @@ -7947,6 +7949,23 @@ real to lower precision real values.  This 
> > > > > option is also enabled by
> > > > >   @opindex Wscalar-storage-order
> > > > >   Do not warn on suspicious constructs involving reverse scalar 
> > > > > storage order.
> > > > > +@item -Wsizeof-array-div
> > > > > +@opindex Wsizeof-array-div
> > > > > +@opindex Wno-sizeof-array-div
> > > > > +Warn about divisions of two sizeof operators when the first one is 
> > > > > applied
> > > > > +to an array and the divisor does not equal the size of the array 
> > > > > element.
> > > > > +In such a case, the computation will not yield the number of 
> > > > > elements in the
> > > > > +array, which is likely what the user intended.  This warning warns 
> > > > > e.g. about
> > > > > +@smallexample
> > > > > +int fn ()
> > > > > +@{
> > > > > +  int arr[10];
> > > > > +  return sizeof (arr) / sizeof (short);
> > > > > +@}
> > > > > +@end smallexample
> > > > > +
> > > > > +This warning is enabled by @option{-Wall}.
> > > > > +
> > > > >   @item -Wsizeof-pointer-div
> > > > >   @opindex Wsizeof-pointer-div
> > > > >   @opindex Wno-sizeof-pointer-div
> > > > > diff --git a/gcc/testsuite/c-c++-common/Wsizeof-array-div1.c 
> > > > > b/gcc/testsuite/c-c++-common/Wsizeof-array-div1.c
> > > > > new file mode 100644
> > > > > index 00000000000..84d9a730cba
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/c-c++-common/Wsizeof-array-div1.c
> > > > > @@ -0,0 +1,56 @@
> > > > > +/* PR c++/91741 */
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-Wall" } */
> > > > > +
> > > > > +typedef int T;
> > > > > +
> > > > > +int
> > > > > +fn (int ap[])
> > > > > +{
> > > > > +  int arr[10];
> > > > > +  int *arr2[10];
> > > > > +  int *p = &arr[0];
> > > > > +  int r = 0;
> > > > > +
> > > > > +  r += sizeof (arr) / sizeof (*arr);
> > > > > +  r += sizeof (arr) / sizeof (p); /* { dg-warning "expression does 
> > > > > not compute" } */
> > > > > +  r += sizeof (arr) / sizeof p; /* { dg-warning "expression does not 
> > > > > compute" } */
> > > > > +  r += sizeof (arr) / (sizeof p);
> > > > > +  r += sizeof (arr) / (sizeof (p));
> > > > > +  r += sizeof (arr2) / sizeof p;
> > > > > +  r += sizeof (arr2) / sizeof (int); /* { dg-warning "expression 
> > > > > does not compute" } */
> > > > > +  r += sizeof (arr2) / sizeof (int *);
> > > > > +  r += sizeof (arr2) / sizeof (short *);
> > > > > +  r += sizeof (arr) / sizeof (int);
> > > > > +  r += sizeof (arr) / sizeof (unsigned int);
> > > > > +  r += sizeof (arr) / sizeof (T);
> > > > > +  r += sizeof (arr) / sizeof (short); /* { dg-warning "expression 
> > > > > does not compute" } */
> > > > > +  r += sizeof (arr) / (sizeof (short));
> > > > > +
> > > > > +  r += sizeof (ap) / sizeof (char); /* { dg-warning ".sizeof. on 
> > > > > array function parameter" } */
> > > > > +
> > > > > +  const char arr3[] = "foo";
> > > > > +  r += sizeof (arr3) / sizeof(char);
> > > > > +  r += sizeof (arr3) / sizeof(int);
> > > > > +  r += sizeof (arr3) / sizeof (*arr3);
> > > > > +
> > > > > +  int arr4[5][5];
> > > > > +  r += sizeof (arr4) / sizeof (arr4[0]);
> > > > > +  r += sizeof (arr4) / sizeof (*arr4);
> > > > > +  r += sizeof (arr4) / sizeof (**arr4);
> > > > > +  r += sizeof (arr4) / sizeof (int *);
> > > > > +  r += sizeof (arr4) / sizeof (int);
> > > > > +  r += sizeof (arr4) / sizeof (short int);
> > > > > +
> > > > > +  T arr5[10];
> > > > > +  r += sizeof (arr5) / sizeof (T);
> > > > > +  r += sizeof (arr5) / sizeof (int);
> > > > > +  r += sizeof (arr5) / sizeof (short); /* { dg-warning "expression 
> > > > > does not compute" } */
> > > > > +
> > > > > +  double arr6[10];
> > > > > +  r += sizeof (arr6) / sizeof (double);
> > > > > +  r += sizeof (arr6) / sizeof (float); /* { dg-warning "expression 
> > > > > does not compute" } */
> > > > > +  r += sizeof (arr6) / sizeof (*arr6);
> > > > > +
> > > > > +  return r;
> > > > > +}
> > > > > diff --git a/gcc/testsuite/c-c++-common/Wsizeof-pointer-div.c 
> > > > > b/gcc/testsuite/c-c++-common/Wsizeof-pointer-div.c
> > > > > index 83116183902..e9bad1fa420 100644
> > > > > --- a/gcc/testsuite/c-c++-common/Wsizeof-pointer-div.c
> > > > > +++ b/gcc/testsuite/c-c++-common/Wsizeof-pointer-div.c
> > > > > @@ -29,7 +29,7 @@ f2 (void)
> > > > >     i += sizeof(array) / sizeof(array[0]);
> > > > >     i += (sizeof(array)) / (sizeof(array[0]));
> > > > >     i += sizeof(array) / sizeof(int);
> > > > > -  i += sizeof(array) / sizeof(char);
> > > > > +  i += sizeof(array) / sizeof(char);         /* { dg-warning 
> > > > > "expression does not compute" } */
> > > > >     i += sizeof(*array) / sizeof(char);
> > > > >     i += sizeof(array[0]) / sizeof(char);
> > > > >     return i;
> > > > > diff --git a/gcc/testsuite/g++.dg/warn/Wsizeof-array-div1.C 
> > > > > b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div1.C
> > > > > new file mode 100644
> > > > > index 00000000000..da220cd57ba
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div1.C
> > > > > @@ -0,0 +1,37 @@
> > > > > +// PR c++/91741
> > > > > +// { dg-do compile { target c++11 } }
> > > > > +// { dg-options "-Wall" }
> > > > > +
> > > > > +int
> > > > > +fn1 ()
> > > > > +{
> > > > > +  int arr[10];
> > > > > +  return sizeof (arr) / sizeof (decltype(arr[0]));
> > > > > +}
> > > > > +
> > > > > +template<typename T, int N>
> > > > > +int fn2 (T (&arr)[N])
> > > > > +{
> > > > > +  return sizeof (arr) / sizeof (T);
> > > > > +}
> > > > > +
> > > > > +template<typename T, int N>
> > > > > +int fn3 (T (&arr)[N])
> > > > > +{
> > > > > +  return sizeof (arr) / sizeof (bool); // { dg-warning "expression 
> > > > > does not compute" }
> > > > > +}
> > > > > +
> > > > > +template<typename U, int N, typename T>
> > > > > +int fn4 (T (&arr)[N])
> > > > > +{
> > > > > +  return sizeof (arr) / sizeof (U); // { dg-warning "expression does 
> > > > > not compute" }
> > > > > +}
> > > > > +
> > > > > +void
> > > > > +fn ()
> > > > > +{
> > > > > +  int arr[10];
> > > > > +  fn2 (arr);
> > > > > +  fn3 (arr);
> > > > > +  fn4<short> (arr);
> > > > > +}
> > > > > diff --git a/gcc/testsuite/g++.dg/warn/Wsizeof-array-div2.C 
> > > > > b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div2.C
> > > > > new file mode 100644
> > > > > index 00000000000..7962c23522c
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/g++.dg/warn/Wsizeof-array-div2.C
> > > > > @@ -0,0 +1,15 @@
> > > > > +// PR c++/91741
> > > > > +// { dg-do compile }
> > > > > +// { dg-options "-Wall" }
> > > > > +// From <https://www.viva64.com/en/examples/v706/>.
> > > > > +
> > > > > +const int kBaudrates[] = { 50, 75, 110 };
> > > > > +
> > > > > +void
> > > > > +foo ()
> > > > > +{
> > > > > +  for(int i = sizeof(kBaudrates) / sizeof(char*); // { dg-warning 
> > > > > "expression does not compute" }
> > > > > +      --i >= 0;)
> > > > > +    {
> > > > > +    }
> > > > > +}
> > > > > 
> > > > > base-commit: d1a31689a736cdfb5e7cfa01f1168e338510e63b
> > > > > -- 
> > > > > 2.26.2
> > > > > 
> > > > 
> > > > Marek
> > > > 
> > > 
> > 
> > Marek
> > 
> 
> Marek
> 

Marek

Reply via email to