Class template argument deduction in new-expression
[gcc.git] / gcc / cp / init.c
index 524c583138f3e5cf7eb6ab05ad97e27c4c033642..191fe13e31039947d1d5d660eef0b9c0d8d9ba94 100644 (file)
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "varasm.h"
 #include "gimplify.h"
 #include "c-family/c-ubsan.h"
+#include "intl.h"
 
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
@@ -597,6 +598,34 @@ get_nsdmi (tree member, bool in_ctor)
   return init;
 }
 
+/* Diagnose the flexible array MEMBER if its INITializer is non-null
+   and return true if so.  Otherwise return false.  */
+
+bool
+maybe_reject_flexarray_init (tree member, tree init)
+{
+  tree type = TREE_TYPE (member);
+
+  if (!init
+      || TREE_CODE (type) != ARRAY_TYPE
+      || TYPE_DOMAIN (type))
+    return false;
+
+  /* Point at the flexible array member declaration if it's initialized
+     in-class, and at the ctor if it's initialized in a ctor member
+     initializer list.  */
+  location_t loc;
+  if (DECL_INITIAL (member) == init
+      || !current_function_decl
+      || DECL_DEFAULTED_FN (current_function_decl))
+    loc = DECL_SOURCE_LOCATION (member);
+  else
+    loc = DECL_SOURCE_LOCATION (current_function_decl);
+
+  error_at (loc, "initializer for flexible array member %q#D", member);
+  return true;
+}
+
 /* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
    arguments.  If TREE_LIST is void_type_node, an empty initializer
    list was given; if NULL_TREE no initializer was given.  */
@@ -722,10 +751,18 @@ perform_member_init (tree member, tree init)
        {
          if (init)
            {
-             if (TREE_CHAIN (init))
+             /* Check to make sure the member initializer is valid and
+                something like a CONSTRUCTOR in: T a[] = { 1, 2 } and
+                if it isn't, return early to avoid triggering another
+                error below.  */
+             if (maybe_reject_flexarray_init (member, init))
+               return;
+
+             if (TREE_CODE (init) != TREE_LIST || TREE_CHAIN (init))
                init = error_mark_node;
              else
                init = TREE_VALUE (init);
+
              if (BRACE_ENCLOSED_INITIALIZER_P (init))
                init = digest_init (type, init, tf_warning_or_error);
            }
@@ -800,16 +837,9 @@ perform_member_init (tree member, tree init)
           in that case.  */
        init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
                                                tf_warning_or_error);
-      if (TREE_CODE (type) == ARRAY_TYPE
-         && TYPE_DOMAIN (type) == NULL_TREE
-         && init != NULL_TREE)
-       {
-         error_at (DECL_SOURCE_LOCATION (current_function_decl),
-                   "member initializer for flexible array member");
-         inform (DECL_SOURCE_LOCATION (member), "%q#D initialized", member);
-       }
 
-      if (init)
+      /* Reject a member initializer for a flexible array member.  */
+      if (init && !maybe_reject_flexarray_init (member, init))
        finish_expr_stmt (cp_build_modify_expr (input_location, decl,
                                                INIT_EXPR, init,
                                                tf_warning_or_error));
@@ -1187,6 +1217,12 @@ emit_mem_initializers (tree mem_inits)
        /* C++14 DR1658 Means we do not have to construct vbases of
           abstract classes.  */
        construct_virtual_base (subobject, arguments);
+      else
+       /* When not constructing vbases of abstract classes, at least mark
+          the arguments expressions as read to avoid
+          -Wunused-but-set-parameter false positives.  */
+       for (tree arg = arguments; arg; arg = TREE_CHAIN (arg))
+         mark_exp_read (TREE_VALUE (arg));
 
       if (inherited_base)
        pop_deferring_access_checks ();
@@ -2013,14 +2049,16 @@ build_offset_ref (tree type, tree member, bool address_p,
               If the access is to form a pointer to member, the
               nested-name-specifier shall name the derived class
               (or any class derived from that class).  */
+         bool ok;
          if (address_p && DECL_P (t)
              && DECL_NONSTATIC_MEMBER_P (t))
-           perform_or_defer_access_check (TYPE_BINFO (type), t, t,
-                                          complain);
+           ok = perform_or_defer_access_check (TYPE_BINFO (type), t, t,
+                                               complain);
          else
-           perform_or_defer_access_check (basebinfo, t, t,
-                                          complain);
-
+           ok = perform_or_defer_access_check (basebinfo, t, t,
+                                               complain);
+         if (!ok)
+           return error_mark_node;
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
          member = t;
@@ -2029,11 +2067,14 @@ build_offset_ref (tree type, tree member, bool address_p,
        TREE_TYPE (member) = unknown_type_node;
     }
   else if (address_p && TREE_CODE (member) == FIELD_DECL)
-    /* We need additional test besides the one in
-       check_accessibility_of_qualified_id in case it is
-       a pointer to non-static member.  */
-    perform_or_defer_access_check (TYPE_BINFO (type), member, member,
-                                  complain);
+    {
+      /* We need additional test besides the one in
+        check_accessibility_of_qualified_id in case it is
+        a pointer to non-static member.  */
+      if (!perform_or_defer_access_check (TYPE_BINFO (type), member, member,
+                                         complain))
+       return error_mark_node;
+    }
 
   if (!address_p)
     {
@@ -2606,7 +2647,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
                        exact_size ?
                        "placement new constructing an object of type %qT "
                        "and size %qwu in a region of type %qT and size %qwi"
-                       : "placement new constructing an object of type %qT"
+                       : "placement new constructing an object of type %qT "
                        "and size %qwu in a region of type %qT and size "
                        "at most %qwu",
                        type, bytes_need, TREE_TYPE (oper),
@@ -2774,15 +2815,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
     {
       if (complain & tf_warning_or_error)
        {
-         const char *msg;
-         if (typedef_variant_p (orig_type))
-           msg = ("non-constant array new length must be specified "
-                  "directly, not by typedef");
-         else
-           msg = ("non-constant array new length must be specified "
-                  "without parentheses around the type-id");
-         pedwarn (EXPR_LOC_OR_LOC (outer_nelts, input_location),
-                  OPT_Wvla, msg);
+         pedwarn (EXPR_LOC_OR_LOC (outer_nelts, input_location), OPT_Wvla,
+                  typedef_variant_p (orig_type)
+                  ? G_("non-constant array new length must be specified "
+                       "directly, not by typedef")
+                  : G_("non-constant array new length must be specified "
+                       "without parentheses around the type-id"));
        }
       else
        return error_mark_node;
@@ -3440,15 +3478,19 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (nelts == NULL_TREE && vec_safe_length (*init) == 1
+  if (nelts == NULL_TREE
       /* Don't do auto deduction where it might affect mangling.  */
       && (!processing_template_decl || at_function_scope_p ()))
     {
       tree auto_node = type_uses_auto (type);
       if (auto_node)
        {
-         tree d_init = (**init)[0];
-         d_init = resolve_nondeduced_context (d_init, complain);
+         tree d_init = NULL_TREE;
+         if (vec_safe_length (*init) == 1)
+           {
+             d_init = (**init)[0];
+             d_init = resolve_nondeduced_context (d_init, complain);
+           }
          type = do_auto_deduction (type, d_init, auto_node);
        }
     }