static tree get_temp_regvar (tree, tree);
static tree dfs_initialize_vtbl_ptrs (tree, void *);
static tree build_default_init (tree, tree);
-static tree build_new_1 (tree);
static tree build_dtor_call (tree, special_function_kind, int);
static tree build_field_list (tree, tree, int *);
static tree build_vtbl_address (tree);
items with static storage duration that are not otherwise
initialized are initialized to zero. */
;
- else if (SCALAR_TYPE_P (type))
+ else if (SCALAR_TYPE_P (type)
+ || TREE_CODE (type) == COMPLEX_TYPE)
init = convert (type, integer_zero_node);
else if (CLASS_TYPE_P (type))
{
nelts, integer_one_node);
else
max_index = array_type_nelts (type);
+
+ /* If we have an error_mark here, we should just return error mark
+ as we don't know the size of the array yet. */
+ if (max_index == error_mark_node)
+ return error_mark_node;
gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
/* A zero-sized array, which is accepted as an extension, will
/* Build a constructor to contain the initializations. */
init = build_constructor (type, v);
}
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+ init = fold_convert (type, integer_zero_node);
else
gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
/* Effective C++ rule 12 requires that all data members be
initialized. */
if (warn_ecpp && !explicit && TREE_CODE (type) != ARRAY_TYPE)
- warning (0, "%J%qD should be initialized in the member initialization "
+ warning (OPT_Weffc__, "%J%qD should be initialized in the member initialization "
"list", current_function_decl, member);
if (init == void_type_node)
if (warn_reorder && !subobject_init)
{
if (TREE_CODE (TREE_PURPOSE (next_subobject)) == FIELD_DECL)
- warning (0, "%q+D will be initialized after",
+ warning (OPT_Wreorder, "%q+D will be initialized after",
TREE_PURPOSE (next_subobject));
else
- warning (0, "base %qT will be initialized after",
+ warning (OPT_Wreorder, "base %qT will be initialized after",
TREE_PURPOSE (next_subobject));
if (TREE_CODE (subobject) == FIELD_DECL)
- warning (0, " %q+#D", subobject);
+ warning (OPT_Wreorder, " %q+#D", subobject);
else
- warning (0, " base %qT", subobject);
- warning (0, "%J when initialized here", current_function_decl);
+ warning (OPT_Wreorder, " base %qT", subobject);
+ warning (OPT_Wreorder, "%J when initialized here", current_function_decl);
}
/* Look again, from the beginning of the list. */
if (extra_warnings && !arguments
&& DECL_COPY_CONSTRUCTOR_P (current_function_decl)
&& TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (subobject)))
- warning (0, "%Jbase class %q#T should be explicitly initialized in the "
+ warning (OPT_Wextra, "%Jbase class %q#T should be explicitly initialized in the "
"copy constructor",
current_function_decl, BINFO_TYPE (subobject));
confuses the sjlj exception-handling code. Therefore, we do not
create a single conditional block, but one for each
initialization. (That way the cleanup regions always begin
- in the outer block.) We trust the back-end to figure out
+ in the outer block.) We trust the back end to figure out
that the FLAG will not change across initializations, and
avoid doing multiple tests. */
flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
if (!direct_binfo && !virtual_binfo)
{
if (CLASSTYPE_VBASECLASSES (current_class_type))
- error ("type %qD is not a direct or virtual base of %qT",
- name, current_class_type);
+ error ("type %qT is not a direct or virtual base of %qT",
+ basetype, current_class_type);
else
- error ("type %qD is not a direct base of %qT",
- name, current_class_type);
+ error ("type %qT is not a direct base of %qT",
+ basetype, current_class_type);
return NULL_TREE;
}
return stmt_expr;
}
-/* Like build_aggr_init, but not just for aggregates. */
-
-tree
-build_init (tree decl, tree init, int flags)
-{
- tree expr;
-
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expr = build_aggr_init (decl, init, flags);
- else if (CLASS_TYPE_P (TREE_TYPE (decl)))
- expr = build_special_member_call (decl, complete_ctor_identifier,
- build_tree_list (NULL_TREE, init),
- TREE_TYPE (decl),
- LOOKUP_NORMAL|flags);
- else
- expr = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
-
- return expr;
-}
-
static void
expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
{
as TARGET_EXPRs. */
if (init && TREE_CODE (exp) == VAR_DECL
- && TREE_CODE (init) == CONSTRUCTOR
- && TREE_HAS_CONSTRUCTOR (init))
+ && COMPOUND_LITERAL_P (init))
{
/* If store_init_value returns NULL_TREE, the INIT has been
- record in the DECL_INITIAL for EXP. That means there's
+ recorded as the DECL_INITIAL for EXP. That means there's
nothing more we have to do. */
init = store_init_value (exp, init);
if (init)
@@ This function should be rewritten and placed in search.c. */
tree
-build_offset_ref (tree type, tree name, bool address_p)
+build_offset_ref (tree type, tree member, bool address_p)
{
tree decl;
- tree member;
tree basebinfo = NULL_TREE;
- tree orig_name = name;
/* class templates can come in as TEMPLATE_DECLs here. */
- if (TREE_CODE (name) == TEMPLATE_DECL)
- return name;
+ if (TREE_CODE (member) == TEMPLATE_DECL)
+ return member;
- if (dependent_type_p (type) || type_dependent_expression_p (name))
- return build_qualified_name (NULL_TREE, type, name,
+ if (dependent_type_p (type) || type_dependent_expression_p (member))
+ return build_qualified_name (NULL_TREE, type, member,
/*template_p=*/false);
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
- something like `a.template f<int>' or the like. For the most
- part, we treat this just like a.f. We do remember, however,
- the template-id that was used. */
- name = TREE_OPERAND (orig_name, 0);
-
- if (DECL_P (name))
- name = DECL_NAME (name);
- else
- {
- if (TREE_CODE (name) == COMPONENT_REF)
- name = TREE_OPERAND (name, 1);
- if (TREE_CODE (name) == OVERLOAD)
- name = DECL_NAME (OVL_CURRENT (name));
- }
-
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
- }
-
- if (type == NULL_TREE)
- return error_mark_node;
-
- /* Handle namespace names fully here. */
- if (TREE_CODE (type) == NAMESPACE_DECL)
- {
- tree t = lookup_namespace_name (type, name);
- if (t == error_mark_node)
- return t;
- if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
- /* Reconstruct the TEMPLATE_ID_EXPR. */
- t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t),
- t, TREE_OPERAND (orig_name, 1));
- if (! type_unknown_p (t))
- {
- mark_used (t);
- t = convert_from_reference (t);
- }
- return t;
- }
-
+ gcc_assert (TYPE_P (type));
if (! is_aggr_type (type, 1))
return error_mark_node;
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- if (! check_dtor_name (type, name))
- error ("qualified type %qT does not match destructor name %<~%T%>",
- type, TREE_OPERAND (name, 0));
- name = dtor_identifier;
- }
+ gcc_assert (DECL_P (member) || BASELINK_P (member));
+ /* Callers should call mark_used before this point. */
+ gcc_assert (!DECL_P (member) || TREE_USED (member));
if (!COMPLETE_TYPE_P (complete_type (type))
&& !TYPE_BEING_DEFINED (type))
{
- error ("incomplete type %qT does not have member %qD", type, name);
- return error_mark_node;
- }
-
- /* Set up BASEBINFO for member lookup. */
- decl = maybe_dummy_object (type, &basebinfo);
-
- if (BASELINK_P (name) || DECL_P (name))
- member = name;
- else
- {
- member = lookup_member (basebinfo, name, 1, 0);
-
- if (member == error_mark_node)
- return error_mark_node;
- }
-
- if (!member)
- {
- error ("%qD is not a member of type %qT", name, type);
+ error ("incomplete type %qT does not have member %qD", type, member);
return error_mark_node;
}
+ /* Entities other than non-static members need no further
+ processing. */
if (TREE_CODE (member) == TYPE_DECL)
- {
- TREE_USED (member) = 1;
- return member;
- }
- /* static class members and class-specific enum
- values can be returned without further ado. */
+ return member;
if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
- {
- mark_used (member);
- return convert_from_reference (member);
- }
+ return convert_from_reference (member);
if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
{
return error_mark_node;
}
+ /* Set up BASEBINFO for member lookup. */
+ decl = maybe_dummy_object (type, &basebinfo);
+
/* A lot of this logic is now handled in lookup_member. */
if (BASELINK_P (member))
{
/* Go from the TREE_BASELINK to the member function info. */
- tree fnfields = member;
- tree t = BASELINK_FUNCTIONS (fnfields);
-
- if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
- {
- /* The FNFIELDS are going to contain functions that aren't
- necessarily templates, and templates that don't
- necessarily match the explicit template parameters. We
- save all the functions, and the explicit parameters, and
- then figure out exactly what to instantiate with what
- arguments in instantiate_type. */
-
- if (TREE_CODE (t) != OVERLOAD)
- /* The code in instantiate_type which will process this
- expects to encounter OVERLOADs, not raw functions. */
- t = ovl_cons (t, NULL_TREE);
-
- t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t), t,
- TREE_OPERAND (orig_name, 1));
- t = build2 (OFFSET_REF, unknown_type_node, decl, t);
-
- PTRMEM_OK_P (t) = 1;
-
- return t;
- }
+ tree t = BASELINK_FUNCTIONS (member);
if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
{
(or any class derived from that class). */
if (address_p && DECL_P (t)
&& DECL_NONSTATIC_MEMBER_P (t))
- perform_or_defer_access_check (TYPE_BINFO (type), t);
+ perform_or_defer_access_check (TYPE_BINFO (type), t, t);
else
- perform_or_defer_access_check (basebinfo, t);
+ perform_or_defer_access_check (basebinfo, t, t);
- mark_used (t);
if (DECL_STATIC_FUNCTION_P (t))
return t;
member = t;
}
else
- {
- TREE_TYPE (fnfields) = unknown_type_node;
- member = fnfields;
- }
+ 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);
+ perform_or_defer_access_check (TYPE_BINFO (type), member, member);
if (!address_p)
{
}
error ("invalid use of non-static member function %qD",
TREE_OPERAND (member, 1));
- return member;
+ return error_mark_node;
}
else if (TREE_CODE (member) == FIELD_DECL)
{
constant_value_1 (tree decl, bool integral_p)
{
while (TREE_CODE (decl) == CONST_DECL
- || (integral_p
+ || (integral_p
? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
: (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
{
tree init;
- /* If DECL is a static data member in a template class, we must
- instantiate it here. The initializer for the static data
- member is not processed until needed; we need it now. */
- mark_used (decl);
- init = DECL_INITIAL (decl);
- /* If we are currently processing a template, the
- initializer for a static data member may not be dependent,
- but it is not folded until instantiation time. */
- if (init)
- init = fold_non_dependent_expr (init);
- if (!(init || init == error_mark_node)
+ /* Static data members in template classes may have
+ non-dependent initializers. References to such non-static
+ data members are not value-dependent, so we must retrieve the
+ initializer here. The DECL_INITIAL will have the right type,
+ but will not have been folded because that would prevent us
+ from performing all appropriate semantic checks at
+ instantiation time. */
+ if (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
+ && uses_template_parms (CLASSTYPE_TI_ARGS
+ (DECL_CONTEXT (decl))))
+ {
+ ++processing_template_decl;
+ init = fold_non_dependent_expr (DECL_INITIAL (decl));
+ --processing_template_decl;
+ }
+ else
+ {
+ /* If DECL is a static data member in a template
+ specialization, we must instantiate it here. The
+ initializer for the static data member is not processed
+ until needed; we need it now. */
+ mark_used (decl);
+ init = DECL_INITIAL (decl);
+ }
+ if (init == error_mark_node)
+ return decl;
+ if (!init
|| !TREE_TYPE (init)
|| (integral_p
? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init))
: (!TREE_CONSTANT (init)
/* Do not return an aggregate constant (of which
string literals are a special case), as we do not
- want to make inadvertant copies of such entities,
+ want to make inadvertent copies of such entities,
and we must be sure that their addresses are the
same everywhere. */
|| TREE_CODE (init) == CONSTRUCTOR
|| TREE_CODE (init) == STRING_CST)))
break;
- decl = init;
+ decl = unshare_expr (init);
}
return decl;
}
}
/* A more relaxed version of integral_constant_value, used by the
- common C/C++ code and by the C++ front-end for optimization
+ common C/C++ code and by the C++ front end for optimization
purposes. */
tree
decl_constant_value (tree decl)
{
- return constant_value_1 (decl,
+ return constant_value_1 (decl,
/*integral_p=*/processing_template_decl);
}
\f
return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
}
\f
-/* Generate a representation for a C++ "new" expression. PLACEMENT is
- a TREE_LIST of placement-new arguments (or NULL_TREE if none). If
- NELTS is NULL, TYPE is the type of the storage to be allocated. If
- NELTS is not NULL, then this is an array-new allocation; TYPE is
- the type of the elements in the array and NELTS is the number of
- elements in the array. INIT, if non-NULL, is the initializer for
- the new object. If USE_GLOBAL_NEW is true, then the user
- explicitly wrote "::new" rather than just "new". */
+/* Build and return a NEW_EXPR. If NELTS is non-NULL, TYPE[NELTS] is
+ the type of the object being allocated; otherwise, it's just TYPE.
+ INIT is the initializer, if any. USE_GLOBAL_NEW is true if the
+ user explicitly wrote "::operator new". PLACEMENT, if non-NULL, is
+ the TREE_LIST of arguments to be provided as arguments to a
+ placement new operator. This routine performs no semantic checks;
+ it just creates and returns a NEW_EXPR. */
-tree
-build_new (tree placement, tree type, tree nelts, tree init,
- int use_global_new)
-{
- tree rval;
-
- if (type == error_mark_node)
- return error_mark_node;
-
- if (processing_template_decl)
- {
- rval = build_min (NEW_EXPR, build_pointer_type (type),
- placement, type, nelts, init);
- NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
- TREE_SIDE_EFFECTS (rval) = 1;
- return rval;
- }
-
- if (nelts)
- {
- if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
- pedwarn ("size in array new must have integral type");
- nelts = save_expr (cp_convert (sizetype, nelts));
- if (nelts == integer_zero_node)
- warning (0, "zero size array reserves no space");
- }
-
- /* ``A reference cannot be created by the new operator. A reference
- is not an object (8.2.2, 8.4.3), so a pointer to it could not be
- returned by new.'' ARM 5.3.3 */
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- error ("new cannot be applied to a reference type");
- type = TREE_TYPE (type);
- }
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("new cannot be applied to a function type");
- return error_mark_node;
- }
-
- rval = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
- nelts, init);
- NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
- TREE_SIDE_EFFECTS (rval) = 1;
- rval = build_new_1 (rval);
- if (rval == error_mark_node)
- return error_mark_node;
-
- /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
- rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
- TREE_NO_WARNING (rval) = 1;
-
- return rval;
-}
-
-/* Given a Java class, return a decl for the corresponding java.lang.Class. */
-
-tree
-build_java_class_ref (tree type)
+static tree
+build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
+ int use_global_new)
{
- tree name = NULL_TREE, class_decl;
- static tree CL_suffix = NULL_TREE;
- if (CL_suffix == NULL_TREE)
- CL_suffix = get_identifier("class$");
- if (jclass_node == NULL_TREE)
- {
- jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
- if (jclass_node == NULL_TREE)
- fatal_error ("call to Java constructor, while %<jclass%> undefined");
+ tree new_expr;
- jclass_node = TREE_TYPE (jclass_node);
- }
-
- /* Mangle the class$ field. */
- {
- tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (DECL_NAME (field) == CL_suffix)
- {
- mangle_decl (field);
- name = DECL_ASSEMBLER_NAME (field);
- break;
- }
- if (!field)
- internal_error ("can't find class$");
- }
+ new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
+ nelts, init);
+ NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
+ TREE_SIDE_EFFECTS (new_expr) = 1;
- class_decl = IDENTIFIER_GLOBAL_VALUE (name);
- if (class_decl == NULL_TREE)
- {
- class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
- TREE_STATIC (class_decl) = 1;
- DECL_EXTERNAL (class_decl) = 1;
- TREE_PUBLIC (class_decl) = 1;
- DECL_ARTIFICIAL (class_decl) = 1;
- DECL_IGNORED_P (class_decl) = 1;
- pushdecl_top_level (class_decl);
- make_decl_rtl (class_decl);
- }
- return class_decl;
+ return new_expr;
}
-
-/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
- value is immediately handed to expand_expr. */
+/* 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
+ build_raw_new_expr. */
static tree
-build_new_1 (tree exp)
+build_new_1 (tree placement, tree type, tree nelts, tree init,
+ bool globally_qualified_p)
{
- tree placement, init;
tree size, rval;
/* True iff this is a call to "operator new[]" instead of just
"operator new". */
/* The type of the new-expression. (This type is always a pointer
type.) */
tree pointer_type;
- /* The type pointed to by POINTER_TYPE. This type may be different
- from ELT_TYPE for a multi-dimensional array; ELT_TYPE is never an
- ARRAY_TYPE, but TYPE may be an ARRAY_TYPE. */
- tree type;
/* A pointer type pointing to the FULL_TYPE. */
tree full_pointer_type;
tree outer_nelts = NULL_TREE;
- tree nelts = NULL_TREE;
tree alloc_call, alloc_expr;
/* The address returned by the call to "operator new". This node is
a VAR_DECL and is therefore reusable. */
tree alloc_fn;
tree cookie_expr, init_expr;
int nothrow, check_new;
- /* Nonzero if the user wrote `::new' rather than just `new'. */
- int globally_qualified_p;
int use_java_new = 0;
/* If non-NULL, the number of extra bytes to allocate at the
beginning of the storage allocated for an array-new expression in
tree data_addr;
tree init_preeval_expr = NULL_TREE;
- placement = TREE_OPERAND (exp, 0);
- type = TREE_OPERAND (exp, 1);
- nelts = TREE_OPERAND (exp, 2);
- init = TREE_OPERAND (exp, 3);
- globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
-
if (nelts)
{
tree index;
function context. Methinks that's not it's purvey. So we'll do
our own VLA layout later. */
vla_p = true;
- full_type = build_cplus_array_type (type, NULL_TREE);
index = convert (sizetype, nelts);
index = size_binop (MINUS_EXPR, index, size_one_node);
- TYPE_DOMAIN (full_type) = build_index_type (index);
+ index = build_index_type (index);
+ full_type = build_cplus_array_type (type, NULL_TREE);
+ /* We need a copy of the type as build_array_type will return a shared copy
+ of the incomplete array type. */
+ full_type = build_distinct_type_copy (full_type);
+ TYPE_DOMAIN (full_type) = index;
}
else
{
}
}
- if (!complete_type_or_else (type, exp))
+ if (!complete_type_or_else (type, NULL_TREE))
return error_mark_node;
/* If our base type is an array, then make sure we know how many elements
}
}
+ alloc_fn = NULL_TREE;
+
/* Allocate the object. */
if (! placement && TYPE_FOR_JAVA (elt_type))
{
- tree class_addr, alloc_decl;
+ tree class_addr;
tree class_decl = build_java_class_ref (elt_type);
static const char alloc_name[] = "_Jv_AllocObject";
+ if (class_decl == error_mark_node)
+ return error_mark_node;
+
use_java_new = 1;
- alloc_decl = NULL;
if (!get_global_value_if_present (get_identifier (alloc_name),
- &alloc_decl))
+ &alloc_fn))
{
error ("call to Java constructor with %qs undefined", alloc_name);
return error_mark_node;
}
- else if (really_overloaded_fn (alloc_decl))
+ else if (really_overloaded_fn (alloc_fn))
{
- error ("%qD should never be overloaded", alloc_decl);
+ error ("%qD should never be overloaded", alloc_fn);
return error_mark_node;
}
- alloc_decl = OVL_CURRENT (alloc_decl);
+ alloc_fn = OVL_CURRENT (alloc_fn);
class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
alloc_call = (build_function_call
- (alloc_decl,
+ (alloc_fn,
build_tree_list (NULL_TREE, class_addr)));
}
else
alloc_call = build_new_method_call (build_dummy_object (elt_type),
fns, args,
/*conversion_path=*/NULL_TREE,
- LOOKUP_NORMAL);
+ LOOKUP_NORMAL,
+ &alloc_fn);
}
else
{
cookie_size = NULL_TREE;
alloc_call = build_operator_new_call (fnname, placement,
- &size, &cookie_size);
+ &size, &cookie_size,
+ &alloc_fn);
}
}
if (alloc_call == error_mark_node)
return error_mark_node;
+ gcc_assert (alloc_fn != NULL_TREE);
+
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
if (!cookie_size && !is_initialized)
/* Strip any COMPOUND_EXPRs from ALLOC_CALL. */
while (TREE_CODE (alloc_call) == COMPOUND_EXPR)
alloc_call = TREE_OPERAND (alloc_call, 1);
- alloc_fn = get_callee_fndecl (alloc_call);
- gcc_assert (alloc_fn != NULL_TREE);
/* Now, check to see if this function is actually a placement
allocation function. This can happen even when PLACEMENT is NULL
= build_vec_init (init_expr,
cp_build_binary_op (MINUS_EXPR, outer_nelts,
integer_one_node),
- init,
- explicit_default_init_p,
+ init,
+ explicit_default_init_p,
/*from_array=*/0);
/* An array initialization is stable because the initialization
{
/* We are processing something like `new int (10)', which
means allocate an int, and initialize it with 10. */
-
+
if (TREE_CODE (init) == TREE_LIST)
- init = build_x_compound_expr_from_list (init,
+ init = build_x_compound_expr_from_list (init,
"new initializer");
else
gcc_assert (TREE_CODE (init) != CONSTRUCTOR
|| TREE_TYPE (init) != NULL_TREE);
-
+
init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
stable = stabilize_init (init_expr, &init_preeval_expr);
}
cleanup = build_op_delete_call (dcode, alloc_node, size,
globally_qualified_p,
(placement_allocation_fn_p
- ? alloc_call : NULL_TREE));
+ ? alloc_call : NULL_TREE),
+ (placement_allocation_fn_p
+ ? alloc_fn : NULL_TREE));
if (!cleanup)
/* We're done. */;
rval = build_nop (pointer_type, rval);
/* A new-expression is never an lvalue. */
- rval = rvalue (rval);
+ gcc_assert (!lvalue_p (rval));
+
+ return rval;
+}
+
+/* Generate a representation for a C++ "new" expression. PLACEMENT is
+ a TREE_LIST of placement-new arguments (or NULL_TREE if none). If
+ NELTS is NULL, TYPE is the type of the storage to be allocated. If
+ NELTS is not NULL, then this is an array-new allocation; TYPE is
+ the type of the elements in the array and NELTS is the number of
+ elements in the array. INIT, if non-NULL, is the initializer for
+ the new object, or void_zero_node to indicate an initializer of
+ "()". If USE_GLOBAL_NEW is true, then the user explicitly wrote
+ "::new" rather than just "new". */
+
+tree
+build_new (tree placement, tree type, tree nelts, tree init,
+ int use_global_new)
+{
+ tree rval;
+ tree orig_placement;
+ tree orig_nelts;
+ tree orig_init;
+
+ if (placement == error_mark_node || type == error_mark_node
+ || init == error_mark_node)
+ return error_mark_node;
+
+ orig_placement = placement;
+ orig_nelts = nelts;
+ orig_init = init;
+
+ if (processing_template_decl)
+ {
+ if (dependent_type_p (type)
+ || any_type_dependent_arguments_p (placement)
+ || (nelts && type_dependent_expression_p (nelts))
+ || (init != void_zero_node
+ && any_type_dependent_arguments_p (init)))
+ return build_raw_new_expr (placement, type, nelts, init,
+ use_global_new);
+ placement = build_non_dependent_args (placement);
+ if (nelts)
+ nelts = build_non_dependent_expr (nelts);
+ if (init != void_zero_node)
+ init = build_non_dependent_args (init);
+ }
+
+ if (nelts)
+ {
+ if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
+ pedwarn ("size in array new must have integral type");
+ nelts = cp_save_expr (cp_convert (sizetype, nelts));
+ /* It is valid to allocate a zero-element array:
+
+ [expr.new]
+
+ When the value of the expression in a direct-new-declarator
+ is zero, the allocation function is called to allocate an
+ array with no elements. The pointer returned by the
+ new-expression is non-null. [Note: If the library allocation
+ function is called, the pointer returned is distinct from the
+ pointer to any other object.]
+
+ However, that is not generally useful, so we issue a
+ warning. */
+ if (integer_zerop (nelts))
+ warning (0, "allocating zero-element array");
+ }
+
+ /* ``A reference cannot be created by the new operator. A reference
+ is not an object (8.2.2, 8.4.3), so a pointer to it could not be
+ returned by new.'' ARM 5.3.3 */
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ error ("new cannot be applied to a reference type");
+ type = TREE_TYPE (type);
+ }
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error ("new cannot be applied to a function type");
+ return error_mark_node;
+ }
+
+ rval = build_new_1 (placement, type, nelts, init, use_global_new);
+ if (rval == error_mark_node)
+ return error_mark_node;
+
+ if (processing_template_decl)
+ return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init,
+ use_global_new);
+
+ /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
+ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
+ TREE_NO_WARNING (rval) = 1;
return rval;
}
+
+/* Given a Java class, return a decl for the corresponding java.lang.Class. */
+
+tree
+build_java_class_ref (tree type)
+{
+ tree name = NULL_TREE, class_decl;
+ static tree CL_suffix = NULL_TREE;
+ if (CL_suffix == NULL_TREE)
+ CL_suffix = get_identifier("class$");
+ if (jclass_node == NULL_TREE)
+ {
+ jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
+ if (jclass_node == NULL_TREE)
+ {
+ error ("call to Java constructor, while %<jclass%> undefined");
+ return error_mark_node;
+ }
+ jclass_node = TREE_TYPE (jclass_node);
+ }
+
+ /* Mangle the class$ field. */
+ {
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (DECL_NAME (field) == CL_suffix)
+ {
+ mangle_decl (field);
+ name = DECL_ASSEMBLER_NAME (field);
+ break;
+ }
+ if (!field)
+ {
+ error ("can't find %<class$%> in %qT", type);
+ return error_mark_node;
+ }
+ }
+
+ class_decl = IDENTIFIER_GLOBAL_VALUE (name);
+ if (class_decl == NULL_TREE)
+ {
+ class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+ TREE_STATIC (class_decl) = 1;
+ DECL_EXTERNAL (class_decl) = 1;
+ TREE_PUBLIC (class_decl) = 1;
+ DECL_ARTIFICIAL (class_decl) = 1;
+ DECL_IGNORED_P (class_decl) = 1;
+ pushdecl_top_level (class_decl);
+ make_decl_rtl (class_decl);
+ }
+ return class_decl;
+}
\f
static tree
build_vec_delete_1 (tree base, tree maxindex, tree type,
TREE_SIDE_EFFECTS (controller) = 1;
body = build1 (EXIT_EXPR, void_type_node,
- build2 (EQ_EXPR, boolean_type_node, base, tbase));
+ build2 (EQ_EXPR, boolean_type_node, tbase,
+ fold_convert (ptype, base)));
body = build_compound_expr
(body, build_modify_expr (tbase, NOP_EXPR,
build2 (MINUS_EXPR, ptype, tbase, size_exp)));
}
if (auto_delete_vec == sfk_deleting_destructor)
- deallocate_expr = build_x_delete (base_tbd,
- 2 | use_global_delete,
- virtual_size);
+ deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
+ base_tbd, virtual_size,
+ use_global_delete & 1,
+ /*placement=*/NULL_TREE,
+ /*alloc_fn=*/NULL_TREE);
}
body = loop;
but use assignment instead of initialization. */
tree
-build_vec_init (tree base, tree maxindex, tree init,
+build_vec_init (tree base, tree maxindex, tree init,
bool explicit_default_init_p,
int from_array)
{
When copying from array to another, when the array elements have
only trivial copy constructors, we should use __builtin_memcpy
rather than generating a loop. That way, we could take advantage
- of whatever cleverness the back-end has for dealing with copies
+ of whatever cleverness the back end has for dealing with copies
of blocks of memory. */
is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
for_stmt = begin_for_stmt ();
finish_for_init_stmt (for_stmt);
- finish_for_cond (build2 (NE_EXPR, boolean_type_node,
- iterator, integer_minus_one_node),
+ finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
+ build_int_cst (TREE_TYPE (iterator), -1)),
for_stmt);
finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0),
for_stmt);
sorry
("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
- 0, 0,
+ 0, 0,
/*explicit_default_init_p=*/false,
0);
}
else if (!TYPE_NEEDS_CONSTRUCTING (type))
- elt_init = (build_modify_expr
+ elt_init = (build_modify_expr
(to, INIT_EXPR,
build_zero_init (type, size_one_node,
/*static_storage_p=*/false)));
return stmt_expr;
}
-/* Free up storage of type TYPE, at address ADDR.
-
- TYPE is a POINTER_TYPE and can be ptr_type_node for no special type
- of pointer.
-
- VIRTUAL_SIZE is the amount of storage that was allocated, and is
- used as the second argument to operator delete. It can include
- things like padding and magic size cookies. It has virtual in it,
- because if you have a base pointer and you delete through a virtual
- destructor, it should be the size of the dynamic object, not the
- static object, see Free Store 12.5 ISO C++.
-
- This does not call any destructors. */
-
-tree
-build_x_delete (tree addr, int which_delete, tree virtual_size)
-{
- int use_global_delete = which_delete & 1;
- int use_vec_delete = !!(which_delete & 2);
- enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
-
- return build_op_delete_call (code, addr, virtual_size, use_global_delete,
- NULL_TREE);
-}
-
/* Call the DTOR_KIND destructor for EXP. FLAGS are as for
build_delete. */
return build_new_method_call (exp, fn,
/*args=*/NULL_TREE,
/*conversion_path=*/NULL_TREE,
- flags);
+ flags,
+ /*fn_p=*/NULL);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
if (auto_delete != sfk_deleting_destructor)
return void_zero_node;
- return build_op_delete_call
- (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), use_global_delete,
- NULL_TREE);
+ return build_op_delete_call (DELETE_EXPR, addr,
+ cxx_sizeof_nowarn (type),
+ use_global_delete,
+ /*placement=*/NULL_TREE,
+ /*alloc_fn=*/NULL_TREE);
}
else
{
addr,
cxx_sizeof_nowarn (type),
/*global_p=*/false,
- NULL_TREE);
+ /*placement=*/NULL_TREE,
+ /*alloc_fn=*/NULL_TREE);
/* Call the complete object destructor. */
auto_delete = sfk_complete_destructor;
}
/* Make sure we have access to the member op delete, even though
we'll actually be calling it from the destructor. */
build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
- /*global_p=*/false, NULL_TREE);
+ /*global_p=*/false,
+ /*placement=*/NULL_TREE,
+ /*alloc_fn=*/NULL_TREE);
}
expr = build_dtor_call (build_indirect_ref (addr, NULL),
for (member = TYPE_FIELDS (current_class_type); member;
member = TREE_CHAIN (member))
{
- if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
+ if (TREE_TYPE (member) == error_mark_node
+ || TREE_CODE (member) != FIELD_DECL
+ || DECL_ARTIFICIAL (member))
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{