#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);
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. */
{
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);
}
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));
/* 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 ();
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;
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)
{
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),
{
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;
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);
}
}