summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-common.c43
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c/ChangeLog5
-rw-r--r--gcc/c/c-parser.c17
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/parser.c25
-rw-r--r--gcc/doc/invoke.texi12
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/c-c++-common/memset-array.c36
12 files changed, 139 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1e28a4b521f..2ddc3df12bd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2016-04-27 Bernd Schmidt <bschmidt@redhat.com>
+
+ * doc/invoke.texi (Warning Options): Add -Wmemset-elt-size.
+ (-Wmemset-elt-size): New item.
+
2016-04-27 Eric Botcazou <ebotcazou@adacore.com>
PR ada/70759
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index af601678982..1d87d9dd815 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-04-27 Bernd Schmidt <bschmidt@redhat.com>
+
+ * c.opt (Wmemset-elt-size): New option.
+ * c-common.c (warn_for_memset): New function.
+ * c-common.h (warn_for_memset): Declare.
+
2016-04-25 Jason Merrill <jason@redhat.com>
* c-common.c (handle_unused_attribute): Accept CONST_DECL.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 1edc0bc65bb..1f0d76aa15b 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -11767,6 +11767,49 @@ warn_for_div_by_zero (location_t loc, tree divisor)
warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
}
+/* Warn for patterns where memset appears to be used incorrectly. The
+ warning location should be LOC. ARG0, and ARG2 are the first and
+ last arguments to the call, while LITERAL_ZERO_MASK has a 1 bit for
+ each argument that was a literal zero. */
+
+void
+warn_for_memset (location_t loc, tree arg0, tree arg2,
+ int literal_zero_mask)
+{
+ if (warn_memset_transposed_args
+ && integer_zerop (arg2)
+ && (literal_zero_mask & (1 << 2)) != 0
+ && (literal_zero_mask & (1 << 1)) == 0)
+ warning_at (loc, OPT_Wmemset_transposed_args,
+ "%<memset%> used with constant zero length "
+ "parameter; this could be due to transposed "
+ "parameters");
+
+ if (warn_memset_elt_size && TREE_CODE (arg2) == INTEGER_CST)
+ {
+ STRIP_NOPS (arg0);
+ if (TREE_CODE (arg0) == ADDR_EXPR)
+ arg0 = TREE_OPERAND (arg0, 0);
+ tree type = TREE_TYPE (arg0);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree elt_type = TREE_TYPE (type);
+ tree domain = TYPE_DOMAIN (type);
+ if (!integer_onep (TYPE_SIZE_UNIT (elt_type))
+ && TYPE_MAXVAL (domain)
+ && TYPE_MINVAL (domain)
+ && integer_zerop (TYPE_MINVAL (domain))
+ && integer_onep (fold_build2 (MINUS_EXPR, domain,
+ arg2,
+ TYPE_MAXVAL (domain))))
+ warning_at (loc, OPT_Wmemset_elt_size,
+ "%<memset%> used with length equal to "
+ "number of elements without multiplication "
+ "by element size");
+ }
+ }
+}
+
/* Subroutine of build_binary_op. Give warnings for comparisons
between signed and unsigned quantities that may fail. Do the
checking based on the original operand trees ORIG_OP0 and ORIG_OP1,
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 4c43a354fef..b631e7d1af5 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -903,6 +903,7 @@ extern void c_parse_file (void);
extern void c_parse_final_cleanups (void);
extern void warn_for_omitted_condop (location_t, tree);
+extern void warn_for_memset (location_t, tree, tree, int);
/* These macros provide convenient access to the various _STMT nodes. */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 4f86876c533..05bfa7cbc6f 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -565,6 +565,10 @@ Wmemset-transposed-args
C ObjC C++ ObjC++ Var(warn_memset_transposed_args) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
Warn about suspicious calls to memset where the third argument is constant literal zero and the second is not.
+Wmemset-elt-size
+C ObjC C++ ObjC++ Var(warn_memset_elt_size) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious calls to memset where the third argument contains the number of elements not multiplied by the element size.
+
Wmisleading-indentation
C C++ Common Var(warn_misleading_indentation) Warning LangEnabledBy(C C++,Wall)
Warn when the indentation of the code does not reflect the block structure.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index b59d69092c9..a641721bece 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2016-04-27 Bernd Schmidt <bschmidt@redhat.com>
+
+ * c-parser.c (c_parser_postfix_expression_after_primary): Call
+ warn_for_memset instead of warning directly here.
+
2016-04-26 Marek Polacek <polacek@redhat.com>
PR c/67784
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 74423a6b233..36c44ab5b56 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -8291,18 +8291,15 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.value, exprlist,
sizeof_arg,
sizeof_ptr_memacc_comptypes);
- if (warn_memset_transposed_args
- && TREE_CODE (expr.value) == FUNCTION_DECL
+ if (TREE_CODE (expr.value) == FUNCTION_DECL
&& DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
- && vec_safe_length (exprlist) == 3
- && integer_zerop ((*exprlist)[2])
- && (literal_zero_mask & (1 << 2)) != 0
- && (!integer_zerop ((*exprlist)[1])
- || (literal_zero_mask & (1 << 1)) == 0))
- warning_at (expr_loc, OPT_Wmemset_transposed_args,
- "%<memset%> used with constant zero length parameter; "
- "this could be due to transposed parameters");
+ && vec_safe_length (exprlist) == 3)
+ {
+ tree arg0 = (*exprlist)[0];
+ tree arg2 = (*exprlist)[2];
+ warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+ }
start = expr.get_start ();
finish = parser->tokens_buf[0].get_finish ();
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b2185df76ae..6fc42bc030d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2016-04-27 Bernd Schmidt <bschmidt@redhat.com>
+
+ * parser.c (cp_parser_postfix_expression): Call
+ warn_for_memset instead of warning directly here.
+
2016-04-26 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/70241
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2dcb766a995..98a0cd42fea 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6829,20 +6829,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
}
}
- if (warn_memset_transposed_args)
+ if (TREE_CODE (postfix_expression) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (postfix_expression) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (postfix_expression) == BUILT_IN_MEMSET
+ && vec_safe_length (args) == 3)
{
- if (TREE_CODE (postfix_expression) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (postfix_expression) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (postfix_expression) == BUILT_IN_MEMSET
- && vec_safe_length (args) == 3
- && TREE_CODE ((*args)[2]) == INTEGER_CST
- && integer_zerop ((*args)[2])
- && !(TREE_CODE ((*args)[1]) == INTEGER_CST
- && integer_zerop ((*args)[1])))
- warning (OPT_Wmemset_transposed_args,
- "%<memset%> used with constant zero length "
- "parameter; this could be due to transposed "
- "parameters");
+ tree arg0 = (*args)[0];
+ tree arg1 = (*args)[1];
+ tree arg2 = (*args)[2];
+ int literal_mask = ((!!integer_zerop (arg1) << 1)
+ | (!!integer_zerop (arg2) << 2));
+ if (TREE_CODE (arg2) == CONST_DECL)
+ arg2 = DECL_INITIAL (arg2);
+ warn_for_memset (input_location, arg0, arg2, literal_mask);
}
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 2617cb458ba..67760b5b455 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -273,7 +273,7 @@ Objective-C and Objective-C++ Dialects}.
-Wno-int-to-pointer-cast -Winvalid-memory-model -Wno-invalid-offsetof @gol
-Winvalid-pch -Wlarger-than=@var{len} @gol
-Wlogical-op -Wlogical-not-parentheses -Wlong-long @gol
--Wmain -Wmaybe-uninitialized -Wmemset-transposed-args @gol
+-Wmain -Wmaybe-uninitialized -Wmemset-elt-size -Wmemset-transposed-args @gol
-Wmisleading-indentation -Wmissing-braces @gol
-Wmissing-field-initializers -Wmissing-include-dirs @gol
-Wno-multichar -Wnonnull -Wnonnull-compare @gol
@@ -3548,6 +3548,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Wlogical-not-parentheses
-Wmain @r{(only for C/ObjC and unless} @option{-ffreestanding}@r{)} @gol
-Wmaybe-uninitialized @gol
+-Wmemset-elt-size @gol
-Wmemset-transposed-args @gol
-Wmisleading-indentation @r{(only for C/C++)} @gol
-Wmissing-braces @r{(only for C/ObjC)} @gol
@@ -5257,6 +5258,15 @@ Warn when the @code{sizeof} operator is applied to a parameter that is
declared as an array in a function definition. This warning is enabled by
default for C and C++ programs.
+@item -Wmemset-elt-size
+@opindex Wmemset-elt-size
+@opindex Wno-memset-elt-size
+Warn for suspicious calls to the @code{memset} built-in function, if the
+first argument references an array, and the third argument is a number
+equal to the number of elements, but not equal to the size of the array
+in memory. This indicates that the user has omitted a multiplication by
+the element size. This warning is enabled by @option{-Wall}.
+
@item -Wmemset-transposed-args
@opindex Wmemset-transposed-args
@opindex Wno-memset-transposed-args
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ecd3fa9519f..77f8b0dd24a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-04-27 Bernd Schmidt <bschmidt@redhat.com>
+
+ * c-c++-common/memset-array.c: New test.
+
2016-04-26 Martin Sebor <msebor@redhat.com>
PR c++/66639
diff --git a/gcc/testsuite/c-c++-common/memset-array.c b/gcc/testsuite/c-c++-common/memset-array.c
new file mode 100644
index 00000000000..0346a210bb0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memset-array.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-Wmemset-elt-size" } */
+enum a {
+ a_1,
+ a_2,
+ a_n
+};
+int t1[20];
+int t2[a_n];
+
+struct s
+{
+ int t[20];
+};
+
+void foo (struct s *s)
+{
+ __builtin_memset (t1, 0, 20); /* { dg-warning "element size" } */
+ __builtin_memset (t2, 0, a_n); /* { dg-warning "element size" } */
+ __builtin_memset (s->t, 0, 20); /* { dg-warning "element size" } */
+}
+
+char u1[20];
+char u2[a_n];
+
+struct s2
+{
+ char u[20];
+};
+
+void bar (struct s2 *s)
+{
+ __builtin_memset (u1, 0, 20);
+ __builtin_memset (u2, 0, a_n);
+ __builtin_memset (s->u, 0, 20);
+}