/* Handle initialization things in C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
static tree build_dtor_call (tree, special_function_kind, int);
static tree build_field_list (tree, tree, int *);
static tree build_vtbl_address (tree);
+static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool);
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
/* Iterate over the array elements, building initializations. */
if (nelts)
- max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts),
+ max_index = fold_build2_loc (input_location,
+ MINUS_EXPR, TREE_TYPE (nelts),
nelts, integer_one_node);
else
max_index = array_type_nelts (type);
{
if (init == NULL_TREE)
{
+ tree core_type;
/* member traversal: note it leaves init NULL */
if (TREE_CODE (type) == REFERENCE_TYPE)
permerror (DECL_SOURCE_LOCATION (current_function_decl),
permerror (DECL_SOURCE_LOCATION (current_function_decl),
"uninitialized member %qD with %<const%> type %qT",
member, type);
+
+ core_type = strip_array_types (type);
+ if (CLASS_TYPE_P (core_type)
+ && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+ || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
+ diagnose_uninitialized_cst_or_ref_member (core_type,
+ /*using_new=*/false,
+ /*complain=*/true);
}
else if (TREE_CODE (init) == TREE_LIST)
/* There was an explicit member initialization. Do some work
base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
subobject, 1);
expand_aggr_init_1 (subobject, NULL_TREE,
- cp_build_indirect_ref (base_addr, NULL,
+ cp_build_indirect_ref (base_addr, RO_NULL,
tf_warning_or_error),
arguments,
LOOKUP_NORMAL,
TREE_TYPE (vtt_parm),
vtt_parm,
vtt_index);
- vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error);
+ vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
/* The actual initializer is the VTT value only in the subobject
}
/* Compute the location of the vtpr. */
- vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL,
+ vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL,
tf_warning_or_error),
TREE_TYPE (binfo));
gcc_assert (vtbl_ptr != error_mark_node);
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
if (flag)
- expr = fold_build3 (COND_EXPR, void_type_node,
+ expr = fold_build3_loc (input_location,
+ COND_EXPR, void_type_node,
c_common_truthvalue_conversion (input_location, flag),
expr, integer_zero_node);
/* Must arrange to initialize each element of EXP
from elements of INIT. */
itype = init ? TREE_TYPE (init) : NULL_TREE;
- if (cp_type_quals (type) != TYPE_UNQUALIFIED)
- TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
- if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
- itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
+ if (cv_qualified_p (type))
+ TREE_TYPE (exp) = cv_unqualified (type);
+ if (itype && cv_qualified_p (itype))
+ TREE_TYPE (init) = cv_unqualified (itype);
stmt_expr = build_vec_init (exp, NULL_TREE, init,
/*explicit_value_init_p=*/false,
- itype && same_type_p (itype,
+ itype && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)),
complain);
TREE_READONLY (exp) = was_const;
init = DECL_INITIAL (decl);
}
if (init == error_mark_node)
- return decl;
+ {
+ if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+ /* Treat the error as a constant to avoid cascading errors on
+ excessively recursive template instantiation (c++/9335). */
+ return init;
+ else
+ return decl;
+ }
/* Initializers in templates are generally expanded during
instantiation, so before that for const int i(2)
INIT is a TREE_LIST with the actual initializer as
return new_expr;
}
+/* Diagnose uninitialized const members or reference members of type
+ TYPE. USING_NEW is used to disambiguate the diagnostic between a
+ new expression without a new-initializer and a declaration. Returns
+ the error count. */
+
+static int
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+ bool using_new, bool complain)
+{
+ tree field;
+ int error_count = 0;
+
+ if (type_has_user_provided_constructor (type))
+ return 0;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ tree field_type;
+
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ field_type = strip_array_types (TREE_TYPE (field));
+
+ if (TREE_CODE (field_type) == REFERENCE_TYPE)
+ {
+ ++ error_count;
+ if (complain)
+ {
+ if (using_new)
+ error ("uninitialized reference member in %q#T "
+ "using %<new%> without new-initializer", origin);
+ else
+ error ("uninitialized reference member in %q#T", origin);
+ inform (DECL_SOURCE_LOCATION (field),
+ "%qD should be initialized", field);
+ }
+ }
+
+ if (CP_TYPE_CONST_P (field_type))
+ {
+ ++ error_count;
+ if (complain)
+ {
+ if (using_new)
+ error ("uninitialized const member in %q#T "
+ "using %<new%> without new-initializer", origin);
+ else
+ error ("uninitialized const member in %q#T", origin);
+ inform (DECL_SOURCE_LOCATION (field),
+ "%qD should be initialized", field);
+ }
+ }
+
+ if (CLASS_TYPE_P (field_type))
+ error_count
+ += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin,
+ using_new, complain);
+ }
+ return error_count;
+}
+
+int
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool complain)
+{
+ return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain);
+}
+
/* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for
is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
+ if (*init == NULL)
+ {
+ bool maybe_uninitialized_error = false;
+ /* A program that calls for default-initialization [...] of an
+ entity of reference type is ill-formed. */
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type))
+ maybe_uninitialized_error = true;
+
+ /* A new-expression that creates an object of type T initializes
+ that object as follows:
+ - If the new-initializer is omitted:
+ -- If T is a (possibly cv-qualified) non-POD class type
+ (or array thereof), the object is default-initialized (8.5).
+ [...]
+ -- Otherwise, the object created has indeterminate
+ value. If T is a const-qualified type, or a (possibly
+ cv-qualified) POD class type (or array thereof)
+ containing (directly or indirectly) a member of
+ const-qualified type, the program is ill-formed; */
+
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type))
+ maybe_uninitialized_error = true;
+
+ if (maybe_uninitialized_error
+ && diagnose_uninitialized_cst_or_ref_member (elt_type,
+ /*using_new=*/true,
+ complain & tf_error))
+ return error_mark_node;
+ }
+
if (CP_TYPE_CONST_P (elt_type) && *init == NULL
&& !type_has_user_provided_default_constructor (elt_type))
{
many elements to destroy later. We use the last sizeof
(size_t) bytes to store the number of elements. */
cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype));
- cookie_ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
+ cookie_ptr = fold_build2_loc (input_location,
+ POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
alloc_node, cookie_ptr);
size_ptr_type = build_pointer_type (sizetype);
cookie_ptr = fold_convert (size_ptr_type, cookie_ptr);
- cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+ cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
{
/* Also store the element size. */
cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr,
- fold_build1 (NEGATE_EXPR, sizetype,
+ fold_build1_loc (input_location,
+ NEGATE_EXPR, sizetype,
size_in_bytes (sizetype)));
- cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+ cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
cookie = build2 (MODIFY_EXPR, sizetype, cookie,
size_in_bytes (elt_type));
cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
}
else
{
- init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+ init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
{
else
return error_mark_node;
}
+ nelts = mark_rvalue_use (nelts);
nelts = cp_save_expr (cp_convert (sizetype, nelts));
}
tbase = create_temporary_var (ptype);
tbase_init = cp_build_modify_expr (tbase, NOP_EXPR,
- fold_build2 (POINTER_PLUS_EXPR, ptype,
+ fold_build2_loc (input_location,
+ POINTER_PLUS_EXPR, ptype,
fold_convert (ptype, base),
virtual_size),
tf_warning_or_error);
- DECL_REGISTER (tbase) = 1;
controller = build3 (BIND_EXPR, void_type_node, tbase,
NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (controller) = 1;
body = build1 (EXIT_EXPR, void_type_node,
build2 (EQ_EXPR, boolean_type_node, tbase,
fold_convert (ptype, base)));
- tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp);
+ tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
body = build_compound_expr
(input_location,
body, cp_build_modify_expr (tbase, NOP_EXPR,
body = integer_zero_node;
/* Outermost wrapper: If pointer is null, punt. */
- body = fold_build3 (COND_EXPR, void_type_node,
- fold_build2 (NE_EXPR, boolean_type_node, base,
+ body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+ fold_build2_loc (input_location,
+ NE_EXPR, boolean_type_node, base,
convert (TREE_TYPE (base),
integer_zero_node)),
body, integer_zero_node);
{
tree rval;
tree base2 = NULL_TREE;
- tree size;
tree itype = NULL_TREE;
tree iterator;
/* The type of BASE. */
gcc_assert (!init);
inner_elt_type = strip_array_types (type);
+
+ /* Look through the TARGET_EXPR around a compound literal. */
+ if (init && TREE_CODE (init) == TARGET_EXPR
+ && TREE_CODE (TARGET_EXPR_INITIAL (init)) == CONSTRUCTOR
+ && from_array != 2)
+ init = TARGET_EXPR_INITIAL (init);
+
if (init
&& TREE_CODE (atype) == ARRAY_TYPE
&& (from_array == 2
|| ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
|| from_array))
{
- /* Do non-default initialization of POD arrays resulting from
+ /* Do non-default initialization of trivial arrays resulting from
brace-enclosed initializers. In this case, digest_init and
store_constructor will handle the semantics for us. */
}
maxindex = cp_convert (ptrdiff_type_node, maxindex);
- size = size_in_bytes (type);
if (TREE_CODE (atype) == ARRAY_TYPE)
{
ptype = build_pointer_type (type);
base = get_temp_regvar (ptype, rval);
iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
+ /* If initializing one array from another, initialize element by
+ element. We rely upon the below calls to do the argument
+ checking. Evaluate the initializer before entering the try block. */
+ if (from_array && init && TREE_CODE (init) != CONSTRUCTOR)
+ {
+ base2 = decay_conversion (init);
+ itype = TREE_TYPE (base2);
+ base2 = get_temp_regvar (itype, base2);
+ itype = TREE_TYPE (itype);
+ }
+
/* Protect the entire array initialization so that we can destroy
the partially constructed array if an exception is thrown.
But don't do this if we're assigning. */
if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
{
- /* Do non-default initialization of non-POD arrays resulting from
+ /* Do non-default initialization of non-trivial arrays resulting from
brace-enclosed initializers. */
unsigned HOST_WIDE_INT idx;
tree elt;
}
else if (from_array)
{
- /* If initializing one array from another, initialize element by
- element. We rely upon the below calls the do argument
- checking. */
if (init)
- {
- base2 = decay_conversion (init);
- itype = TREE_TYPE (base2);
- base2 = get_temp_regvar (itype, base2);
- itype = TREE_TYPE (itype);
- }
+ /* OK, we set base2 above. */;
else if (TYPE_LANG_SPECIFIC (type)
&& TYPE_NEEDS_CONSTRUCTING (type)
&& ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
{
atype = build_pointer_type (atype);
stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
- stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+ stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain);
TREE_NO_WARNING (stmt_expr) = 1;
}
type = TYPE_MAIN_VARIANT (type);
+ addr = mark_rvalue_use (addr);
+
if (TREE_CODE (type) == POINTER_TYPE)
{
bool complete_p = true;
/*alloc_fn=*/NULL_TREE);
}
- expr = build_dtor_call (cp_build_indirect_ref (addr, NULL,
+ expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
tf_warning_or_error),
auto_delete, flags);
if (do_delete)
base = TARGET_EXPR_SLOT (base_init);
}
type = strip_array_types (TREE_TYPE (type));
- cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype));
+ cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR,
+ sizetype, TYPE_SIZE_UNIT (sizetype));
cookie_addr = build2 (POINTER_PLUS_EXPR,
size_ptr_type,
fold_convert (size_ptr_type, base),
cookie_addr);
- maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error);
+ maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{