PR c++/85710 - ICE with -Wmemset-elt-size.
authorJason Merrill <jason@redhat.com>
Wed, 6 Jun 2018 15:14:12 +0000 (11:14 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 6 Jun 2018 15:14:12 +0000 (11:14 -0400)
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

gcc/c-family/ChangeLog
gcc/c-family/c-warn.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/warn/Wmemset-elt-size1.C [new file with mode: 0644]

index ad21a4b..f90adb7 100644 (file)
@@ -1,3 +1,8 @@
+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
index e7bcbb1..859d72b 100644 (file)
@@ -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)
index 4962eac..edfa797 100644 (file)
@@ -1,3 +1,11 @@
+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
index f2016f1..a6d0b43 100644 (file)
@@ -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);
index de090d4..03aea2f 100644 (file)
@@ -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);
index aad68a3..448cd69 100644 (file)
@@ -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 *"
index a342662..5579189 100644 (file)
@@ -2350,7 +2350,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 {
   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;
@@ -2524,6 +2524,22 @@ finish_call_expr (tree fn, vec<tree, va_gc> **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 (file)
index 0000000..e4d3232
--- /dev/null
@@ -0,0 +1,31 @@
+// 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();
+}