===================================================================
@@ -6652,6 +6652,8 @@ c_parser_binary_expression (c_parser *parser, stru
enum tree_code op;
/* The source location of this operation. */
location_t loc;
+ /* The sizeof argument if expr.original_code == SIZEOF_EXPR. */
+ tree sizeof_arg;
} stack[NUM_PRECS];
int sp;
/* Location of the binary operator. */
@@ -6668,6 +6670,31 @@ c_parser_binary_expression (c_parser *parser, stru
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) \
+ { \
+ tree type0 = stack[sp - 1].sizeof_arg; \
+ tree type1 = stack[sp].sizeof_arg; \
+ tree first_arg = type0; \
+ if (!TYPE_P (type0)) \
+ type0 = TREE_TYPE (type0); \
+ if (!TYPE_P (type1)) \
+ type1 = TREE_TYPE (type1); \
+ if (POINTER_TYPE_P (type0) \
+ && comptypes (TREE_TYPE (type0), type1) \
+ && !(TREE_CODE (first_arg) == PARM_DECL \
+ && C_ARRAY_PARAMETER (first_arg) \
+ && warn_sizeof_array_argument)) \
+ if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
+ "division 'sizeof (%qT) / sizeof (%qT)' 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"); \
+ } \
+ break; \
default: \
break; \
} \
@@ -6701,6 +6728,7 @@ c_parser_binary_expression (c_parser *parser, stru
stack[0].loc = c_parser_peek_token (parser)->location;
stack[0].expr = c_parser_cast_expression (parser, after);
stack[0].prec = PREC_NONE;
+ stack[0].sizeof_arg = c_last_sizeof_arg;
sp = 0;
while (true)
{
@@ -6824,6 +6852,7 @@ c_parser_binary_expression (c_parser *parser, stru
stack[sp].expr = c_parser_cast_expression (parser, NULL);
stack[sp].prec = oprec;
stack[sp].op = ocode;
+ stack[sp].sizeof_arg = c_last_sizeof_arg;
}
out:
while (sp > 0)
@@ -7715,7 +7744,8 @@ c_parser_postfix_expression (c_parser *parser)
expr = c_parser_expression (parser);
if (TREE_CODE (expr.value) == MODIFY_EXPR)
TREE_NO_WARNING (expr.value) = 1;
- if (expr.original_code != C_MAYBE_CONST_EXPR)
+ if (expr.original_code != C_MAYBE_CONST_EXPR
+ && expr.original_code != SIZEOF_EXPR)
expr.original_code = ERROR_MARK;
/* Don't change EXPR.ORIGINAL_TYPE. */
location_t loc_close_paren = c_parser_peek_token (parser)->location;
@@ -8674,7 +8704,6 @@ c_parser_expr_list (c_parser *parser, bool convert
vec<tree, va_gc> *orig_types;
struct c_expr expr;
location_t loc = c_parser_peek_token (parser)->location;
- location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION;
unsigned int idx = 0;
ret = make_tree_vector ();
@@ -8683,9 +8712,6 @@ c_parser_expr_list (c_parser *parser, bool convert
else
orig_types = make_tree_vector ();
- if (sizeof_arg != NULL
- && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
- cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
if (literal_zero_mask)
c_parser_check_literal_zero (parser, literal_zero_mask, 0);
expr = c_parser_expr_no_commas (parser, NULL);
@@ -8699,21 +8725,15 @@ c_parser_expr_list (c_parser *parser, bool convert
if (locations)
locations->safe_push (loc);
if (sizeof_arg != NULL
- && cur_sizeof_arg_loc != UNKNOWN_LOCATION
&& expr.original_code == SIZEOF_EXPR)
{
sizeof_arg[0] = c_last_sizeof_arg;
- sizeof_arg_loc[0] = cur_sizeof_arg_loc;
+ sizeof_arg_loc[0] = c_last_sizeof_loc;
}
while (c_parser_next_token_is (parser, CPP_COMMA))
{
c_parser_consume_token (parser);
loc = c_parser_peek_token (parser)->location;
- if (sizeof_arg != NULL
- && c_parser_next_token_is_keyword (parser, RID_SIZEOF))
- cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
- else
- cur_sizeof_arg_loc = UNKNOWN_LOCATION;
if (literal_zero_mask)
c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
expr = c_parser_expr_no_commas (parser, NULL);
@@ -8728,11 +8748,10 @@ c_parser_expr_list (c_parser *parser, bool convert
locations->safe_push (loc);
if (++idx < 3
&& sizeof_arg != NULL
- && cur_sizeof_arg_loc != UNKNOWN_LOCATION
&& expr.original_code == SIZEOF_EXPR)
{
sizeof_arg[idx] = c_last_sizeof_arg;
- sizeof_arg_loc[idx] = cur_sizeof_arg_loc;
+ sizeof_arg_loc[idx] = c_last_sizeof_loc;
}
}
if (orig_types)
===================================================================
@@ -606,6 +606,7 @@ extern int in_sizeof;
extern int in_typeof;
extern tree c_last_sizeof_arg;
+extern location_t c_last_sizeof_loc;
extern struct c_switch *c_switch_stack;
===================================================================
@@ -72,6 +72,7 @@ int in_typeof;
/* The argument of last parsed sizeof expression, only to be tested
if expr.original_code == SIZEOF_EXPR. */
tree c_last_sizeof_arg;
+location_t c_last_sizeof_loc;
/* Nonzero if we might need to print a "missing braces around
initializer" message within this initializer. */
@@ -2909,6 +2910,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr
&expr_const_operands);
ret.value = c_sizeof (loc, TREE_TYPE (folded_expr));
c_last_sizeof_arg = expr.value;
+ c_last_sizeof_loc = loc;
ret.original_code = SIZEOF_EXPR;
ret.original_type = NULL;
if (c_vla_type_p (TREE_TYPE (folded_expr)))
@@ -2938,6 +2940,7 @@ c_expr_sizeof_type (location_t loc, struct c_type_
type = groktypename (t, &type_expr, &type_expr_const);
ret.value = c_sizeof (loc, type);
c_last_sizeof_arg = type;
+ c_last_sizeof_loc = loc;
ret.original_code = SIZEOF_EXPR;
ret.original_type = NULL;
if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
===================================================================
@@ -698,6 +698,10 @@ Wsized-deallocation
C++ ObjC++ Var(warn_sized_deallocation) Warning EnabledBy(Wextra)
Warn about missing sized deallocation functions.
+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-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.
===================================================================
@@ -2223,6 +2223,22 @@ cp_fold (tree x)
else
x = fold (x);
+ if (TREE_CODE (x) == INTEGER_CST &&
+ TREE_CODE (org_x) == TRUNC_DIV_EXPR
+ && TREE_CODE (TREE_OPERAND (org_x, 0)) == SIZEOF_EXPR
+ && TREE_CODE (TREE_OPERAND (org_x, 1)) == SIZEOF_EXPR)
+ {
+ tree type0 = TREE_OPERAND (TREE_OPERAND (org_x, 0), 0);
+ tree type1 = TREE_OPERAND (TREE_OPERAND (org_x, 1), 0);
+ tree first_arg = type0;
+ if (!TYPE_P (type0))
+ type0 = TREE_TYPE (type0);
+ if (!TYPE_P (type1))
+ type1 = TREE_TYPE (type1);
+ if (POINTER_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1)
+ && !(TREE_CODE (first_arg) == PARM_DECL
+ && DECL_ARRAY_PARAMETER_P (first_arg)
+ && warn_sizeof_array_argument))
+ if (warning_at (loc, OPT_Wsizeof_pointer_div,
+ "division 'sizeof (%qT) / sizeof (%qT)' 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");
+ }
+
if (TREE_NO_WARNING (org_x)
&& warn_nonnull_compare
&& COMPARISON_CLASS_P (org_x))
===================================================================
@@ -304,7 +304,7 @@ Objective-C and Objective-C++ Dialects}.
-Wshift-overflow -Wshift-overflow=@var{n} @gol
-Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol
--Wno-scalar-storage-order @gol
+-Wno-scalar-storage-order -Wsizeof-pointer-div @gol
-Wsizeof-pointer-memaccess -Wsizeof-array-argument @gol
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
@@ -3777,6 +3777,7 @@ Options} and @ref{Objective-C and Objective-C++ Di
-Wreturn-type @gol
-Wsequence-point @gol
-Wsign-compare @r{(only in C++)} @gol
+-Wsizeof-pointer-div @gol
-Wsizeof-pointer-memaccess @gol
-Wstrict-aliasing @gol
-Wstrict-overflow=1 @gol
@@ -6022,6 +6023,15 @@ void operator delete[] (void *, std::size_t) noexc
or vice versa. Enabled by @option{-Wextra} along with
@option{-fsized-deallocation}.
+@item -Wsizeof-pointer-div
+@opindex Wsizeof-pointer-div
+@opindex Wno-sizeof-pointer-div
+Warn for suspicious divisions of two sizeof expressions that divide
+the pointer size by the element size, which is the usual way to compute
+the array size but won't work out correctly with pointers. This warning
+warns e.g.@: about @code{sizeof (ptr) / sizeof (ptr[0])} if @code{ptr} is
+not an array, but a pointer. This warning is enabled by @option{-Wall}.
+
@item -Wsizeof-pointer-memaccess
@opindex Wsizeof-pointer-memaccess
@opindex Wno-sizeof-pointer-memaccess
===================================================================
@@ -0,0 +1,41 @@
+/* Test -Wsizeof-pointer-div warnings. */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+int
+f1 (int *array)
+{
+ int i;
+ i = sizeof array / sizeof *array; /* { dg-warning "does not compute the number of array elements" } */
+ i += sizeof array / sizeof array[0]; /* { dg-warning "does not compute the number of array elements" } */
+ i += sizeof(array) / sizeof(*array); /* { dg-warning "does not compute the number of array elements" } */
+ i += sizeof(array) / sizeof(array[0]); /* { dg-warning "does not compute the number of array elements" } */
+ i += (sizeof(array)) / (sizeof(array[0])); /* { dg-warning "does not compute the number of array elements" } */
+ i += sizeof(array) / sizeof(int); /* { dg-warning "does not compute the number of array elements" } */
+ i += sizeof(array) / sizeof(char);
+ i += sizeof(*array) / sizeof(char);
+ i += sizeof(array[0]) / sizeof(char);
+ return i;
+}
+
+int
+f2 (void)
+{
+ int array[10];
+ int i;
+ i = sizeof array / sizeof *array;
+ i += sizeof array / sizeof array[0];
+ i += sizeof(array) / sizeof(*array);
+ 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);
+ i += sizeof(array[0]) / sizeof(char);
+ return i;
+}
+
+int f3 (int a[])
+{
+ return sizeof a / sizeof *a; /* { dg-warning "Wsizeof-array-argument" } */
+}
===================================================================
@@ -73,6 +73,15 @@ f1 (void *x, int z)
z += bcmp (x, pa2, sizeof (PTA)); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
z += bcmp (x, pa3, sizeof (PA)); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+ z += bcmp (x, (&a), (sizeof (&a))); /* { dg-warning "call is the same expression as the second source; did you mean to remove the addressof" } */
+ z += bcmp (x, (pa1), (sizeof (pa1))); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += bcmp (x, (pa2), (sizeof pa2)); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += bcmp (x, (pa3), (sizeof (pa3))); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += bcmp (x, (pa4), (sizeof pa4)); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += bcmp (x, (pa1), (sizeof (struct A *)));/* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+ z += bcmp (x, (pa2), (sizeof (PTA))); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+ z += bcmp (x, (pa3), (sizeof (PA))); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+
/* These are correct, no warning. */
bzero (&a, sizeof a);
bzero (&a, sizeof (a));
===================================================================
@@ -150,6 +150,15 @@ f1 (void *x, int z)
z += memcmp (x, pa2, sizeof (PTA)); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
z += memcmp (x, pa3, sizeof (PA)); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+ z += memcmp (x, (&a), (sizeof (&a))); /* { dg-warning "call is the same expression as the second source; did you mean to remove the addressof" } */
+ z += memcmp (x, (pa1), (sizeof (pa1))); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += memcmp (x, (pa2), (sizeof pa2)); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += memcmp (x, (pa3), (sizeof (pa3))); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += memcmp (x, (pa4), (sizeof pa4)); /* { dg-warning "call is the same expression as the second source; did you mean to dereference it" } */
+ z += memcmp (x, (pa1), (sizeof (struct A *)));/* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+ z += memcmp (x, (pa2), (sizeof (PTA))); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+ z += memcmp (x, (pa3), (sizeof (PA))); /* { dg-warning "call is the same pointer type \[^\n\r\]* as the second source; expected \[^\n\r\]* or an explicit length" } */
+
/* These are correct, no warning. */
memset (&a, 0, sizeof a);
memset (&a, 0, sizeof (a));
===================================================================
@@ -17,13 +17,13 @@ check (__m64 x, unsigned short *v, int j)
union
{
__m64 x;
- unsigned short i[8];
+ unsigned short i[4];
} u;
unsigned int i;
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128 x, float *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.f[i])
===================================================================
@@ -23,7 +23,7 @@ test (float *v)
u.x = _mm_set_ps (v[3], v[2], v[1], v[0]);
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (v[i] != u.f[i])
{
#ifdef DEBUG
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned char *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned long long *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned int *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned short *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ test (unsigned int *v)
u.x = _mm_set_epi32 (v[3], v[2], v[1], v[0]);
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (v[i] != u.i[i])
{
#ifdef DEBUG
===================================================================
@@ -23,7 +23,7 @@ test (unsigned long long *v)
u.x = _mm_set_epi64x (v[1], v[0]);
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (v[i] != u.i[i])
{
#ifdef DEBUG
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned char *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned long long *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128 x, float *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.f[i])
===================================================================
@@ -23,7 +23,7 @@ check (__m128i x, unsigned int *v, int j)
u.x = x;
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (i == j)
{
if (v[i] != u.i[i])
===================================================================
@@ -23,7 +23,7 @@ test (unsigned int *v)
u.x = _mm_set_epi32 (v[3], v[2], v[1], v[0]);
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (v[i] != u.i[i])
{
#ifdef DEBUG
===================================================================
@@ -23,7 +23,7 @@ test (unsigned long long *v)
u.x = _mm_set_epi64x (v[1], v[0]);
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (v[i] != u.i[i])
{
#ifdef DEBUG
===================================================================
@@ -23,7 +23,7 @@ test (float *v)
u.x = _mm_set_ps (v[3], v[2], v[1], v[0]);
- for (i = 0; i < sizeof (v) / sizeof (v[0]); i++)
+ for (i = 0; i < sizeof (u) / sizeof (v[0]); i++)
if (v[i] != u.f[i])
{
#ifdef DEBUG
===================================================================
@@ -11,7 +11,7 @@ foo (int *array)
#pragma omp task
{
int j;
- for (j = 0; j < sizeof array / sizeof array[0]; j++)
+ for (j = 0; j < 40; j++)
if (array[j] != 0x55555555)
#pragma omp atomic
err++;
===================================================================
@@ -11,7 +11,7 @@ foo (int *array)
#pragma omp task
{
int j;
- for (j = 0; j < sizeof array / sizeof array[0]; j++)
+ for (j = 0; j < 40; j++)
if (array[j] != 0x55555555)
#pragma omp atomic
err++;