From: Jason Merrill Date: Wed, 6 Jun 2018 15:14:12 +0000 (-0400) Subject: PR c++/85710 - ICE with -Wmemset-elt-size. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4dbdb49b1b07a22e9f216b2ca988e17663b959d3;p=gcc.git PR c++/85710 - ICE with -Wmemset-elt-size. c-family/ * c-warn.c (warn_for_memset): Don't crash on incomplete element type. cp/ * 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. From-SVN: r261238 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ad21a4bd0e9..f90adb75c40 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2018-06-06 Jason Merrill + + 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 * c-cppbuiltin.c (c_cpp_builtins): Bump __cpp_deduction_guides to diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index e7bcbb18a3c..859d72b3f83 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -1897,7 +1897,8 @@ warn_for_memset (location_t loc, tree arg0, tree arg2, { 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) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4962eacf5fc..edfa797d20b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2018-06-06 Jason Merrill + + 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 PR c++/85976 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f2016f173bd..a6d0b431a9d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6548,6 +6548,7 @@ extern bool parsing_default_capturing_generic_lambda_in_template (void); 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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index de090d42d8d..03aea2f1150 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6614,11 +6614,11 @@ cp_parser_compound_literal_p (cp_parser *parser) /* 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. @@ -7159,19 +7159,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } } - 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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index aad68a32643..448cd69b722 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -25837,8 +25837,8 @@ build_non_dependent_expr (tree expr) 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 *" diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index a3426623385..55791894221 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2350,7 +2350,7 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, { tree result; tree orig_fn; - vec *orig_args = NULL; + vec *orig_args = *args; if (fn == error_mark_node) return error_mark_node; @@ -2524,6 +2524,22 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, 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); } diff --git a/gcc/testsuite/g++.dg/warn/Wmemset-elt-size1.C b/gcc/testsuite/g++.dg/warn/Wmemset-elt-size1.C new file mode 100644 index 00000000000..e4d3232063d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wmemset-elt-size1.C @@ -0,0 +1,31 @@ +// PR c++/85710 +// { dg-additional-options -Wmemset-elt-size } + +#include + +template struct A { int a; }; + +void foo(A (*ap)[2]) +{ + std::memset (*ap, 0, 2); // no warning because A is incomplete +} + +template +class E +{ +public: + void Clear(); +private: + A mA[2]; +}; + +template +void E::Clear() +{ + std::memset(mA, 0, 2); // { dg-warning -Wmemset-elt-size } +} + +int main() +{ + E().Clear(); +}