On 9/22/20 1:29 PM, Marek Polacek wrote:
Ping.

The C++ change is OK.

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


Reply via email to