+2018-06-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/85710 - ICE with -Wmemset-elt-size.
+ * c-warn.c (warn_for_memset): Don't crash on incomplete element type.
+
2018-06-01 Jason Merrill <jason@redhat.com>
* c-cppbuiltin.c (c_cpp_builtins): Bump __cpp_deduction_guides to
{
tree elt_type = TREE_TYPE (type);
tree domain = TYPE_DOMAIN (type);
- if (!integer_onep (TYPE_SIZE_UNIT (elt_type))
+ if (COMPLETE_TYPE_P (elt_type)
+ && !integer_onep (TYPE_SIZE_UNIT (elt_type))
&& domain != NULL_TREE
&& TYPE_MAX_VALUE (domain)
&& TYPE_MIN_VALUE (domain)
+2018-06-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/85710 - ICE with -Wmemset-elt-size.
+ * semantics.c (finish_call_expr): Call warn_for_memset here.
+ * parser.c (cp_parser_postfix_expression): Not here.
+ (literal_integer_zerop): No longer static.
+ * pt.c (build_non_dependent_expr): Don't wrap CONST_DECL.
+
2018-06-05 Marek Polacek <polacek@redhat.com>
PR c++/85976
extern void inject_this_parameter (tree, cp_cv_quals);
extern location_t defarg_location (tree);
extern void maybe_show_extern_c_location (void);
+extern bool literal_integer_zerop (const_tree);
/* in pt.c */
extern bool check_template_shadow (tree);
/* Return true if EXPR is the integer constant zero or a complex constant
of zero, without any folding, but ignoring location wrappers. */
-static bool
+bool
literal_integer_zerop (const_tree expr)
{
- STRIP_ANY_LOCATION_WRAPPER (expr);
- return integer_zerop (expr);
+ return (location_wrapper_p (expr)
+ && integer_zerop (TREE_OPERAND (expr, 0)));
}
/* Parse a postfix-expression.
}
}
- 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 arg0 = (*args)[0];
- tree arg1 = (*args)[1];
- tree arg2 = (*args)[2];
- int literal_mask = ((literal_integer_zerop (arg1) << 1)
- | (literal_integer_zerop (arg2) << 2));
- warn_for_memset (input_location, arg0, arg2, literal_mask);
- }
-
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
{
tree instance = TREE_OPERAND (postfix_expression, 0);
if (is_overloaded_fn (inner_expr)
|| TREE_CODE (inner_expr) == OFFSET_REF)
return orig_expr;
- /* There is no need to return a proxy for a variable. */
- if (VAR_P (expr))
+ /* There is no need to return a proxy for a variable or enumerator. */
+ if (VAR_P (expr) || TREE_CODE (expr) == CONST_DECL)
return orig_expr;
/* Preserve string constants; conversions from string constants to
"char *" are allowed, even though normally a "const char *"
{
tree result;
tree orig_fn;
- vec<tree, va_gc> *orig_args = NULL;
+ vec<tree, va_gc> *orig_args = *args;
if (fn == error_mark_node)
return error_mark_node;
sizeof_arg, same_type_ignoring_top_level_qualifiers_p);
}
+ if ((complain & tf_warning)
+ && TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (fn) == BUILT_IN_MEMSET
+ && vec_safe_length (*args) == 3
+ && !any_type_dependent_arguments_p (*args))
+ {
+ tree arg0 = (*orig_args)[0];
+ tree arg1 = (*orig_args)[1];
+ tree arg2 = (*orig_args)[2];
+ int literal_mask = ((literal_integer_zerop (arg1) << 1)
+ | (literal_integer_zerop (arg2) << 2));
+ arg2 = instantiate_non_dependent_expr (arg2);
+ warn_for_memset (input_location, arg0, arg2, literal_mask);
+ }
+
/* A call to a namespace-scope function. */
result = build_new_function_call (fn, args, complain);
}
--- /dev/null
+// PR c++/85710
+// { dg-additional-options -Wmemset-elt-size }
+
+#include <cstring>
+
+template <typename T> struct A { int a; };
+
+void foo(A<int> (*ap)[2])
+{
+ std::memset (*ap, 0, 2); // no warning because A<int> is incomplete
+}
+
+template <typename T>
+class E
+{
+public:
+ void Clear();
+private:
+ A<T> mA[2];
+};
+
+template<typename T>
+void E<T>::Clear()
+{
+ std::memset(mA, 0, 2); // { dg-warning -Wmemset-elt-size }
+}
+
+int main()
+{
+ E<int>().Clear();
+}