* 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>
|
2000-03-02 Clinton Popetz <cpopetz@cygnus.com>
|
||||||
|
|
||||||
* config/i386/i386.c: (constant_call_address_operand): Reject
|
* 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>
|
2000-03-01 Jason Merrill <jason@casey.cygnus.com>
|
||||||
|
|
||||||
* pt.c (instantiate_decl): Clear TI_PENDING_TEMPLATE_FLAG.
|
* 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,
|
/* Build a call to operator delete. This has to be handled very specially,
|
||||||
because the restrictions on what signatures match are different from all
|
because the restrictions on what signatures match are different from all
|
||||||
other call instances. For a normal delete, only a delete taking (void *)
|
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
|
/* A lot of properties from the bases also apply to the derived
|
||||||
class. */
|
class. */
|
||||||
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
|
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 (t)
|
||||||
|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
|
|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
|
||||||
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_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_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
|
||||||
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
|
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
|
||||||
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (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 (variants)
|
||||||
= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
|
= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
|
||||||
@ -3503,14 +3505,14 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
|||||||
tree *f;
|
tree *f;
|
||||||
|
|
||||||
/* Destructor. */
|
/* 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);
|
default_fn = cons_up_default_function (t, name, 0);
|
||||||
check_for_override (default_fn, t);
|
check_for_override (default_fn, t);
|
||||||
|
|
||||||
/* If we couldn't make it work, then pretend we didn't need it. */
|
/* If we couldn't make it work, then pretend we didn't need it. */
|
||||||
if (default_fn == void_type_node)
|
if (default_fn == void_type_node)
|
||||||
TYPE_NEEDS_DESTRUCTOR (t) = 0;
|
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TREE_CHAIN (default_fn) = implicit_fns;
|
TREE_CHAIN (default_fn) = implicit_fns;
|
||||||
@ -3520,7 +3522,9 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
|
|||||||
virtual_dtor = default_fn;
|
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. */
|
/* Default constructor. */
|
||||||
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
|
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))
|
if (TYPE_NEEDS_CONSTRUCTING (type))
|
||||||
cp_error_at ("member `%#D' with constructor not allowed in union",
|
cp_error_at ("member `%#D' with constructor not allowed in union",
|
||||||
field);
|
field);
|
||||||
if (TYPE_NEEDS_DESTRUCTOR (type))
|
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||||
cp_error_at ("member `%#D' with destructor not allowed in union",
|
cp_error_at ("member `%#D' with destructor not allowed in union",
|
||||||
field);
|
field);
|
||||||
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
|
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
|
||||||
@ -3754,7 +3758,8 @@ check_field_decl (field, t, cant_have_const_ctor,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
|
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_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
|
||||||
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
|
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
|
||||||
}
|
}
|
||||||
@ -4268,6 +4273,7 @@ check_methods (t)
|
|||||||
tree t;
|
tree t;
|
||||||
{
|
{
|
||||||
tree x;
|
tree x;
|
||||||
|
int seen_one_arg_array_delete_p = 0;
|
||||||
|
|
||||||
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
|
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
|
||||||
{
|
{
|
||||||
@ -4291,6 +4297,37 @@ check_methods (t)
|
|||||||
CLASSTYPE_PURE_VIRTUALS (t)
|
CLASSTYPE_PURE_VIRTUALS (t)
|
||||||
= tree_cons (NULL_TREE, x, 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.
|
1: TYPE_HAS_CONSTRUCTOR.
|
||||||
2: TYPE_HAS_DESTRUCTOR.
|
2: TYPE_HAS_DESTRUCTOR.
|
||||||
3: TYPE_FOR_JAVA.
|
3: TYPE_FOR_JAVA.
|
||||||
4: TYPE_NEEDS_DESTRUCTOR.
|
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
|
||||||
5: IS_AGGR_TYPE.
|
5: IS_AGGR_TYPE.
|
||||||
6: TYPE_BUILT_IN.
|
6: TYPE_BUILT_IN.
|
||||||
|
|
||||||
@ -1310,7 +1310,8 @@ struct lang_type
|
|||||||
unsigned has_nonpublic_assign_ref : 2;
|
unsigned has_nonpublic_assign_ref : 2;
|
||||||
unsigned vtable_needs_writing : 1;
|
unsigned vtable_needs_writing : 1;
|
||||||
unsigned has_assign_ref : 1;
|
unsigned has_assign_ref : 1;
|
||||||
unsigned gets_new : 2;
|
unsigned has_new : 1;
|
||||||
|
unsigned has_array_new : 1;
|
||||||
|
|
||||||
unsigned gets_delete : 2;
|
unsigned gets_delete : 2;
|
||||||
unsigned has_call_overloaded : 1;
|
unsigned has_call_overloaded : 1;
|
||||||
@ -1391,9 +1392,7 @@ struct lang_type
|
|||||||
/* List of friends which were defined inline in this class definition. */
|
/* List of friends which were defined inline in this class definition. */
|
||||||
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
|
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
|
||||||
|
|
||||||
/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
|
/* Nonzero for _CLASSTYPE means that operator delete is defined. */
|
||||||
respectively. */
|
|
||||||
#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_new)
|
|
||||||
#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_delete)
|
#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->gets_delete)
|
||||||
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
|
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
|
||||||
|
|
||||||
@ -1401,9 +1400,15 @@ struct lang_type
|
|||||||
takes the optional size_t argument. */
|
takes the optional size_t argument. */
|
||||||
#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \
|
#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \
|
||||||
(TYPE_LANG_SPECIFIC(NODE)->vec_delete_takes_size)
|
(TYPE_LANG_SPECIFIC(NODE)->vec_delete_takes_size)
|
||||||
#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
|
|
||||||
(TYPE_NEEDS_DESTRUCTOR (NODE) \
|
/* Nonzero if `new NODE[x]' should cause the allocation of extra
|
||||||
|| (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
|
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
|
/* Nonzero means that this _CLASSTYPE node defines ways of converting
|
||||||
itself to other types. */
|
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_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)
|
#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
|
/* Nonzero means that this type is being defined. I.e., the left brace
|
||||||
starting the definition of this type has been seen. */
|
starting the definition of this type has been seen. */
|
||||||
#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->being_defined)
|
#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) \
|
#define SET_DECL_TINFO_FN_P(NODE) \
|
||||||
(DECL_LANG_SPECIFIC((NODE))->decl_flags.mutable_flag = 1)
|
(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
|
/* 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
|
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
|
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_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)
|
#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
|
/* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
|
||||||
will involve a call to a destructor. This can apply to objects
|
|
||||||
of ARRAY_TYPE is the type of the elements needs a destructor. */
|
A destructor is trivial if it is an implicitly declared
|
||||||
#define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE))
|
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
|
/* Nonzero for class type means that initialization of this type can use
|
||||||
a bitwise copy. */
|
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_user_type_conversion PARAMS ((tree, tree, int));
|
||||||
extern tree build_new_function_call PARAMS ((tree, tree));
|
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_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 tree build_op_delete_call PARAMS ((enum tree_code, tree, tree, int, tree));
|
||||||
extern int can_convert PARAMS ((tree, tree));
|
extern int can_convert PARAMS ((tree, tree));
|
||||||
extern int can_convert_arg PARAMS ((tree, 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 resolve_offset_ref PARAMS ((tree));
|
||||||
extern tree decl_constant_value PARAMS ((tree));
|
extern tree decl_constant_value PARAMS ((tree));
|
||||||
extern tree build_new PARAMS ((tree, tree, tree, int));
|
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_vec_init PARAMS ((tree, tree, tree, tree, int));
|
||||||
extern tree build_x_delete PARAMS ((tree, int, tree));
|
extern tree build_x_delete PARAMS ((tree, int, tree));
|
||||||
extern tree build_delete PARAMS ((tree, tree, tree, int, int));
|
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
|
/* 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
|
add any more objects with cleanups to the current scope, create a
|
||||||
new binding level. */
|
new binding level. */
|
||||||
if (TYPE_NEEDS_DESTRUCTOR (type)
|
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|
||||||
&& current_binding_level->more_cleanups_ok == 0)
|
&& current_binding_level->more_cleanups_ok == 0)
|
||||||
{
|
{
|
||||||
keep_next_level (2);
|
keep_next_level (2);
|
||||||
@ -7490,7 +7490,7 @@ initialize_local_var (decl, init, flags)
|
|||||||
if (TREE_STATIC (decl))
|
if (TREE_STATIC (decl))
|
||||||
{
|
{
|
||||||
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|
||||||
|| TYPE_NEEDS_DESTRUCTOR (type))
|
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||||
expand_static_init (decl, init);
|
expand_static_init (decl, init);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -7522,7 +7522,7 @@ initialize_local_var (decl, init, flags)
|
|||||||
marked used. (see TREE_USED, above.) */
|
marked used. (see TREE_USED, above.) */
|
||||||
if (TYPE_NEEDS_CONSTRUCTING (type)
|
if (TYPE_NEEDS_CONSTRUCTING (type)
|
||||||
&& ! already_used
|
&& ! already_used
|
||||||
&& !TYPE_NEEDS_DESTRUCTOR (type)
|
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
|
||||||
&& DECL_NAME (decl))
|
&& DECL_NAME (decl))
|
||||||
TREE_USED (decl) = 0;
|
TREE_USED (decl) = 0;
|
||||||
else if (already_used)
|
else if (already_used)
|
||||||
@ -7544,7 +7544,7 @@ destroy_local_var (decl)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* And only things with destructors need cleaning up. */
|
/* And only things with destructors need cleaning up. */
|
||||||
if (!TYPE_NEEDS_DESTRUCTOR (type))
|
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TREE_CODE (decl) == VAR_DECL &&
|
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'. */
|
/* Cleanups for static variables are handled by `finish_file'. */
|
||||||
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|
||||||
|| TYPE_NEEDS_DESTRUCTOR (type))
|
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||||
expand_static_init (decl, init);
|
expand_static_init (decl, init);
|
||||||
}
|
}
|
||||||
finish_end0:
|
finish_end0:
|
||||||
@ -8054,7 +8054,7 @@ register_dtor_fn (decl)
|
|||||||
|
|
||||||
int saved_flag_access_control;
|
int saved_flag_access_control;
|
||||||
|
|
||||||
if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
|
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Call build_cleanup before we enter the anonymous function so that
|
/* 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])
|
|| name == ansi_opname[(int) MEMBER_REF])
|
||||||
TYPE_OVERLOADS_ARROW (current_class_type) = 1;
|
TYPE_OVERLOADS_ARROW (current_class_type) = 1;
|
||||||
else if (name == ansi_opname[(int) NEW_EXPR])
|
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])
|
else if (name == ansi_opname[(int) DELETE_EXPR])
|
||||||
TYPE_GETS_DELETE (current_class_type) |= 1;
|
TYPE_GETS_DELETE (current_class_type) |= 1;
|
||||||
else if (name == ansi_opname[(int) VEC_NEW_EXPR])
|
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])
|
else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
|
||||||
TYPE_GETS_DELETE (current_class_type) |= 2;
|
TYPE_GETS_DELETE (current_class_type) |= 2;
|
||||||
}
|
}
|
||||||
@ -11894,14 +11894,7 @@ grok_op_properties (decl, virtualp, friendp)
|
|||||||
hash_tree_chain (ptr_type_node,
|
hash_tree_chain (ptr_type_node,
|
||||||
void_list_node));
|
void_list_node));
|
||||||
else
|
else
|
||||||
{
|
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -12508,7 +12501,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
|
|||||||
|
|
||||||
if (CLASS_TYPE_P (basetype))
|
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);
|
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
|
||||||
/* If the base-class uses multiple inheritance, so do we. */
|
/* If the base-class uses multiple inheritance, so do we. */
|
||||||
TYPE_USES_MULTIPLE_INHERITANCE (ref)
|
TYPE_USES_MULTIPLE_INHERITANCE (ref)
|
||||||
@ -13387,7 +13383,7 @@ store_parm_decls ()
|
|||||||
cleanups = tree_cons (parm, cleanup, cleanups);
|
cleanups = tree_cons (parm, cleanup, cleanups);
|
||||||
}
|
}
|
||||||
else if (type != error_mark_node
|
else if (type != error_mark_node
|
||||||
&& TYPE_NEEDS_DESTRUCTOR (type))
|
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||||
parms_have_cleanups = 1;
|
parms_have_cleanups = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -13603,7 +13599,7 @@ finish_destructor_body ()
|
|||||||
|
|
||||||
while (vbases)
|
while (vbases)
|
||||||
{
|
{
|
||||||
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
|
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbases)))
|
||||||
{
|
{
|
||||||
tree vb = get_vbase
|
tree vb = get_vbase
|
||||||
(BINFO_TYPE (vbases),
|
(BINFO_TYPE (vbases),
|
||||||
@ -14286,7 +14282,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
|
|||||||
tree decl, auto_delete;
|
tree decl, auto_delete;
|
||||||
{
|
{
|
||||||
tree type = TREE_TYPE (decl);
|
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;
|
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
|
||||||
tree rval;
|
tree rval;
|
||||||
|
@ -3238,7 +3238,7 @@ do_static_destruction (decl)
|
|||||||
my_friendly_assert (!flag_use_cxa_atexit, 20000121);
|
my_friendly_assert (!flag_use_cxa_atexit, 20000121);
|
||||||
|
|
||||||
/* If we don't need a destructor, there's nothing to do. */
|
/* 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;
|
return;
|
||||||
|
|
||||||
/* Actually do the destruction. */
|
/* 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 *));
|
real_arglist = (char **) xmalloc (num_args * sizeof (char *));
|
||||||
arglist = (const char **) real_arglist;
|
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. */
|
/* NOTE: We start at 1 now, not 0. */
|
||||||
for (i = 0, j = 0; i < argc; i++, j++)
|
while (i < argc)
|
||||||
{
|
{
|
||||||
arglist[j] = argv[i];
|
arglist[j] = argv[i];
|
||||||
|
|
||||||
@ -237,11 +250,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
|
|||||||
arglist[j++] = argv[i];
|
arglist[j++] = argv[i];
|
||||||
arglist[j] = "-xnone";
|
arglist[j] = "-xnone";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_NEW_GXX_ABI
|
i++;
|
||||||
arglist[j++] = "-fnew-abi";
|
j++;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
/* Add `-lstdc++' if we haven't already done so. */
|
/* Add `-lstdc++' if we haven't already done so. */
|
||||||
if (library)
|
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 void expand_cleanup_for_base PARAMS ((tree, tree));
|
||||||
static tree get_temp_regvar PARAMS ((tree, tree));
|
static tree get_temp_regvar PARAMS ((tree, tree));
|
||||||
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
|
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
|
/* Set up local variable for this file. MUST BE CALLED AFTER
|
||||||
INIT_DECL_PROCESSING. */
|
INIT_DECL_PROCESSING. */
|
||||||
@ -225,7 +227,7 @@ perform_member_init (member, name, init, explicit)
|
|||||||
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
|
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TYPE_NEEDS_DESTRUCTOR (type))
|
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
|
||||||
{
|
{
|
||||||
tree expr;
|
tree expr;
|
||||||
|
|
||||||
@ -701,7 +703,7 @@ expand_cleanup_for_base (binfo, flag)
|
|||||||
{
|
{
|
||||||
tree expr;
|
tree expr;
|
||||||
|
|
||||||
if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
|
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Call the destructor. */
|
/* Call the destructor. */
|
||||||
@ -2101,10 +2103,40 @@ build_java_class_ref (type)
|
|||||||
return class_decl;
|
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
|
/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
|
||||||
value is immediately handed to expand_expr. */
|
value is immediately handed to expand_expr. */
|
||||||
|
|
||||||
tree
|
static tree
|
||||||
build_new_1 (exp)
|
build_new_1 (exp)
|
||||||
tree exp;
|
tree exp;
|
||||||
{
|
{
|
||||||
@ -2113,15 +2145,23 @@ build_new_1 (exp)
|
|||||||
tree nelts = NULL_TREE;
|
tree nelts = NULL_TREE;
|
||||||
tree alloc_expr, alloc_node = NULL_TREE;
|
tree alloc_expr, alloc_node = NULL_TREE;
|
||||||
int has_array = 0;
|
int has_array = 0;
|
||||||
enum tree_code code = NEW_EXPR;
|
enum tree_code code;
|
||||||
int use_cookie, nothrow, check_new;
|
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_global_new;
|
||||||
int use_java_new = 0;
|
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);
|
placement = TREE_OPERAND (exp, 0);
|
||||||
type = TREE_OPERAND (exp, 1);
|
type = TREE_OPERAND (exp, 1);
|
||||||
init = TREE_OPERAND (exp, 2);
|
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)
|
if (TREE_CODE (type) == ARRAY_REF)
|
||||||
{
|
{
|
||||||
@ -2131,6 +2171,8 @@ build_new_1 (exp)
|
|||||||
}
|
}
|
||||||
true_type = type;
|
true_type = type;
|
||||||
|
|
||||||
|
code = has_array ? VEC_NEW_EXPR : NEW_EXPR;
|
||||||
|
|
||||||
if (CP_TYPE_QUALS (type))
|
if (CP_TYPE_QUALS (type))
|
||||||
type = TYPE_MAIN_VARIANT (type);
|
type = TYPE_MAIN_VARIANT (type);
|
||||||
|
|
||||||
@ -2161,32 +2203,44 @@ build_new_1 (exp)
|
|||||||
if (abstract_virtuals_error (NULL_TREE, true_type))
|
if (abstract_virtuals_error (NULL_TREE, true_type))
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
/* When we allocate an array, and the corresponding deallocation
|
/* Figure out whether or not we're going to use the global operator
|
||||||
function takes a second argument of type size_t, and that's the
|
new. */
|
||||||
"usual deallocation function", we allocate some extra space at
|
if (!globally_qualified_p
|
||||||
the beginning of the array to store the size of the array.
|
&& 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
|
/* We only need cookies for arrays containing types for which we
|
||||||
have to do this whenever there's a two-argument array-delete
|
need cookies. */
|
||||||
operator.
|
if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
|
||||||
|
use_cookie = 0;
|
||||||
FIXME: For -fnew-abi, we don't have to maintain backwards
|
/* When using placement new, users may not realize that they need
|
||||||
compatibility and we should fix this. */
|
the extra storage. Under the old ABI, we don't allocate the
|
||||||
use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
|
cookie whenever they use one placement argument of type `void
|
||||||
&& ! (placement && ! TREE_CHAIN (placement)
|
*'. Under the new ABI, we require that the operator called be
|
||||||
&& TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
|
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)
|
if (use_cookie)
|
||||||
size = size_binop (PLUS_EXPR, size, BI_header_size);
|
|
||||||
|
|
||||||
if (has_array)
|
|
||||||
{
|
{
|
||||||
code = VEC_NEW_EXPR;
|
cookie_size = get_cookie_size (true_type);
|
||||||
|
size = size_binop (PLUS_EXPR, size, cookie_size);
|
||||||
if (init && pedantic)
|
|
||||||
cp_pedwarn ("initialization in array new");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_array && init && pedantic)
|
||||||
|
cp_pedwarn ("initialization in array new");
|
||||||
|
|
||||||
/* Allocate the object. */
|
/* Allocate the object. */
|
||||||
|
|
||||||
if (! placement && TYPE_FOR_JAVA (true_type))
|
if (! placement && TYPE_FOR_JAVA (true_type))
|
||||||
@ -2208,9 +2262,20 @@ build_new_1 (exp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rval = build_op_new_call
|
tree fnname;
|
||||||
(code, true_type, tree_cons (NULL_TREE, size, placement),
|
tree args;
|
||||||
LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
|
|
||||||
|
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);
|
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 */
|
/* Finish up some magic for new'ed arrays */
|
||||||
if (use_cookie && rval != NULL_TREE)
|
if (use_cookie && rval != NULL_TREE)
|
||||||
{
|
{
|
||||||
tree extra = BI_header_size;
|
|
||||||
tree cookie, exp1;
|
tree cookie, exp1;
|
||||||
rval = convert (string_type_node, rval); /* for ptr arithmetic */
|
rval = convert (string_type_node, rval); /* for ptr arithmetic */
|
||||||
rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra));
|
rval = save_expr (build_binary_op (PLUS_EXPR, rval, cookie_size));
|
||||||
/* Store header info. */
|
/* Store the number of bytes allocated so that we can know how
|
||||||
cookie = build_indirect_ref (build (MINUS_EXPR,
|
many elements to destroy later. */
|
||||||
build_pointer_type (BI_header_type),
|
if (flag_new_abi)
|
||||||
rval, extra), NULL_PTR);
|
{
|
||||||
exp1 = build (MODIFY_EXPR, void_type_node,
|
/* Under the new ABI, we use the last sizeof (size_t) bytes
|
||||||
build_component_ref (cookie, nelts_identifier,
|
to store the number of elements. */
|
||||||
NULL_TREE, 0),
|
cookie = build_indirect_ref (build (MINUS_EXPR,
|
||||||
nelts);
|
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 = cp_convert (build_pointer_type (true_type), rval);
|
||||||
rval = build_compound_expr
|
rval = build_compound_expr
|
||||||
(tree_cons (NULL_TREE, exp1,
|
(tree_cons (NULL_TREE, exp1,
|
||||||
@ -2372,7 +2455,8 @@ build_new_1 (exp)
|
|||||||
{
|
{
|
||||||
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
|
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
|
||||||
tree cleanup, fn = NULL_TREE;
|
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
|
/* The Standard is unclear here, but the right thing to do
|
||||||
is to use the same method for finding deallocation
|
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. */
|
This is also the containing expression returned by this function. */
|
||||||
tree controller = NULL_TREE;
|
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;
|
loop = integer_zero_node;
|
||||||
goto no_destructor;
|
goto no_destructor;
|
||||||
@ -2534,12 +2618,16 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
|
|||||||
base_tbd = base;
|
base_tbd = base;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
base_tbd = cp_convert (ptype,
|
tree cookie_size;
|
||||||
build_binary_op (MINUS_EXPR,
|
|
||||||
cp_convert (string_type_node, base),
|
cookie_size = get_cookie_size (type);
|
||||||
BI_header_size));
|
base_tbd
|
||||||
|
= cp_convert (ptype,
|
||||||
|
build_binary_op (MINUS_EXPR,
|
||||||
|
cp_convert (string_type_node, base),
|
||||||
|
cookie_size));
|
||||||
/* True size with header. */
|
/* 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,
|
deallocate_expr = build_x_delete (base_tbd,
|
||||||
2 | use_global_delete,
|
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
|
/* Protect the entire array initialization so that we can destroy
|
||||||
the partially constructed array if an exception is thrown. */
|
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_block = begin_try_block ();
|
||||||
try_body = begin_compound_stmt (/*has_no_scope=*/1);
|
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. */
|
/* 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;
|
tree e;
|
||||||
|
|
||||||
@ -3029,7 +3117,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
|||||||
|
|
||||||
my_friendly_assert (IS_AGGR_TYPE (type), 220);
|
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)
|
if (auto_delete == integer_zero_node)
|
||||||
return void_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)
|
if (auto_delete == integer_zero_node)
|
||||||
cond = NULL_TREE;
|
cond = NULL_TREE;
|
||||||
else if (base_binfo == 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,
|
cond = build (COND_EXPR, void_type_node,
|
||||||
build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_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
|
if (base_binfo
|
||||||
&& ! TREE_VIA_VIRTUAL (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;
|
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++)
|
for (i = 1; i < n_baseclasses; i++)
|
||||||
{
|
{
|
||||||
base_binfo = TREE_VEC_ELT (binfos, 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))
|
|| TREE_VIA_VIRTUAL (base_binfo))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -3154,7 +3242,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
|
|||||||
{
|
{
|
||||||
if (TREE_CODE (member) != FIELD_DECL)
|
if (TREE_CODE (member) != FIELD_DECL)
|
||||||
continue;
|
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_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
|
||||||
tree this_type = TREE_TYPE (member);
|
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)
|
if (TREE_CODE (type) == POINTER_TYPE)
|
||||||
{
|
{
|
||||||
/* Step back one from start of vector, and read dimension. */
|
/* Step back one from start of vector, and read dimension. */
|
||||||
tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
|
tree cookie_addr;
|
||||||
base, BI_header_size);
|
|
||||||
tree cookie = build_indirect_ref (cookie_addr, NULL_PTR);
|
if (flag_new_abi)
|
||||||
maxindex = build_component_ref (cookie, nelts_identifier, NULL_TREE, 0);
|
{
|
||||||
do
|
cookie_addr = build (MINUS_EXPR,
|
||||||
type = TREE_TYPE (type);
|
build_pointer_type (sizetype),
|
||||||
while (TREE_CODE (type) == ARRAY_TYPE);
|
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)
|
else if (TREE_CODE (type) == ARRAY_TYPE)
|
||||||
{
|
{
|
||||||
/* get the total number of things in the array, maxindex is a bad name */
|
/* get the total number of things in the array, maxindex is a bad name */
|
||||||
maxindex = array_type_nelts_total (type);
|
maxindex = array_type_nelts_total (type);
|
||||||
while (TREE_CODE (type) == ARRAY_TYPE)
|
type = strip_array_types (type);
|
||||||
type = TREE_TYPE (type);
|
|
||||||
base = build_unary_op (ADDR_EXPR, base, 1);
|
base = build_unary_op (ADDR_EXPR, base, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3147,7 +3147,7 @@ do_identifier (token, parsing, args)
|
|||||||
else if (!DECL_ERROR_REPORTED (id))
|
else if (!DECL_ERROR_REPORTED (id))
|
||||||
{
|
{
|
||||||
DECL_ERROR_REPORTED (id) = 1;
|
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",
|
error ("name lookup of `%s' changed for new ISO `for' scoping",
|
||||||
IDENTIFIER_POINTER (token));
|
IDENTIFIER_POINTER (token));
|
||||||
|
@ -4830,7 +4830,8 @@ instantiate_class_template (type)
|
|||||||
TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
|
TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
|
||||||
TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
|
TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
|
||||||
TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (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_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
|
||||||
TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
|
TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
|
||||||
TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (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))
|
if (TYPE_NEEDS_CONSTRUCTING (node))
|
||||||
fputs ( "needs-constructor", file);
|
fputs ( "needs-constructor", file);
|
||||||
if (TYPE_NEEDS_DESTRUCTOR (node))
|
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node))
|
||||||
fputs (" needs-destructor", file);
|
fputs (" needs-destructor", file);
|
||||||
if (TYPE_HAS_DESTRUCTOR (node))
|
if (TYPE_HAS_DESTRUCTOR (node))
|
||||||
fputs (" ~X()", file);
|
fputs (" ~X()", file);
|
||||||
@ -128,9 +128,9 @@ print_lang_type (file, node, indent)
|
|||||||
else
|
else
|
||||||
fputs (" X(X&)", file);
|
fputs (" X(X&)", file);
|
||||||
}
|
}
|
||||||
if (TYPE_GETS_NEW (node) & 1)
|
if (TYPE_HAS_NEW_OPERATOR (node))
|
||||||
fputs (" new", file);
|
fputs (" new", file);
|
||||||
if (TYPE_GETS_NEW (node) & 2)
|
if (TYPE_HAS_ARRAY_NEW_OPERATOR (node))
|
||||||
fputs (" new[]", file);
|
fputs (" new[]", file);
|
||||||
if (TYPE_GETS_DELETE (node) & 1)
|
if (TYPE_GETS_DELETE (node) & 1)
|
||||||
fputs (" delete", file);
|
fputs (" delete", file);
|
||||||
|
@ -725,7 +725,7 @@ context_for_name_lookup (decl)
|
|||||||
|
|
||||||
For the purposes of name lookup, after the anonymous union
|
For the purposes of name lookup, after the anonymous union
|
||||||
definition, the members of the anonymous union are considered to
|
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. */
|
declared. */
|
||||||
tree context = CP_DECL_CONTEXT (decl);
|
tree context = CP_DECL_CONTEXT (decl);
|
||||||
|
|
||||||
@ -1955,7 +1955,7 @@ tree_has_any_destructor_p (binfo, data)
|
|||||||
void *data ATTRIBUTE_UNUSED;
|
void *data ATTRIBUTE_UNUSED;
|
||||||
{
|
{
|
||||||
tree type = BINFO_TYPE (binfo);
|
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
|
/* Returns > 0 if a function with type DRETTYPE overriding a function
|
||||||
|
@ -322,7 +322,7 @@ break_out_cleanups (exp)
|
|||||||
tree tmp = exp;
|
tree tmp = exp;
|
||||||
|
|
||||||
if (TREE_CODE (tmp) == CALL_EXPR
|
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);
|
return build_cplus_new (TREE_TYPE (tmp), tmp);
|
||||||
|
|
||||||
while (TREE_CODE (tmp) == NOP_EXPR
|
while (TREE_CODE (tmp) == NOP_EXPR
|
||||||
@ -330,7 +330,7 @@ break_out_cleanups (exp)
|
|||||||
|| TREE_CODE (tmp) == NON_LVALUE_EXPR)
|
|| TREE_CODE (tmp) == NON_LVALUE_EXPR)
|
||||||
{
|
{
|
||||||
if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_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)
|
TREE_OPERAND (tmp, 0)
|
||||||
= build_cplus_new (TREE_TYPE (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. */
|
more easily. */
|
||||||
TYPE_NEEDS_CONSTRUCTING (t)
|
TYPE_NEEDS_CONSTRUCTING (t)
|
||||||
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
|
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
|
||||||
TYPE_NEEDS_DESTRUCTOR (t)
|
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||||
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
|
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,7 +602,7 @@ cp_build_qualified_type_real (type, type_quals, complain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Even if we already had this variant, we update
|
/* 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.
|
they changed since the variant was originally created.
|
||||||
|
|
||||||
This seems hokey; if there is some way to use a previous
|
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 will never be updated. */
|
||||||
TYPE_NEEDS_CONSTRUCTING (t)
|
TYPE_NEEDS_CONSTRUCTING (t)
|
||||||
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
|
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
|
||||||
TYPE_NEEDS_DESTRUCTOR (t)
|
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|
||||||
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
|
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
else if (TYPE_PTRMEMFUNC_P (type))
|
else if (TYPE_PTRMEMFUNC_P (type))
|
||||||
|
@ -155,8 +155,8 @@ complete_type (type)
|
|||||||
layout_type (type);
|
layout_type (type);
|
||||||
TYPE_NEEDS_CONSTRUCTING (type)
|
TYPE_NEEDS_CONSTRUCTING (type)
|
||||||
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
|
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
|
||||||
TYPE_NEEDS_DESTRUCTOR (type)
|
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|
||||||
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
|
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
|
||||||
}
|
}
|
||||||
else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
|
else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
|
||||||
instantiate_class_template (TYPE_MAIN_VARIANT (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>
|
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||||
|
// Special g++ Options: -O2
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
@ -880,6 +880,10 @@ struct tree_block
|
|||||||
The value is an int, measured in bits. */
|
The value is an int, measured in bits. */
|
||||||
#define TYPE_ALIGN(NODE) (TYPE_CHECK (NODE)->type.align)
|
#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))
|
#define TYPE_STUB_DECL(NODE) (TREE_CHAIN (NODE))
|
||||||
|
|
||||||
/* In a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, it means the type
|
/* In a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, it means the type
|
||||||
|
Loading…
Reference in New Issue
Block a user