* tree.h (TYPE_ALIGN_UNIT): New macro.
From-SVN: r32302
This commit is contained in:
parent
a2b10a92a3
commit
834c6dff7b
@ -1,3 +1,7 @@
|
||||
2000-03-02 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* tree.h (TYPE_ALIGN_UNIT): New macro.
|
||||
|
||||
2000-03-02 Clinton Popetz <cpopetz@cygnus.com>
|
||||
|
||||
* config/i386/i386.c: (constant_call_address_operand): Reject
|
||||
|
@ -1,3 +1,64 @@
|
||||
2000-03-02 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (TYPE_NEEDS_DESTRUCTOR): Rename to ...
|
||||
(TYPE_HAS_NONTRIVIAL_DESTRUCTOR): ... this.
|
||||
(TYPE_HAS_TRIVIAL_DESTRUCTOR): New macro.
|
||||
(lang_type): Split gets_new into has_new and has_array_new.
|
||||
(TYPE_VEC_NEW_USES_COOKIE): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
|
||||
(TYPE_GETS_NEW): Split into ...
|
||||
(TYPE_HAS_NEW_OPERATOR): ... this, and ...
|
||||
(TYPE_HAS_ARRAY_NEW_OPERATOR): ... this.
|
||||
(DECL_ARRAY_DELETE_OPERATOR_P): New macro
|
||||
(build_op_new_call): Don't declare.
|
||||
(build_new_1): Likewise.
|
||||
* call.c (build_op_new_call): Remove.
|
||||
* class.c (check_bases): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR
|
||||
instead of TYPE_NEEDS_DESTRUCTOR.
|
||||
(finish_struct_bits): Likewise.
|
||||
(add_implicitly_declared_members): Likewise.
|
||||
(check_field_decl): Likewise.
|
||||
(check_methods): Set TYPE_VEC_DELETE_TAKES_SIZE here, and set it
|
||||
correctly under the new ABI.
|
||||
* decl.c (start_decl_1): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR
|
||||
instead of TYPE_NEEDS_DESTRUCTOR.
|
||||
(initialize_local_var): Likewise.
|
||||
(destroy_local_var): Likewise.
|
||||
(cp_finish_decl): Likewise.
|
||||
(register_dtor_fn): Likewise.
|
||||
(grok_op_properties): Set TYPE_HAS_NEW_OPERATOR and
|
||||
TYPE_HAS_ARRAY_NEW_OPERATOR, not TYPE_HAS_NEW. Don't set
|
||||
TYPE_VEC_DELETE_TAKES_SIZE here.
|
||||
(xref_basetypes): Set TYPE_HAS_NEW_OPERATOR and
|
||||
TYPE_HAS_ARRAY_NEW_OPERATOR, not TYPE_HAS_NEW.
|
||||
(store_parm_decls): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
|
||||
(finish_destructor_body): Likewise.
|
||||
(maybe_build_cleanup_1): Likewise.
|
||||
* decl2.c (do_static_destruction): Likewise.
|
||||
* init.c (build_new_1): Make it static.
|
||||
(perform_member_init): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
|
||||
(expand_cleanup_for_base): Likewise.
|
||||
(get_cookie_size): New function.
|
||||
(build_new_1): Handle array-new cookies correctly under the new
|
||||
ABI.
|
||||
(build_vec_delete_1): Likewise.
|
||||
(build_vec_init): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
|
||||
(build_delete): Likewise.
|
||||
(build_vec_delete): Handle array-new cookies correctly under the new
|
||||
ABI.
|
||||
* lex.c (do_identifier): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
|
||||
* pt.c (instantiate_class_template): Set TYPE_HAS_NEW_OPERATOR and
|
||||
TYPE_HAS_ARRAY_NEW_OPERATOR.
|
||||
* ptree.c (print_lang_type): Check them.
|
||||
* search.c (context_for_name_lookup): Fix typo in comment.
|
||||
(tree_has_any_destructor_p): Use TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
|
||||
* tree.c (break_out_cleanups): Likewise.
|
||||
(build_cplus_array_test_1): Likewise.
|
||||
(cp_build_qualified_type_real): Likewise.
|
||||
* typeck.c (complete_type): Likewise.
|
||||
|
||||
* g++spec.c (lang_specific_driver): Add -fnew-abi at the start of
|
||||
the command-line, not the end.
|
||||
|
||||
2000-03-01 Jason Merrill <jason@casey.cygnus.com>
|
||||
|
||||
* pt.c (instantiate_decl): Clear TI_PENDING_TEMPLATE_FLAG.
|
||||
|
@ -3452,31 +3452,6 @@ builtin:
|
||||
}
|
||||
}
|
||||
|
||||
/* Build up a call to operator new. This has to be handled differently
|
||||
from other operators in the way lookup is handled; first members are
|
||||
considered, then globals. CODE is either NEW_EXPR or VEC_NEW_EXPR.
|
||||
TYPE is the type to be created. ARGS are any new-placement args.
|
||||
FLAGS are the usual overloading flags. */
|
||||
|
||||
tree
|
||||
build_op_new_call (code, type, args, flags)
|
||||
enum tree_code code;
|
||||
tree type, args;
|
||||
int flags;
|
||||
{
|
||||
tree fnname = ansi_opname[code];
|
||||
|
||||
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
|
||||
&& (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
|
||||
{
|
||||
return build_method_call (build_dummy_object (type),
|
||||
fnname, args, NULL_TREE, flags);
|
||||
}
|
||||
else
|
||||
return build_new_function_call
|
||||
(lookup_function_nonclass (fnname, args), args);
|
||||
}
|
||||
|
||||
/* Build a call to operator delete. This has to be handled very specially,
|
||||
because the restrictions on what signatures match are different from all
|
||||
other call instances. For a normal delete, only a delete taking (void *)
|
||||
|
@ -1934,7 +1934,8 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
|
||||
/* A lot of properties from the bases also apply to the derived
|
||||
class. */
|
||||
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
|
||||
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype);
|
||||
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|
||||
|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
|
||||
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
|
||||
@ -2079,7 +2080,8 @@ finish_struct_bits (t)
|
||||
TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
|
||||
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
|
||||
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
|
||||
TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
|
||||
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
|
||||
|
||||
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants)
|
||||
= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
|
||||
@ -3503,14 +3505,14 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
||||
tree *f;
|
||||
|
||||
/* Destructor. */
|
||||
if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
|
||||
{
|
||||
default_fn = cons_up_default_function (t, name, 0);
|
||||
check_for_override (default_fn, t);
|
||||
|
||||
/* If we couldn't make it work, then pretend we didn't need it. */
|
||||
if (default_fn == void_type_node)
|
||||
TYPE_NEEDS_DESTRUCTOR (t) = 0;
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 0;
|
||||
else
|
||||
{
|
||||
TREE_CHAIN (default_fn) = implicit_fns;
|
||||
@ -3520,7 +3522,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
||||
virtual_dtor = default_fn;
|
||||
}
|
||||
}
|
||||
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
|
||||
else
|
||||
/* Any non-implicit destructor is non-trivial. */
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
|
||||
|
||||
/* Default constructor. */
|
||||
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
|
||||
@ -3744,7 +3748,7 @@ check_field_decl (field, t, cant_have_const_ctor,
|
||||
if (TYPE_NEEDS_CONSTRUCTING (type))
|
||||
cp_error_at ("member `%#D' with constructor not allowed in union",
|
||||
field);
|
||||
if (TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
cp_error_at ("member `%#D' with destructor not allowed in union",
|
||||
field);
|
||||
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
|
||||
@ -3754,7 +3758,8 @@ check_field_decl (field, t, cant_have_const_ctor,
|
||||
else
|
||||
{
|
||||
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
|
||||
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
|
||||
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
|
||||
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
|
||||
}
|
||||
@ -4268,6 +4273,7 @@ check_methods (t)
|
||||
tree t;
|
||||
{
|
||||
tree x;
|
||||
int seen_one_arg_array_delete_p = 0;
|
||||
|
||||
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
|
||||
{
|
||||
@ -4291,6 +4297,37 @@ check_methods (t)
|
||||
CLASSTYPE_PURE_VIRTUALS (t)
|
||||
= tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
|
||||
}
|
||||
|
||||
if (DECL_ARRAY_DELETE_OPERATOR_P (x))
|
||||
{
|
||||
tree second_parm;
|
||||
|
||||
/* When dynamically allocating an array of this type, we
|
||||
need a "cookie" to record how many elements we allocated,
|
||||
even if the array elements have no non-trivial
|
||||
destructor, if the usual array deallocation function
|
||||
takes a second argument of type size_t. The standard (in
|
||||
[class.free]) requires that the second argument be set
|
||||
correctly. */
|
||||
second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (x)));
|
||||
/* This is overly conservative, but we must maintain this
|
||||
behavior for backwards compatibility. */
|
||||
if (!flag_new_abi && second_parm != void_list_node)
|
||||
TYPE_VEC_DELETE_TAKES_SIZE (t) = 1;
|
||||
/* Under the new ABI, we choose only those function that are
|
||||
explicitly declared as `operator delete[] (void *,
|
||||
size_t)'. */
|
||||
else if (flag_new_abi
|
||||
&& !seen_one_arg_array_delete_p
|
||||
&& second_parm
|
||||
&& TREE_CHAIN (second_parm) == void_list_node
|
||||
&& same_type_p (TREE_VALUE (second_parm), sizetype))
|
||||
TYPE_VEC_DELETE_TAKES_SIZE (t) = 1;
|
||||
/* If there's no second parameter, then this is the usual
|
||||
deallocation function. */
|
||||
else if (second_parm == void_list_node)
|
||||
seen_one_arg_array_delete_p = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ Boston, MA 02111-1307, USA. */
|
||||
1: TYPE_HAS_CONSTRUCTOR.
|
||||
2: TYPE_HAS_DESTRUCTOR.
|
||||
3: TYPE_FOR_JAVA.
|
||||
4: TYPE_NEEDS_DESTRUCTOR.
|
||||
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
|
||||
5: IS_AGGR_TYPE.
|
||||
6: TYPE_BUILT_IN.
|
||||
|
||||
@ -1310,7 +1310,8 @@ struct lang_type
|
||||
unsigned has_nonpublic_assign_ref : 2;
|
||||
unsigned vtable_needs_writing : 1;
|
||||
unsigned has_assign_ref : 1;
|
||||
unsigned gets_new : 2;
|
||||
unsigned has_new : 1;
|
||||
unsigned has_array_new : 1;
|
||||
|
||||
unsigned gets_delete : 2;
|
||||
unsigned has_call_overloaded : 1;
|
||||
@ -1391,9 +1392,7 @@ struct lang_type
|
||||
/* List of friends which were defined inline in this class definition. */
|
||||
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
|
||||
|
||||
/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
|
||||
respectively. */
|
||||
#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_new)
|
||||
/* Nonzero for _CLASSTYPE means that operator delete is defined. */
|
||||
#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_delete)
|
||||
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
|
||||
|
||||
@ -1401,9 +1400,15 @@ struct lang_type
|
||||
takes the optional size_t argument. */
|
||||
#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \
|
||||
(TYPE_LANG_SPECIFIC(NODE)->vec_delete_takes_size)
|
||||
#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
|
||||
(TYPE_NEEDS_DESTRUCTOR (NODE) \
|
||||
|| (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
|
||||
|
||||
/* Nonzero if `new NODE[x]' should cause the allocation of extra
|
||||
storage to indicate how many array elements are in use. The old
|
||||
ABI had a bug in that we always allocate the extra storage if NODE
|
||||
has a two-argument array operator delete. */
|
||||
#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
|
||||
(TYPE_HAS_NONTRIVIAL_DESTRUCTOR (NODE) \
|
||||
|| (TYPE_LANG_SPECIFIC (NODE) \
|
||||
&& TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
|
||||
|
||||
/* Nonzero means that this _CLASSTYPE node defines ways of converting
|
||||
itself to other types. */
|
||||
@ -1417,6 +1422,15 @@ struct lang_type
|
||||
#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_init_ref)
|
||||
#define TYPE_HAS_CONST_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_const_init_ref)
|
||||
|
||||
/* Nonzero if this class defines an overloaded operator new. (An
|
||||
operator new [] doesn't count.) */
|
||||
#define TYPE_HAS_NEW_OPERATOR(NODE) \
|
||||
(TYPE_LANG_SPECIFIC (NODE)->has_new)
|
||||
|
||||
/* Nonzero if this class defines an overloaded operator new[]. */
|
||||
#define TYPE_HAS_ARRAY_NEW_OPERATOR(NODE) \
|
||||
(TYPE_LANG_SPECIFIC (NODE)->has_array_new)
|
||||
|
||||
/* Nonzero means that this type is being defined. I.e., the left brace
|
||||
starting the definition of this type has been seen. */
|
||||
#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->being_defined)
|
||||
@ -1916,6 +1930,10 @@ struct lang_decl
|
||||
#define SET_DECL_TINFO_FN_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC((NODE))->decl_flags.mutable_flag = 1)
|
||||
|
||||
/* Nonzero if NODE is an overloaded `operator delete[]' function. */
|
||||
#define DECL_ARRAY_DELETE_OPERATOR_P(NODE) \
|
||||
(DECL_NAME (NODE) == ansi_opname[(int) VEC_DELETE_EXPR])
|
||||
|
||||
/* Nonzero for _DECL means that this decl appears in (or will appear
|
||||
in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for
|
||||
detecting circularity in case members are multiply defined. In the
|
||||
@ -2410,10 +2428,26 @@ extern int flag_new_for_scope;
|
||||
#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_abstract_assign_ref)
|
||||
#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_complex_init_ref)
|
||||
|
||||
/* Nonzero for _TYPE node means that destroying an object of this type
|
||||
will involve a call to a destructor. This can apply to objects
|
||||
of ARRAY_TYPE is the type of the elements needs a destructor. */
|
||||
#define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE))
|
||||
/* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
|
||||
|
||||
A destructor is trivial if it is an implicitly declared
|
||||
destructor and if:
|
||||
|
||||
- all of the direct base classes of its class have trivial
|
||||
destructors,
|
||||
|
||||
- for all of the non-static data members of its class that are
|
||||
of class type (or array thereof), each such class has a
|
||||
trivial destructor. */
|
||||
#define TYPE_HAS_TRIVIAL_DESTRUCTOR(NODE) \
|
||||
(!TYPE_HAS_NONTRIVIAL_DESTRUCTOR (NODE))
|
||||
|
||||
/* Nonzero for _TYPE node means that this type does not have a trivial
|
||||
destructor. Therefore, destroying an object of this type will
|
||||
involve a call to a destructor. This can apply to objects of
|
||||
ARRAY_TYPE is the type of the elements needs a destructor. */
|
||||
#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
|
||||
(TYPE_LANG_FLAG_4(NODE))
|
||||
|
||||
/* Nonzero for class type means that initialization of this type can use
|
||||
a bitwise copy. */
|
||||
@ -3578,7 +3612,6 @@ extern tree type_decays_to PARAMS ((tree));
|
||||
extern tree build_user_type_conversion PARAMS ((tree, tree, int));
|
||||
extern tree build_new_function_call PARAMS ((tree, tree));
|
||||
extern tree build_new_op PARAMS ((enum tree_code, int, tree, tree, tree));
|
||||
extern tree build_op_new_call PARAMS ((enum tree_code, tree, tree, int));
|
||||
extern tree build_op_delete_call PARAMS ((enum tree_code, tree, tree, int, tree));
|
||||
extern int can_convert PARAMS ((tree, tree));
|
||||
extern int can_convert_arg PARAMS ((tree, tree, tree));
|
||||
@ -3922,7 +3955,6 @@ extern tree build_offset_ref PARAMS ((tree, tree));
|
||||
extern tree resolve_offset_ref PARAMS ((tree));
|
||||
extern tree decl_constant_value PARAMS ((tree));
|
||||
extern tree build_new PARAMS ((tree, tree, tree, int));
|
||||
extern tree build_new_1 PARAMS ((tree));
|
||||
extern tree build_vec_init PARAMS ((tree, tree, tree, tree, int));
|
||||
extern tree build_x_delete PARAMS ((tree, int, tree));
|
||||
extern tree build_delete PARAMS ((tree, tree, tree, int, int));
|
||||
|
@ -6844,7 +6844,7 @@ start_decl_1 (decl)
|
||||
/* If this type of object needs a cleanup, but we're not allowed to
|
||||
add any more objects with cleanups to the current scope, create a
|
||||
new binding level. */
|
||||
if (TYPE_NEEDS_DESTRUCTOR (type)
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|
||||
&& current_binding_level->more_cleanups_ok == 0)
|
||||
{
|
||||
keep_next_level (2);
|
||||
@ -7490,7 +7490,7 @@ initialize_local_var (decl, init, flags)
|
||||
if (TREE_STATIC (decl))
|
||||
{
|
||||
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|
||||
|| TYPE_NEEDS_DESTRUCTOR (type))
|
||||
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
expand_static_init (decl, init);
|
||||
return;
|
||||
}
|
||||
@ -7522,7 +7522,7 @@ initialize_local_var (decl, init, flags)
|
||||
marked used. (see TREE_USED, above.) */
|
||||
if (TYPE_NEEDS_CONSTRUCTING (type)
|
||||
&& ! already_used
|
||||
&& !TYPE_NEEDS_DESTRUCTOR (type)
|
||||
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
|
||||
&& DECL_NAME (decl))
|
||||
TREE_USED (decl) = 0;
|
||||
else if (already_used)
|
||||
@ -7544,7 +7544,7 @@ destroy_local_var (decl)
|
||||
return;
|
||||
|
||||
/* And only things with destructors need cleaning up. */
|
||||
if (!TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
|
||||
return;
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL &&
|
||||
@ -7820,7 +7820,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
|
||||
{
|
||||
/* Cleanups for static variables are handled by `finish_file'. */
|
||||
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|
||||
|| TYPE_NEEDS_DESTRUCTOR (type))
|
||||
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
expand_static_init (decl, init);
|
||||
}
|
||||
finish_end0:
|
||||
@ -8054,7 +8054,7 @@ register_dtor_fn (decl)
|
||||
|
||||
int saved_flag_access_control;
|
||||
|
||||
if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
|
||||
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
|
||||
return;
|
||||
|
||||
/* Call build_cleanup before we enter the anonymous function so that
|
||||
@ -11856,11 +11856,11 @@ grok_op_properties (decl, virtualp, friendp)
|
||||
|| name == ansi_opname[(int) MEMBER_REF])
|
||||
TYPE_OVERLOADS_ARROW (current_class_type) = 1;
|
||||
else if (name == ansi_opname[(int) NEW_EXPR])
|
||||
TYPE_GETS_NEW (current_class_type) |= 1;
|
||||
TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
|
||||
else if (name == ansi_opname[(int) DELETE_EXPR])
|
||||
TYPE_GETS_DELETE (current_class_type) |= 1;
|
||||
else if (name == ansi_opname[(int) VEC_NEW_EXPR])
|
||||
TYPE_GETS_NEW (current_class_type) |= 2;
|
||||
TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
|
||||
else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
|
||||
TYPE_GETS_DELETE (current_class_type) |= 2;
|
||||
}
|
||||
@ -11894,14 +11894,7 @@ grok_op_properties (decl, virtualp, friendp)
|
||||
hash_tree_chain (ptr_type_node,
|
||||
void_list_node));
|
||||
else
|
||||
{
|
||||
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
|
||||
|
||||
if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR]
|
||||
&& (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
|
||||
!= void_list_node))
|
||||
TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1;
|
||||
}
|
||||
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -12508,7 +12501,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
|
||||
|
||||
if (CLASS_TYPE_P (basetype))
|
||||
{
|
||||
TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
|
||||
TYPE_HAS_NEW_OPERATOR (ref)
|
||||
|= TYPE_HAS_NEW_OPERATOR (basetype);
|
||||
TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
|
||||
|= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
|
||||
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
|
||||
/* If the base-class uses multiple inheritance, so do we. */
|
||||
TYPE_USES_MULTIPLE_INHERITANCE (ref)
|
||||
@ -13387,7 +13383,7 @@ store_parm_decls ()
|
||||
cleanups = tree_cons (parm, cleanup, cleanups);
|
||||
}
|
||||
else if (type != error_mark_node
|
||||
&& TYPE_NEEDS_DESTRUCTOR (type))
|
||||
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
parms_have_cleanups = 1;
|
||||
}
|
||||
else
|
||||
@ -13603,7 +13599,7 @@ finish_destructor_body ()
|
||||
|
||||
while (vbases)
|
||||
{
|
||||
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbases)))
|
||||
{
|
||||
tree vb = get_vbase
|
||||
(BINFO_TYPE (vbases),
|
||||
@ -14286,7 +14282,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
|
||||
tree decl, auto_delete;
|
||||
{
|
||||
tree type = TREE_TYPE (decl);
|
||||
if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
|
||||
tree rval;
|
||||
|
@ -3238,7 +3238,7 @@ do_static_destruction (decl)
|
||||
my_friendly_assert (!flag_use_cxa_atexit, 20000121);
|
||||
|
||||
/* If we don't need a destructor, there's nothing to do. */
|
||||
if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
|
||||
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
|
||||
return;
|
||||
|
||||
/* Actually do the destruction. */
|
||||
|
@ -206,8 +206,21 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
|
||||
real_arglist = (char **) xmalloc (num_args * sizeof (char *));
|
||||
arglist = (const char **) real_arglist;
|
||||
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
/* Copy the 0th argument, i.e., the name of the program itself. */
|
||||
arglist[i++] = arglist[j++];
|
||||
|
||||
#if ENABLE_NEW_GXX_ABI
|
||||
/* If we should use the new ABI by default, add the appropriate flag
|
||||
to cc1plus here. We put this first so that it can be overridden
|
||||
by other command-line options. */
|
||||
arglist[j++] = "-fnew-abi";
|
||||
#endif
|
||||
|
||||
/* NOTE: We start at 1 now, not 0. */
|
||||
for (i = 0, j = 0; i < argc; i++, j++)
|
||||
while (i < argc)
|
||||
{
|
||||
arglist[j] = argv[i];
|
||||
|
||||
@ -237,11 +250,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
|
||||
arglist[j++] = argv[i];
|
||||
arglist[j] = "-xnone";
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_NEW_GXX_ABI
|
||||
arglist[j++] = "-fnew-abi";
|
||||
#endif
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Add `-lstdc++' if we haven't already done so. */
|
||||
if (library)
|
||||
|
224
gcc/cp/init.c
224
gcc/cp/init.c
@ -49,6 +49,8 @@ static tree initializing_context PARAMS ((tree));
|
||||
static void expand_cleanup_for_base PARAMS ((tree, tree));
|
||||
static tree get_temp_regvar PARAMS ((tree, tree));
|
||||
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
|
||||
static tree build_new_1 PARAMS ((tree));
|
||||
static tree get_cookie_size PARAMS ((tree));
|
||||
|
||||
/* Set up local variable for this file. MUST BE CALLED AFTER
|
||||
INIT_DECL_PROCESSING. */
|
||||
@ -225,7 +227,7 @@ perform_member_init (member, name, init, explicit)
|
||||
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
|
||||
}
|
||||
|
||||
if (TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
tree expr;
|
||||
|
||||
@ -701,7 +703,7 @@ expand_cleanup_for_base (binfo, flag)
|
||||
{
|
||||
tree expr;
|
||||
|
||||
if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
|
||||
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
|
||||
return;
|
||||
|
||||
/* Call the destructor. */
|
||||
@ -2101,10 +2103,40 @@ build_java_class_ref (type)
|
||||
return class_decl;
|
||||
}
|
||||
|
||||
/* Returns teh size of the cookie to use when allocating an array
|
||||
whose elements have the indicated TYPE. Assumes that it is already
|
||||
known that a cookie is needed. */
|
||||
|
||||
static tree
|
||||
get_cookie_size (type)
|
||||
tree type;
|
||||
{
|
||||
tree cookie_size;
|
||||
|
||||
if (flag_new_abi)
|
||||
{
|
||||
/* Under the new ABI, we need to allocate an additional max
|
||||
(sizeof (size_t), alignof (true_type)) bytes. */
|
||||
tree sizetype_size;
|
||||
tree type_align;
|
||||
|
||||
sizetype_size = size_in_bytes (sizetype);
|
||||
type_align = size_int (TYPE_ALIGN_UNIT (type));
|
||||
if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
|
||||
cookie_size = sizetype_size;
|
||||
else
|
||||
cookie_size = type_align;
|
||||
}
|
||||
else
|
||||
cookie_size = BI_header_size;
|
||||
|
||||
return cookie_size;
|
||||
}
|
||||
|
||||
/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
|
||||
value is immediately handed to expand_expr. */
|
||||
|
||||
tree
|
||||
static tree
|
||||
build_new_1 (exp)
|
||||
tree exp;
|
||||
{
|
||||
@ -2113,15 +2145,23 @@ build_new_1 (exp)
|
||||
tree nelts = NULL_TREE;
|
||||
tree alloc_expr, alloc_node = NULL_TREE;
|
||||
int has_array = 0;
|
||||
enum tree_code code = NEW_EXPR;
|
||||
enum tree_code code;
|
||||
int use_cookie, nothrow, check_new;
|
||||
/* Nonzero if the user wrote `::new' rather than just `new'. */
|
||||
int globally_qualified_p;
|
||||
/* Nonzero if we're going to call a global operator new, rather than
|
||||
a class-specific version. */
|
||||
int use_global_new;
|
||||
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
|
||||
order to store the number of elements. */
|
||||
tree cookie_size = NULL_TREE;
|
||||
|
||||
placement = TREE_OPERAND (exp, 0);
|
||||
type = TREE_OPERAND (exp, 1);
|
||||
init = TREE_OPERAND (exp, 2);
|
||||
use_global_new = NEW_EXPR_USE_GLOBAL (exp);
|
||||
globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_REF)
|
||||
{
|
||||
@ -2131,6 +2171,8 @@ build_new_1 (exp)
|
||||
}
|
||||
true_type = type;
|
||||
|
||||
code = has_array ? VEC_NEW_EXPR : NEW_EXPR;
|
||||
|
||||
if (CP_TYPE_QUALS (type))
|
||||
type = TYPE_MAIN_VARIANT (type);
|
||||
|
||||
@ -2161,32 +2203,44 @@ build_new_1 (exp)
|
||||
if (abstract_virtuals_error (NULL_TREE, true_type))
|
||||
return error_mark_node;
|
||||
|
||||
/* When we allocate an array, and the corresponding deallocation
|
||||
function takes a second argument of type size_t, and that's the
|
||||
"usual deallocation function", we allocate some extra space at
|
||||
the beginning of the array to store the size of the array.
|
||||
/* Figure out whether or not we're going to use the global operator
|
||||
new. */
|
||||
if (!globally_qualified_p
|
||||
&& IS_AGGR_TYPE (true_type)
|
||||
&& ((!has_array && TYPE_HAS_NEW_OPERATOR (true_type))
|
||||
|| (has_array && TYPE_HAS_ARRAY_NEW_OPERATOR (true_type))))
|
||||
use_global_new = 0;
|
||||
else
|
||||
use_global_new = 1;
|
||||
|
||||
Well, that's what we should do. For backwards compatibility, we
|
||||
have to do this whenever there's a two-argument array-delete
|
||||
operator.
|
||||
|
||||
FIXME: For -fnew-abi, we don't have to maintain backwards
|
||||
compatibility and we should fix this. */
|
||||
use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
|
||||
&& ! (placement && ! TREE_CHAIN (placement)
|
||||
&& TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
|
||||
/* We only need cookies for arrays containing types for which we
|
||||
need cookies. */
|
||||
if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
|
||||
use_cookie = 0;
|
||||
/* When using placement new, users may not realize that they need
|
||||
the extra storage. Under the old ABI, we don't allocate the
|
||||
cookie whenever they use one placement argument of type `void
|
||||
*'. Under the new ABI, we require that the operator called be
|
||||
the global placement operator delete[]. */
|
||||
else if (placement && !TREE_CHAIN (placement)
|
||||
&& same_type_p (TREE_TYPE (TREE_VALUE (placement)),
|
||||
ptr_type_node))
|
||||
use_cookie = (!flag_new_abi || !use_global_new);
|
||||
/* Otherwise, we need the cookie. */
|
||||
else
|
||||
use_cookie = 1;
|
||||
|
||||
/* Compute the number of extra bytes to allocate, now that we know
|
||||
whether or not we need the cookie. */
|
||||
if (use_cookie)
|
||||
size = size_binop (PLUS_EXPR, size, BI_header_size);
|
||||
|
||||
if (has_array)
|
||||
{
|
||||
code = VEC_NEW_EXPR;
|
||||
|
||||
if (init && pedantic)
|
||||
cp_pedwarn ("initialization in array new");
|
||||
cookie_size = get_cookie_size (true_type);
|
||||
size = size_binop (PLUS_EXPR, size, cookie_size);
|
||||
}
|
||||
|
||||
if (has_array && init && pedantic)
|
||||
cp_pedwarn ("initialization in array new");
|
||||
|
||||
/* Allocate the object. */
|
||||
|
||||
if (! placement && TYPE_FOR_JAVA (true_type))
|
||||
@ -2208,9 +2262,20 @@ build_new_1 (exp)
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = build_op_new_call
|
||||
(code, true_type, tree_cons (NULL_TREE, size, placement),
|
||||
LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
|
||||
tree fnname;
|
||||
tree args;
|
||||
|
||||
args = tree_cons (NULL_TREE, size, placement);
|
||||
fnname = ansi_opname[code];
|
||||
|
||||
if (use_global_new)
|
||||
rval = (build_new_function_call
|
||||
(lookup_function_nonclass (fnname, args),
|
||||
args));
|
||||
else
|
||||
rval = build_method_call (build_dummy_object (true_type),
|
||||
fnname, args, NULL_TREE,
|
||||
LOOKUP_NORMAL);
|
||||
rval = cp_convert (build_pointer_type (true_type), rval);
|
||||
}
|
||||
|
||||
@ -2249,18 +2314,36 @@ build_new_1 (exp)
|
||||
/* Finish up some magic for new'ed arrays */
|
||||
if (use_cookie && rval != NULL_TREE)
|
||||
{
|
||||
tree extra = BI_header_size;
|
||||
tree cookie, exp1;
|
||||
rval = convert (string_type_node, rval); /* for ptr arithmetic */
|
||||
rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra));
|
||||
/* Store header info. */
|
||||
cookie = build_indirect_ref (build (MINUS_EXPR,
|
||||
build_pointer_type (BI_header_type),
|
||||
rval, extra), NULL_PTR);
|
||||
exp1 = build (MODIFY_EXPR, void_type_node,
|
||||
build_component_ref (cookie, nelts_identifier,
|
||||
NULL_TREE, 0),
|
||||
nelts);
|
||||
rval = save_expr (build_binary_op (PLUS_EXPR, rval, cookie_size));
|
||||
/* Store the number of bytes allocated so that we can know how
|
||||
many elements to destroy later. */
|
||||
if (flag_new_abi)
|
||||
{
|
||||
/* Under the new ABI, we use the last sizeof (size_t) bytes
|
||||
to store the number of elements. */
|
||||
cookie = build_indirect_ref (build (MINUS_EXPR,
|
||||
build_pointer_type (sizetype),
|
||||
rval,
|
||||
size_in_bytes (sizetype)),
|
||||
NULL_PTR);
|
||||
exp1 = build (MODIFY_EXPR, void_type_node, cookie, nelts);
|
||||
}
|
||||
else
|
||||
{
|
||||
cookie
|
||||
= build_indirect_ref (build (MINUS_EXPR,
|
||||
build_pointer_type (BI_header_type),
|
||||
rval, cookie_size), NULL_PTR);
|
||||
exp1 = build (MODIFY_EXPR, void_type_node,
|
||||
build_component_ref (cookie, nelts_identifier,
|
||||
NULL_TREE, 0),
|
||||
nelts);
|
||||
}
|
||||
|
||||
/* Build `(cookie = nelts, rval)' and use that as the complete
|
||||
expression. */
|
||||
rval = cp_convert (build_pointer_type (true_type), rval);
|
||||
rval = build_compound_expr
|
||||
(tree_cons (NULL_TREE, exp1,
|
||||
@ -2372,7 +2455,8 @@ build_new_1 (exp)
|
||||
{
|
||||
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
|
||||
tree cleanup, fn = NULL_TREE;
|
||||
int flags = LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL);
|
||||
int flags = (LOOKUP_NORMAL
|
||||
| (globally_qualified_p * LOOKUP_GLOBAL));
|
||||
|
||||
/* The Standard is unclear here, but the right thing to do
|
||||
is to use the same method for finding deallocation
|
||||
@ -2475,7 +2559,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
|
||||
This is also the containing expression returned by this function. */
|
||||
tree controller = NULL_TREE;
|
||||
|
||||
if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (! IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
loop = integer_zero_node;
|
||||
goto no_destructor;
|
||||
@ -2534,12 +2618,16 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
|
||||
base_tbd = base;
|
||||
else
|
||||
{
|
||||
base_tbd = cp_convert (ptype,
|
||||
build_binary_op (MINUS_EXPR,
|
||||
cp_convert (string_type_node, base),
|
||||
BI_header_size));
|
||||
tree cookie_size;
|
||||
|
||||
cookie_size = get_cookie_size (type);
|
||||
base_tbd
|
||||
= cp_convert (ptype,
|
||||
build_binary_op (MINUS_EXPR,
|
||||
cp_convert (string_type_node, base),
|
||||
cookie_size));
|
||||
/* True size with header. */
|
||||
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
|
||||
virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size);
|
||||
}
|
||||
deallocate_expr = build_x_delete (base_tbd,
|
||||
2 | use_global_delete,
|
||||
@ -2708,7 +2796,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
|
||||
|
||||
/* Protect the entire array initialization so that we can destroy
|
||||
the partially constructed array if an exception is thrown. */
|
||||
if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
try_block = begin_try_block ();
|
||||
try_body = begin_compound_stmt (/*has_no_scope=*/1);
|
||||
@ -2893,7 +2981,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
|
||||
}
|
||||
|
||||
/* Make sure to cleanup any partially constructed elements. */
|
||||
if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
tree e;
|
||||
|
||||
@ -3029,7 +3117,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
||||
|
||||
my_friendly_assert (IS_AGGR_TYPE (type), 220);
|
||||
|
||||
if (! TYPE_NEEDS_DESTRUCTOR (type))
|
||||
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
|
||||
{
|
||||
if (auto_delete == integer_zero_node)
|
||||
return void_zero_node;
|
||||
@ -3105,7 +3193,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
||||
if (auto_delete == integer_zero_node)
|
||||
cond = NULL_TREE;
|
||||
else if (base_binfo == NULL_TREE
|
||||
|| ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
|
||||
|| TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
|
||||
{
|
||||
cond = build (COND_EXPR, void_type_node,
|
||||
build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
|
||||
@ -3120,7 +3208,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
||||
|
||||
if (base_binfo
|
||||
&& ! TREE_VIA_VIRTUAL (base_binfo)
|
||||
&& TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
|
||||
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
|
||||
{
|
||||
tree this_auto_delete;
|
||||
|
||||
@ -3139,7 +3227,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
||||
for (i = 1; i < n_baseclasses; i++)
|
||||
{
|
||||
base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
if (! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))
|
||||
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
|
||||
|| TREE_VIA_VIRTUAL (base_binfo))
|
||||
continue;
|
||||
|
||||
@ -3154,7 +3242,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
||||
{
|
||||
if (TREE_CODE (member) != FIELD_DECL)
|
||||
continue;
|
||||
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (member)))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
|
||||
{
|
||||
tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
|
||||
tree this_type = TREE_TYPE (member);
|
||||
@ -3234,20 +3322,34 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
|
||||
if (TREE_CODE (type) == POINTER_TYPE)
|
||||
{
|
||||
/* Step back one from start of vector, and read dimension. */
|
||||
tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
|
||||
base, BI_header_size);
|
||||
tree cookie = build_indirect_ref (cookie_addr, NULL_PTR);
|
||||
maxindex = build_component_ref (cookie, nelts_identifier, NULL_TREE, 0);
|
||||
do
|
||||
type = TREE_TYPE (type);
|
||||
while (TREE_CODE (type) == ARRAY_TYPE);
|
||||
tree cookie_addr;
|
||||
|
||||
if (flag_new_abi)
|
||||
{
|
||||
cookie_addr = build (MINUS_EXPR,
|
||||
build_pointer_type (sizetype),
|
||||
base,
|
||||
TYPE_SIZE_UNIT (sizetype));
|
||||
maxindex = build_indirect_ref (cookie_addr, NULL_PTR);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree cookie;
|
||||
|
||||
cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
|
||||
base, BI_header_size);
|
||||
cookie = build_indirect_ref (cookie_addr, NULL_PTR);
|
||||
maxindex = build_component_ref (cookie, nelts_identifier,
|
||||
NULL_TREE, 0);
|
||||
}
|
||||
|
||||
type = strip_array_types (TREE_TYPE (type));
|
||||
}
|
||||
else if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
/* get the total number of things in the array, maxindex is a bad name */
|
||||
maxindex = array_type_nelts_total (type);
|
||||
while (TREE_CODE (type) == ARRAY_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
type = strip_array_types (type);
|
||||
base = build_unary_op (ADDR_EXPR, base, 1);
|
||||
}
|
||||
else
|
||||
|
@ -3147,7 +3147,7 @@ do_identifier (token, parsing, args)
|
||||
else if (!DECL_ERROR_REPORTED (id))
|
||||
{
|
||||
DECL_ERROR_REPORTED (id) = 1;
|
||||
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (id)))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (id)))
|
||||
{
|
||||
error ("name lookup of `%s' changed for new ISO `for' scoping",
|
||||
IDENTIFIER_POINTER (token));
|
||||
|
@ -4830,7 +4830,8 @@ instantiate_class_template (type)
|
||||
TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
|
||||
TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
|
||||
TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
|
||||
TYPE_GETS_NEW (type) = TYPE_GETS_NEW (pattern);
|
||||
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
|
||||
TYPE_HAS_ARRAY_NEW_OPERATOR (type) = TYPE_HAS_ARRAY_NEW_OPERATOR (pattern);
|
||||
TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
|
||||
TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
|
||||
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
|
||||
|
@ -113,7 +113,7 @@ print_lang_type (file, node, indent)
|
||||
|
||||
if (TYPE_NEEDS_CONSTRUCTING (node))
|
||||
fputs ( "needs-constructor", file);
|
||||
if (TYPE_NEEDS_DESTRUCTOR (node))
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
|
||||
fputs (" needs-destructor", file);
|
||||
if (TYPE_HAS_DESTRUCTOR (node))
|
||||
fputs (" ~X()", file);
|
||||
@ -128,9 +128,9 @@ print_lang_type (file, node, indent)
|
||||
else
|
||||
fputs (" X(X&)", file);
|
||||
}
|
||||
if (TYPE_GETS_NEW (node) & 1)
|
||||
if (TYPE_HAS_NEW_OPERATOR (node))
|
||||
fputs (" new", file);
|
||||
if (TYPE_GETS_NEW (node) & 2)
|
||||
if (TYPE_HAS_ARRAY_NEW_OPERATOR (node))
|
||||
fputs (" new[]", file);
|
||||
if (TYPE_GETS_DELETE (node) & 1)
|
||||
fputs (" delete", file);
|
||||
|
@ -725,7 +725,7 @@ context_for_name_lookup (decl)
|
||||
|
||||
For the purposes of name lookup, after the anonymous union
|
||||
definition, the members of the anonymous union are considered to
|
||||
have been defined in the scope in which teh anonymous union is
|
||||
have been defined in the scope in which the anonymous union is
|
||||
declared. */
|
||||
tree context = CP_DECL_CONTEXT (decl);
|
||||
|
||||
@ -1955,7 +1955,7 @@ tree_has_any_destructor_p (binfo, data)
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
tree type = BINFO_TYPE (binfo);
|
||||
return TYPE_NEEDS_DESTRUCTOR (type) ? binfo : NULL_TREE;
|
||||
return TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) ? binfo : NULL_TREE;
|
||||
}
|
||||
|
||||
/* Returns > 0 if a function with type DRETTYPE overriding a function
|
||||
|
@ -322,7 +322,7 @@ break_out_cleanups (exp)
|
||||
tree tmp = exp;
|
||||
|
||||
if (TREE_CODE (tmp) == CALL_EXPR
|
||||
&& TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
|
||||
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (tmp)))
|
||||
return build_cplus_new (TREE_TYPE (tmp), tmp);
|
||||
|
||||
while (TREE_CODE (tmp) == NOP_EXPR
|
||||
@ -330,7 +330,7 @@ break_out_cleanups (exp)
|
||||
|| TREE_CODE (tmp) == NON_LVALUE_EXPR)
|
||||
{
|
||||
if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR
|
||||
&& TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
|
||||
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
|
||||
{
|
||||
TREE_OPERAND (tmp, 0)
|
||||
= build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
|
||||
@ -505,8 +505,8 @@ build_cplus_array_type_1 (elt_type, index_type)
|
||||
more easily. */
|
||||
TYPE_NEEDS_CONSTRUCTING (t)
|
||||
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
|
||||
TYPE_NEEDS_DESTRUCTOR (t)
|
||||
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ cp_build_qualified_type_real (type, type_quals, complain)
|
||||
}
|
||||
|
||||
/* Even if we already had this variant, we update
|
||||
TYPE_NEEDS_CONSTRUCTING and TYPE_NEEDS_DESTRUCTOR in case
|
||||
TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
|
||||
they changed since the variant was originally created.
|
||||
|
||||
This seems hokey; if there is some way to use a previous
|
||||
@ -610,8 +610,8 @@ cp_build_qualified_type_real (type, type_quals, complain)
|
||||
TYPE_NEEDS_CONSTRUCTING will never be updated. */
|
||||
TYPE_NEEDS_CONSTRUCTING (t)
|
||||
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
|
||||
TYPE_NEEDS_DESTRUCTOR (t)
|
||||
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
|
||||
return t;
|
||||
}
|
||||
else if (TYPE_PTRMEMFUNC_P (type))
|
||||
|
@ -155,8 +155,8 @@ complete_type (type)
|
||||
layout_type (type);
|
||||
TYPE_NEEDS_CONSTRUCTING (type)
|
||||
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
|
||||
TYPE_NEEDS_DESTRUCTOR (type)
|
||||
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
|
||||
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|
||||
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
|
||||
}
|
||||
else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
|
||||
instantiate_class_template (TYPE_MAIN_VARIANT (type));
|
||||
|
127
gcc/testsuite/g++.old-deja/g++.abi/arraynew.C
Normal file
127
gcc/testsuite/g++.old-deja/g++.abi/arraynew.C
Normal file
@ -0,0 +1,127 @@
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
|
||||
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
extern "C" int printf (const char*, ...);
|
||||
|
||||
void* p;
|
||||
|
||||
void* operator new[](size_t s) throw (bad_alloc)
|
||||
{
|
||||
// Record the base of the last array allocated.
|
||||
p = malloc (s);
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void check_no_cookie (int i)
|
||||
{
|
||||
void* a = new T[7];
|
||||
if (p != a)
|
||||
exit (i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void check_no_placement_cookie (int i)
|
||||
{
|
||||
p = malloc (13 * sizeof (T));
|
||||
void* a = new (p) T[13];
|
||||
if (p != a)
|
||||
exit (i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void check_cookie (int i)
|
||||
{
|
||||
void* a = new T[11];
|
||||
|
||||
// Compute the cookie location manually.
|
||||
size_t x = __alignof__ (T);
|
||||
if (x < sizeof (size_t))
|
||||
x = sizeof (size_t);
|
||||
if ((char *) a - x != (char *) p)
|
||||
exit (i);
|
||||
|
||||
// Check the cookie value.
|
||||
size_t *sp = ((size_t *) a) - 1;
|
||||
if (*sp != 11)
|
||||
exit (i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void check_placement_cookie (int i)
|
||||
{
|
||||
p = malloc (sizeof (T) * 11 + 100);
|
||||
void* a = new (p) T[11];
|
||||
|
||||
printf ("%x %x\n", a, p);
|
||||
// Compute the cookie location manually.
|
||||
size_t x = __alignof__ (T);
|
||||
if (x < sizeof (size_t))
|
||||
x = sizeof (size_t);
|
||||
if ((char *) a - x != (char *) p)
|
||||
exit (i);
|
||||
|
||||
// Check the cookie value.
|
||||
size_t *sp = ((size_t *) a) - 1;
|
||||
if (*sp != 11)
|
||||
exit (i);
|
||||
}
|
||||
|
||||
struct X {};
|
||||
|
||||
template <typename T>
|
||||
struct Y { int i; virtual void f () {}; };
|
||||
|
||||
// A class with a non-trivial destructor -- it needs a cookie.
|
||||
struct Z { ~Z () {}; };
|
||||
// Likewise, but this class needs a bigger cookie so that the array
|
||||
// elements are correctly aligned.
|
||||
struct Z2 { ~Z2 () {}; long double d; };
|
||||
|
||||
struct W1 { void operator delete[] (void *, size_t) {}; };
|
||||
struct W2 { void operator delete[] (void *) {};
|
||||
void operator delete[] (void *, size_t) {}; };
|
||||
|
||||
struct V { void *operator new[] (size_t s, void *p)
|
||||
{ return p; }
|
||||
~V () {}
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
// There should be no cookies for types with trivial destructors.
|
||||
check_no_cookie<int> (1);
|
||||
check_no_cookie<X> (2);
|
||||
check_no_cookie<Y<double> > (3);
|
||||
|
||||
// There should be no cookies for allocations using global placement
|
||||
// new.
|
||||
check_no_placement_cookie<int> (4);
|
||||
check_no_placement_cookie<X> (5);
|
||||
check_no_placement_cookie<Z> (6);
|
||||
|
||||
// There should be a cookie when using a non-trivial destructor.
|
||||
check_cookie<Z> (7);
|
||||
check_cookie<Z2> (8);
|
||||
|
||||
// There should be a cookie when using the two-argument array delete
|
||||
// operator.
|
||||
check_cookie<W1> (9);
|
||||
// But not when the one-argument version is also available.
|
||||
check_no_cookie<W2> (10);
|
||||
|
||||
// There should be a cookie when using a non-global placement new.
|
||||
check_placement_cookie<V> (11);
|
||||
}
|
||||
|
||||
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
|
||||
|
||||
int main ()
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
|
@ -1,4 +1,5 @@
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
// Special g++ Options: -O2
|
||||
|
||||
#include <list>
|
||||
|
||||
|
@ -880,6 +880,10 @@ struct tree_block
|
||||
The value is an int, measured in bits. */
|
||||
#define TYPE_ALIGN(NODE) (TYPE_CHECK (NODE)->type.align)
|
||||
|
||||
/* The alignment for NODE, in bytes. */
|
||||
#define TYPE_ALIGN_UNIT(NODE) \
|
||||
(TYPE_ALIGN (NODE) / BITS_PER_UNIT)
|
||||
|
||||
#define TYPE_STUB_DECL(NODE) (TREE_CHAIN (NODE))
|
||||
|
||||
/* In a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, it means the type
|
||||
|
Loading…
Reference in New Issue
Block a user