Deleted Added
full compact
2c2
< Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
---
> Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
21a22
> /* High-level class interface. */
23,24d23
< /* High-level class interface. */
<
25a25
> #include "system.h"
30a31,33
> #include "except.h"
> #include "expr.h"
> #include "toplev.h"
32,33c35
< #undef NULL
< #define NULL 0
---
> extern void compiler_error ();
46,54c48,60
< void emit_base_init ();
< void check_base_init ();
< static void expand_aggr_vbase_init ();
< void expand_member_init ();
< void expand_aggr_init ();
<
< static void expand_aggr_init_1 ();
< static void expand_recursive_init_1 ();
< static void expand_recursive_init ();
---
> static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree));
> static void expand_aggr_vbase_init PROTO((tree, tree, tree, tree));
> static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int,
> int));
> static void expand_default_init PROTO((tree, tree, tree, tree, int,
> int));
> static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, tree,
> int));
> static void perform_member_init PROTO((tree, tree, tree, int));
> static void sort_base_init PROTO((tree, tree *, tree *));
> static tree build_builtin_call PROTO((tree, tree, tree));
> static tree build_array_eh_cleanup PROTO((tree, tree, tree));
> static int member_init_ok_or_else PROTO((tree, tree, char *));
56c62,64
< tree expand_vec_init ();
---
> static tree sort_member_init PROTO((tree));
> static tree build_partial_cleanup_for PROTO((tree));
> static tree initializing_context PROTO((tree));
58,59d65
< static void add_friend (), add_friends ();
<
63c69
< /* Cache the identifier nodes for the two magic field of a new cookie. */
---
> /* Cache the identifier nodes for the magic field of a new cookie. */
65,67d70
< #if 0
< static tree nc_ptr_2comp_field_id;
< #endif
74c77
< tree BI_header_type, BI_header_size;
---
> static tree BI_header_type, BI_header_size;
121a125
>
135,136c139,140
< int is_not_base_vtable =
< i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
---
> int is_not_base_vtable
> = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
155a160
>
157,158c162,163
< perform_member_init (member, name, init, explicit, protect_list)
< tree member, name, init, *protect_list;
---
> perform_member_init (member, name, init, explicit)
> tree member, name, init;
163a169,170
> expand_start_target_temps ();
>
170c177
< init = build_tree_list (NULL_TREE, init);
---
> init = build_expr_list (NULL_TREE, init);
172c179
< decl = build_component_ref (C_C_D, name, 0, explicit);
---
> decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
193,195c200,210
< cp_error ("incomplete initializer for member `%D' of class `%T' which has no constructor",
< member, current_class_type);
< init = error_mark_node;
---
> /* default-initialization. */
> if (AGGREGATE_TYPE_P (type))
> init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
> else if (TREE_CODE (type) == REFERENCE_TYPE)
> {
> cp_error ("default-initialization of `%#D', which has reference type",
> member);
> init = error_mark_node;
> }
> else
> init = integer_zero_node;
218c233,234
< decl = build_component_ref (C_C_D, name, 0, explicit);
---
> decl = build_component_ref (current_class_ref, name, NULL_TREE,
> explicit);
222d237
< expand_cleanups_to (NULL_TREE);
223a239,241
> expand_end_target_temps ();
> free_temp_slots ();
>
226c244,251
< tree expr = build_component_ref (C_C_D, name, 0, explicit);
---
> tree expr;
>
> /* All cleanups must be on the function_obstack. */
> push_obstacks_nochange ();
> resume_temporary_allocation ();
>
> expr = build_component_ref (current_class_ref, name, NULL_TREE,
> explicit);
231,234c256,258
< {
< start_protect ();
< *protect_list = tree_cons (NULL_TREE, expr, *protect_list);
< }
---
> add_partial_entry (expr);
>
> pop_obstacks ();
240a265
>
245c270
< tree x, member, name, field, init;
---
> tree x, member, name, field;
247d271
< tree fields_to_unmark = NULL_TREE;
249c273
< tree last_field;
---
> tree last_field = NULL_TREE;
268a293,294
> /* This happens in templates, since the IDENTIFIER is replaced
> with the COMPONENT_REF in tsubst_expr. */
356,357c382,383
< tree basename = TREE_PURPOSE (x);
< tree binfo;
---
> tree basetype = TREE_PURPOSE (x);
> tree binfo = NULL_TREE;
359c385
< if (basename == NULL_TREE)
---
> if (basetype == NULL_TREE)
378c404
< else if (is_aggr_typedef (basename, 1))
---
> else if (is_aggr_type (basetype, 1))
380c406
< binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
---
> binfo = binfo_or_else (basetype, t);
405,406c431
< IDENTIFIER_TYPE_VALUE (basename),
< current_class_type);
---
> basetype, current_class_type);
470a496
>
475,481c501,503
< tree expr = convert_pointer_to_real (binfo,
< build_unary_op (ADDR_EXPR, C_C_D, 0));
<
< return build_delete (TREE_TYPE (expr),
< expr,
< integer_zero_node,
< LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
---
> return build_scoped_method_call
> (current_class_ref, binfo, dtor_identifier,
> build_expr_list (NULL_TREE, integer_zero_node));
509,511c531
< extern tree in_charge_identifier;
<
< tree member, x;
---
> tree member;
519,520d538
< my_friendly_assert (protect_list == NULL_TREE, 999);
<
552c570
< expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
---
> expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,
560d577
< tree base = current_class_decl;
568c585
< my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
---
> my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999);
576c593,598
< init = NULL_TREE;
---
> {
> init = NULL_TREE;
> if (extra_warnings && copy_args_p (current_function_decl))
> cp_warning ("base class `%#T' should be explicitly initialized in the copy constructor",
> BINFO_TYPE (base_binfo));
> }
580,581c602,605
< member = convert_pointer_to_real (base_binfo, current_class_decl);
< expand_aggr_init_1 (base_binfo, 0,
---
> expand_start_target_temps ();
>
> member = convert_pointer_to_real (base_binfo, current_class_ptr);
> expand_aggr_init_1 (base_binfo, NULL_TREE,
584c608,610
< expand_cleanups_to (NULL_TREE);
---
>
> expand_end_target_temps ();
> free_temp_slots ();
589,592c615,622
< start_protect ();
< protect_list = tree_cons (NULL_TREE,
< build_partial_cleanup_for (base_binfo),
< protect_list);
---
> tree expr;
>
> /* All cleanups must be on the function_obstack. */
> push_obstacks_nochange ();
> resume_temporary_allocation ();
> expr = build_partial_cleanup_for (base_binfo);
> pop_obstacks ();
> add_partial_entry (expr);
599c629
< do come from virtual base classes. */
---
> do come from virtual base classes. */
601c631
< expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
---
> expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
605c635
< expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
---
> expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
624a655,658
> #if 0
> if (TREE_CODE (name) == COMPONENT_REF)
> name = DECL_NAME (TREE_OPERAND (name, 1));
> #else
628a663
> #endif
635a671,676
>
> /* Effective C++ rule 12. */
> if (warn_ecpp && init == NULL_TREE
> && !DECL_ARTIFICIAL (member)
> && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE)
> cp_warning ("`%D' should be initialized in the member initialization list", member);
638c679
< perform_member_init (member, name, init, from_init_list, &protect_list);
---
> perform_member_init (member, name, init, from_init_list);
676c717
< perform_member_init (field, name, init, 1, &protect_list);
---
> perform_member_init (field, name, init, 1);
699a741
>
715a758
>
745a789
>
751a796,798
>
> expand_start_target_temps ();
>
756c803,805
< expand_cleanups_to (NULL_TREE);
---
>
> expand_end_target_temps ();
> free_temp_slots ();
762a812
>
791,797c841,845
< /* Subroutine to perform parser actions for member initialization.
< S_ID is the scoped identifier.
< NAME is the name of the member.
< INIT is the initializer, or `void_type_node' if none. */
< void
< do_member_init (s_id, name, init)
< tree s_id, name, init;
---
> /* Find the context in which this FIELD can be initialized. */
>
> static tree
> initializing_context (field)
> tree field;
799c847
< tree binfo, base;
---
> tree t = DECL_CONTEXT (field);
801,815c849,853
< if (current_class_type == NULL_TREE
< || ! is_aggr_typedef (s_id, 1))
< return;
< binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
< current_class_type, 1);
< if (binfo == error_mark_node)
< return;
< if (binfo == 0)
< {
< error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
< return;
< }
<
< base = convert_pointer_to (binfo, current_class_decl);
< expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
---
> /* Anonymous union members can be initialized in the first enclosing
> non-anonymous union context. */
> while (t && ANON_UNION_TYPE_P (t))
> t = TYPE_CONTEXT (t);
> return t;
821,822c859
< FIELD must be a member of TYPE, or the base type from which FIELD
< comes must not need a constructor.
---
> FIELD must be a member of TYPE.
834c871
< if (field == NULL_TREE)
---
> if (field == NULL_TREE || initializing_context (field) != type)
840,850d876
< if (DECL_CONTEXT (field) != type
< && TYPE_NEEDS_CONSTRUCTING (DECL_CONTEXT (field)))
< {
< if (current_function_decl && DECL_CONSTRUCTOR_P (current_function_decl))
< cp_error ("initialization of `%D' inside constructor for `%T'",
< field, type);
< else
< cp_error ("member `%D' comes from base class needing constructor",
< field);
< return 0;
< }
875a902
>
880,881d906
< extern tree ptr_type_node; /* should be in tree.h */
<
883,885c908
< tree parm;
< tree rval, type;
< tree actual_name;
---
> tree type;
891a915,920
> if (name && TREE_CODE (name) == TYPE_DECL)
> {
> basetype = TREE_TYPE (name);
> name = DECL_NAME (name);
> }
>
907,914c936
< if (init)
< {
< /* The grammar should not allow fields which have names
< that are TYPENAMEs. Therefore, if the field has
< a non-NULL TREE_TYPE, we may assume that this is an
< attempt to initialize a base class member of the current
< type. Otherwise, it is an attempt to initialize a
< member field. */
---
> my_friendly_assert (init != NULL_TREE, 0);
916,917c938,942
< if (init == void_type_node)
< init = NULL_TREE;
---
> /* The grammar should not allow fields which have names that are
> TYPENAMEs. Therefore, if the field has a non-NULL TREE_TYPE, we
> may assume that this is an attempt to initialize a base class
> member of the current type. Otherwise, it is an attempt to
> initialize a member field. */
919,921c944,945
< if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name))
< {
< tree base_init;
---
> if (init == void_type_node)
> init = NULL_TREE;
923,934c947,955
< if (name == NULL_TREE)
< {
< /*
< if (basetype)
< name = TYPE_IDENTIFIER (basetype);
< else
< {
< error ("no base class to initialize");
< return;
< }
< */
< }
---
> if (name == NULL_TREE || basetype)
> {
> tree base_init;
>
> if (name == NULL_TREE)
> {
> #if 0
> if (basetype)
> name = TYPE_IDENTIFIER (basetype);
937,959c958
< basetype = IDENTIFIER_TYPE_VALUE (name);
< if (basetype != type
< && ! binfo_member (basetype, TYPE_BINFO (type))
< && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
< {
< if (IDENTIFIER_CLASS_VALUE (name))
< goto try_member;
< if (TYPE_USES_VIRTUAL_BASECLASSES (type))
< error ("type `%s' is not an immediate or virtual basetype for `%s'",
< IDENTIFIER_POINTER (name),
< TYPE_NAME_STRING (type));
< else
< error ("type `%s' is not an immediate basetype for `%s'",
< IDENTIFIER_POINTER (name),
< TYPE_NAME_STRING (type));
< return;
< }
< }
<
< if (purpose_member (name, current_base_init_list))
< {
< error ("base class `%s' already initialized",
< IDENTIFIER_POINTER (name));
---
> error ("no base class to initialize");
962,965c961
<
< base_init = build_tree_list (name, init);
< TREE_TYPE (base_init) = basetype;
< current_base_init_list = chainon (current_base_init_list, base_init);
---
> #endif
967c963,967
< else
---
> else if (basetype != type
> && ! current_template_parms
> && ! vec_binfo_member (basetype,
> TYPE_BINFO_BASETYPES (type))
> && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
969,985c969,977
< tree member_init;
<
< try_member:
< field = lookup_field (type, name, 1, 0);
<
< if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
< return;
<
< if (purpose_member (name, current_member_init_list))
< {
< error ("field `%s' already initialized", IDENTIFIER_POINTER (name));
< return;
< }
<
< member_init = build_tree_list (name, init);
< TREE_TYPE (member_init) = TREE_TYPE (field);
< current_member_init_list = chainon (current_member_init_list, member_init);
---
> if (IDENTIFIER_CLASS_VALUE (name))
> goto try_member;
> if (TYPE_USES_VIRTUAL_BASECLASSES (type))
> cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
> basetype, type);
> else
> cp_error ("type `%T' is not an immediate basetype for `%T'",
> basetype, type);
> return;
987,993d978
< return;
< }
< else if (name == NULL_TREE)
< {
< compiler_error ("expand_member_init: name == NULL_TREE");
< return;
< }
995,1008c980
< basetype = type;
< field = lookup_field (basetype, name, 0, 0);
<
< if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
< return;
<
< /* now see if there is a constructor for this type
< which will take these args. */
<
< if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
< {
< tree parmtypes, fndecl;
<
< if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
---
> if (purpose_member (basetype, current_base_init_list))
1010,1012c982,983
< /* just know that we've seen something for this node */
< DECL_INITIAL (exp) = error_mark_node;
< TREE_USED (exp) = 1;
---
> cp_error ("base class `%T' already initialized", basetype);
> return;
1014,1016d984
< type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
< actual_name = TYPE_IDENTIFIER (type);
< parm = build_component_ref (exp, name, 0, 0);
1018,1029c986
< /* Now get to the constructor. */
< fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
< /* Get past destructor, if any. */
< if (TYPE_HAS_DESTRUCTOR (type))
< fndecl = DECL_CHAIN (fndecl);
<
< if (fndecl)
< my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
<
< /* If the field is unique, we can use the parameter
< types to guide possible type instantiation. */
< if (DECL_CHAIN (fndecl) == NULL_TREE)
---
> if (warn_reorder && current_member_init_list)
1031,1036c988,989
< /* There was a confusion here between
< FIELD and FNDECL. The following code
< should be correct, but abort is here
< to make sure. */
< my_friendly_abort (48);
< parmtypes = FUNCTION_ARG_CHAIN (fndecl);
---
> cp_warning ("base initializer for `%T'", basetype);
> warning (" will be re-ordered to precede member initializations");
1038,1042d990
< else
< {
< parmtypes = NULL_TREE;
< fndecl = NULL_TREE;
< }
1044,1047c992,1002
< init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
< if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
< rval = build_method_call (NULL_TREE, actual_name, init, NULL_TREE, LOOKUP_NORMAL);
< else
---
> base_init = build_tree_list (basetype, init);
> current_base_init_list = chainon (current_base_init_list, base_init);
> }
> else
> {
> tree member_init;
>
> try_member:
> field = lookup_field (type, name, 1, 0);
>
> if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
1050c1005
< if (rval != error_mark_node)
---
> if (purpose_member (name, current_member_init_list))
1052,1056c1007,1008
< /* Now, fill in the first parm with our guy */
< TREE_VALUE (TREE_OPERAND (rval, 1))
< = build_unary_op (ADDR_EXPR, parm, 0);
< TREE_TYPE (rval) = ptr_type_node;
< TREE_SIDE_EFFECTS (rval) = 1;
---
> cp_error ("field `%D' already initialized", field);
> return;
1058,1064d1009
< }
< else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
< {
< parm = build_component_ref (exp, name, 0, 0);
< expand_aggr_init (parm, NULL_TREE, 0, 0);
< rval = error_mark_node;
< }
1066,1069c1011,1013
< /* Now initialize the member. It does not have to
< be of aggregate type to receive initialization. */
< if (rval != error_mark_node)
< expand_expr_stmt (rval);
---
> member_init = build_tree_list (name, init);
> current_member_init_list = chainon (current_member_init_list, member_init);
> }
1086,1087c1030,1032
< essentially an alias for C_C_D. In this case, the base constructor
< may move it on us, and we must keep track of such deviations.
---
> essentially an alias for current_class_ref. In this case, the base
> constructor may move it on us, and we must keep track of such
> deviations.
1107,1108c1052
< perform the initialization, but not both, as it would be ambiguous.
< */
---
> perform the initialization, but not both, as it would be ambiguous. */
1189c1133
< expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
---
> expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
1192d1135
< tree type;
1196a1140,1141
> tree type = TREE_TYPE (exp);
>
1205a1151,1181
> if (init && TREE_CODE (init) != TREE_LIST
> && (flags & LOOKUP_ONLYCONVERTING))
> {
> /* Base subobjects should only get direct-initialization. */
> if (true_exp != exp)
> abort ();
>
> /* We special-case TARGET_EXPRs here to avoid an error about
> private copy constructors for temporaries bound to reference vars.
> If the TARGET_EXPR represents a call to a function that has
> permission to create such objects, a reference can bind directly
> to the return value. An object variable must be initialized
> via the copy constructor, even if the call is elided. */
> if (! (TREE_CODE (exp) == VAR_DECL && DECL_ARTIFICIAL (exp)
> && TREE_CODE (init) == TARGET_EXPR && TREE_TYPE (init) == type))
> init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
>
> if (TREE_CODE (init) == TRY_CATCH_EXPR)
> /* We need to protect the initialization of a catch parm
> with a call to terminate(), which shows up as a TRY_CATCH_EXPR
> around the TARGET_EXPR for the copy constructor. See
> expand_start_catch_block. */
> TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
> TREE_OPERAND (init, 0));
> else
> init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
> TREE_SIDE_EFFECTS (init) = 1;
> expand_expr_stmt (init);
> return;
> }
>
1213,1220d1188
< else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
< && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
< {
< rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
< TREE_USED (rval) = 1;
< expand_expr_stmt (rval);
< return;
< }
1222c1190
< parms = build_tree_list (NULL_TREE, init);
---
> parms = build_expr_list (NULL_TREE, init);
1227c1195
< parms = tree_cons (NULL_TREE, integer_one_node, parms);
---
> parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
1229c1197
< parms = tree_cons (NULL_TREE, integer_zero_node, parms);
---
> parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms);
1233,1270c1201,1204
< if (init && TREE_CHAIN (parms) == NULL_TREE
< && TYPE_HAS_TRIVIAL_INIT_REF (type)
< && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
< {
< rval = build (INIT_EXPR, type, exp, init);
< TREE_SIDE_EFFECTS (rval) = 1;
< expand_expr_stmt (rval);
< }
< else
< {
< if (flags & LOOKUP_ONLYCONVERTING)
< flags |= LOOKUP_NO_CONVERSION;
< rval = build_method_call (exp, constructor_name_full (type),
< parms, binfo, flags);
<
< /* Private, protected, or otherwise unavailable. */
< if (rval == error_mark_node)
< {
< if (flags & LOOKUP_COMPLAIN)
< cp_error ("in base initialization for %sclass `%T'",
< TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",
< binfo);
< }
< else if (rval == NULL_TREE)
< my_friendly_abort (361);
< else
< {
< /* p. 222: if the base class assigns to `this', then that
< value is used in the derived class. */
< if ((flag_this_is_variable & 1) && alias_this)
< {
< TREE_TYPE (rval) = TREE_TYPE (current_class_decl);
< expand_assignment (current_class_decl, rval, 0, 0);
< }
< else
< expand_expr_stmt (rval);
< }
< }
---
> rval = build_method_call (exp, ctor_identifier,
> parms, binfo, flags);
> if (TREE_SIDE_EFFECTS (rval))
> expand_expr_stmt (rval);
1304d1237
< tree init_type = NULL_TREE;
1313,1315d1245
< if (init)
< {
< tree init_list = NULL_TREE;
1317c1247,1252
< if (TREE_CODE (init) == TREE_LIST)
---
> if (init && TREE_CODE (exp) == VAR_DECL
> && TREE_CODE (init) == CONSTRUCTOR
> && TREE_HAS_CONSTRUCTOR (init))
> {
> tree t = store_init_value (exp, init);
> if (!t)
1319,1461c1254
< init_list = init;
< if (TREE_CHAIN (init) == NULL_TREE)
< init = TREE_VALUE (init);
< }
<
< init_type = TREE_TYPE (init);
<
< if (TREE_CODE (init) != TREE_LIST)
< {
< if (TREE_CODE (init_type) == ERROR_MARK)
< return;
<
< #if 0
< /* These lines are found troublesome 5/11/89. */
< if (TREE_CODE (init_type) == REFERENCE_TYPE)
< init_type = TREE_TYPE (init_type);
< #endif
<
< /* This happens when we use C++'s functional cast notation.
< If the types match, then just use the TARGET_EXPR
< directly. Otherwise, we need to create the initializer
< separately from the object being initialized. */
< if (TREE_CODE (init) == TARGET_EXPR)
< {
< if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
< {
< if (TREE_CODE (exp) == VAR_DECL
< || TREE_CODE (exp) == RESULT_DECL)
< /* Unify the initialization targets. */
< DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
< else
< DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, 0, 0);
<
< expand_expr_stmt (init);
< return;
< }
< else
< {
< init = TREE_OPERAND (init, 1);
< init = build (CALL_EXPR, init_type,
< TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
< TREE_SIDE_EFFECTS (init) = 1;
< if (init_list)
< TREE_VALUE (init_list) = init;
< }
< }
<
< if (init_type == type && TREE_CODE (init) == CALL_EXPR
< #if 0
< /* It is valid to directly initialize from a CALL_EXPR
< without going through X(X&), apparently. */
< && ! TYPE_GETS_INIT_REF (type)
< #endif
< )
< {
< /* A CALL_EXPR is a legitimate form of initialization, so
< we should not print this warning message. */
< #if 0
< /* Should have gone away due to 5/11/89 change. */
< if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
< init = convert_from_reference (init);
< #endif
< expand_assignment (exp, init, 0, 0);
< if (exp == DECL_RESULT (current_function_decl))
< {
< /* Failing this assertion means that the return value
< from receives multiple initializations. */
< my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE
< || DECL_INITIAL (exp) == error_mark_node,
< 212);
< DECL_INITIAL (exp) = init;
< }
< return;
< }
< else if (init_type == type
< && TREE_CODE (init) == COND_EXPR)
< {
< /* Push value to be initialized into the cond, where possible.
< Avoid spurious warning messages when initializing the
< result of this function. */
< TREE_OPERAND (init, 1)
< = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
< if (exp == DECL_RESULT (current_function_decl))
< DECL_INITIAL (exp) = NULL_TREE;
< TREE_OPERAND (init, 2)
< = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
< if (exp == DECL_RESULT (current_function_decl))
< DECL_INITIAL (exp) = init;
< TREE_SIDE_EFFECTS (init) = 1;
< expand_expr (init, const0_rtx, VOIDmode, 0);
< free_temp_slots ();
< return;
< }
< }
<
< /* We did not know what we were initializing before. Now we do. */
< if (TREE_CODE (init) == TARGET_EXPR)
< {
< tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
<
< if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
< && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
< {
< /* In order for this to work for RESULT_DECLs, if their
< type has a constructor, then they must be BLKmode
< so that they will be meaningfully addressable. */
< tree arg = build_unary_op (ADDR_EXPR, exp, 0);
< init = TREE_OPERAND (init, 1);
< init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
< TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
< TREE_SIDE_EFFECTS (init) = 1;
< TREE_VALUE (TREE_OPERAND (init, 1))
< = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
<
< if (alias_this)
< {
< expand_assignment (current_function_decl, init, 0, 0);
< return;
< }
< if (exp == DECL_RESULT (current_function_decl))
< {
< if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
< fatal ("return value from function receives multiple initializations");
< DECL_INITIAL (exp) = init;
< }
< expand_expr_stmt (init);
< return;
< }
< }
<
< if (TREE_CODE (exp) == VAR_DECL
< && TREE_CODE (init) == CONSTRUCTOR
< && TREE_HAS_CONSTRUCTOR (init))
< {
< tree t = store_init_value (exp, init);
< if (!t)
< {
< expand_decl_init (exp);
< return;
< }
< t = build (INIT_EXPR, type, exp, init);
< TREE_SIDE_EFFECTS (t) = 1;
< expand_expr_stmt (t);
---
> expand_decl_init (exp);
1464,1515c1257,1260
<
< /* Handle this case: when calling a constructor: xyzzy foo(bar);
< which really means: xyzzy foo = bar; Ugh!
<
< More useful for this case: xyzzy *foo = new xyzzy (bar); */
<
< if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
< {
< if (init_list && TREE_CHAIN (init_list))
< {
< warning ("initializer list being treated as compound expression");
< init = convert (type, build_compound_expr (init_list));
< if (init == error_mark_node)
< return;
< }
<
< expand_assignment (exp, init, 0, 0);
<
< return;
< }
< /* See whether we can go through a type conversion operator.
< This wins over going through a non-existent constructor. If
< there is a constructor, it is ambiguous. */
< if (TREE_CODE (init) != TREE_LIST)
< {
< tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
< ? TREE_TYPE (init_type) : init_type;
<
< if (ttype != type && IS_AGGR_TYPE (ttype))
< {
< tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0);
<
< if (rval)
< {
< /* See if there is a constructor for``type'' that takes a
< ``ttype''-typed object. */
< tree parms = build_tree_list (NULL_TREE, init);
< tree as_cons = NULL_TREE;
< if (TYPE_HAS_CONSTRUCTOR (type))
< as_cons = build_method_call (exp, constructor_name_full (type),
< parms, binfo,
< LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
< if (as_cons != NULL_TREE && as_cons != error_mark_node)
< /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
< cp_error ("ambiguity between conversion to `%T' and constructor",
< type);
< else
< expand_assignment (exp, rval, 0, 0);
< return;
< }
< }
< }
---
> t = build (INIT_EXPR, type, exp, init);
> TREE_SIDE_EFFECTS (t) = 1;
> expand_expr_stmt (t);
> return;
1518,1535c1263,1265
< /* Handle default copy constructors here, does not matter if there is
< a constructor or not. */
< if (type == init_type && IS_AGGR_TYPE (type)
< && init && TREE_CODE (init) != TREE_LIST)
< expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);
< /* Not sure why this is here... */
< else if (TYPE_HAS_CONSTRUCTOR (type))
< expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);
< else if (TREE_CODE (type) == ARRAY_TYPE)
< {
< if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
< expand_vec_init (exp, exp, array_type_nelts (type), init, 0);
< else if (TYPE_VIRTUAL_P (TREE_TYPE (type)))
< sorry ("arrays of objects with virtual functions but no constructors");
< }
< else
< expand_recursive_init (binfo, true_exp, exp, init,
< CLASSTYPE_BASE_INIT_LIST (type), alias_this);
---
> /* We know that expand_default_init can handle everything we want
> at this point. */
> expand_default_init (binfo, true_exp, exp, init, alias_this, flags);
1538,1661d1267
< /* A pointer which holds the initializer. First call to
< expand_aggr_init gets this value pointed to, and sets it to init_null. */
< static tree *init_ptr, init_null;
<
< /* Subroutine of expand_recursive_init:
<
< ADDR is the address of the expression being initialized.
< INIT_LIST is the cons-list of initializations to be performed.
< ALIAS_THIS is its same, lovable self. */
< static void
< expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)
< tree binfo, true_exp, addr;
< tree init_list;
< int alias_this;
< {
< while (init_list)
< {
< if (TREE_PURPOSE (init_list))
< {
< if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL)
< {
< tree member = TREE_PURPOSE (init_list);
< tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR);
< tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member);
< if (IS_AGGR_TYPE (TREE_TYPE (member)))
< expand_aggr_init (member_base, DECL_INITIAL (member), 0, 0);
< else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE
< && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member)))
< {
< member_base = save_expr (default_conversion (member_base));
< expand_vec_init (member, member_base,
< array_type_nelts (TREE_TYPE (member)),
< DECL_INITIAL (member), 0);
< }
< else
< expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member)));
< }
< else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST)
< {
< expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this);
< expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this);
< }
< else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK)
< {
< /* Only initialize the virtual function tables if we
< are initializing the ultimate users of those vtables. */
< if (TREE_VALUE (init_list))
< {
< /* We have to ensure that the first argment to
< expand_virtual_init is in binfo's hierarchy. */
< /* Is it the case that this is exactly the right binfo? */
< /* If it is ok, then fixup expand_virtual_init, to make
< it much simpler. */
< expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0),
< addr);
< if (TREE_VALUE (init_list) == binfo
< && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
< expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
< }
< }
< else
< my_friendly_abort (49);
< }
< else if (TREE_VALUE (init_list)
< && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC)
< {
< tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR);
< expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr,
< alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)),
< LOOKUP_COMPLAIN);
<
< /* INIT_PTR is used up. */
< init_ptr = &init_null;
< }
< else
< my_friendly_abort (50);
< init_list = TREE_CHAIN (init_list);
< }
< }
<
< /* Initialize EXP with INIT. Type EXP does not have a constructor,
< but it has a baseclass with a constructor or a virtual function
< table which needs initializing.
<
< INIT_LIST is a cons-list describing what parts of EXP actually
< need to be initialized. INIT is given to the *unique*, first
< constructor within INIT_LIST. If there are multiple first
< constructors, such as with multiple inheritance, INIT must
< be zero or an ambiguity error is reported.
<
< ALIAS_THIS is passed from `expand_aggr_init'. See comments
< there. */
<
< static void
< expand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)
< tree binfo, true_exp, exp, init;
< tree init_list;
< int alias_this;
< {
< tree *old_init_ptr = init_ptr;
< tree addr = build_unary_op (ADDR_EXPR, exp, 0);
< init_ptr = &init;
<
< if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
< {
< expand_aggr_vbase_init (binfo, exp, addr, init_list);
< expand_indirect_vtbls_init (binfo, true_exp, addr, 1);
< }
< expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);
<
< if (*init_ptr)
< {
< tree type = TREE_TYPE (exp);
<
< if (TREE_CODE (type) == REFERENCE_TYPE)
< type = TREE_TYPE (type);
< if (IS_AGGR_TYPE (type))
< cp_error ("unexpected argument to constructor `%T'", type);
< else
< error ("unexpected argument to constructor");
< }
< init_ptr = old_init_ptr;
< }
<
1663a1270
>
1684c1291,1292
< && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
---
> && TREE_CODE (type) != TEMPLATE_TYPE_PARM
> && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
1692a1301,1322
> /* Report an error if TYPE is not a user-defined, aggregate type. If
> OR_ELSE is nonzero, give an error message. */
>
> int
> is_aggr_type (type, or_else)
> tree type;
> int or_else;
> {
> if (type == error_mark_node)
> return 0;
>
> if (! IS_AGGR_TYPE (type)
> && TREE_CODE (type) != TEMPLATE_TYPE_PARM
> && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
> {
> if (or_else)
> cp_error ("`%T' is not an aggregate type", type);
> return 0;
> }
> return 1;
> }
>
1693a1324
>
1714c1345,1346
< && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
---
> && TREE_CODE (type) != TEMPLATE_TYPE_PARM
> && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
1740c1372
< /* For an expression of the form CNAME :: NAME (PARMLIST), build
---
> /* For an expression of the form TYPE :: NAME (PARMLIST), build
1741a1374
>
1743,1744c1376,1377
< build_member_call (cname, name, parmlist)
< tree cname, name, parmlist;
---
> build_member_call (type, name, parmlist)
> tree type, name, parmlist;
1746,1747c1379,1380
< tree type, t;
< tree method_name = name;
---
> tree t;
> tree method_name;
1751a1385,1405
> if (TREE_CODE (name) == TEMPLATE_ID_EXPR
> && TREE_CODE (type) == NAMESPACE_DECL)
> {
> /* 'name' already refers to the decls from the namespace, since we
> hit do_identifier for template_ids. */
> my_friendly_assert (is_overloaded_fn (TREE_OPERAND (name, 0)), 980519);
> return build_x_function_call (name, parmlist, current_class_ref);
> }
>
> if (type == std_node)
> return build_x_function_call (do_scoped_id (name, 0), parmlist,
> current_class_ref);
> if (TREE_CODE (type) == NAMESPACE_DECL)
> return build_x_function_call (lookup_namespace_name (type, name),
> parmlist, current_class_ref);
>
> if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
> method_name = name;
> else
> method_name = TREE_OPERAND (name, 0);
>
1758,1760d1411
< if (TREE_CODE (cname) == SCOPE_REF)
< cname = resolve_scope_to_name (NULL_TREE, cname);
<
1763,1764c1414,1415
< if (cname && get_aggr_from_typedef (cname, 0) == 0
< && TREE_CODE (cname) == IDENTIFIER_NODE)
---
> if (type && TREE_CODE (type) == IDENTIFIER_NODE
> && get_aggr_from_typedef (type, 0) == 0)
1766c1417
< tree ns = lookup_name (cname, 0);
---
> tree ns = lookup_name (type, 0);
1769c1420
< return build_x_function_call (build_offset_ref (cname, name), parmlist, current_class_decl);
---
> return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
1773c1424
< if (cname == NULL_TREE || ! (type = get_aggr_from_typedef (cname, 1)))
---
> if (type == NULL_TREE || ! is_aggr_type (type, 1))
1782,1787d1432
< #if 0
< /* Everything can explicitly call a destructor; see 12.4 */
< if (! TYPE_HAS_DESTRUCTOR (type))
< cp_error ("type `%#T' does not have a destructor", type);
< else
< #endif
1804c1449
< else if (current_class_decl == 0)
---
> else if (current_class_ptr == 0)
1811c1456
< tree olddecl = current_class_decl;
---
> tree olddecl = current_class_ptr;
1828,1829c1473,1477
< if (t = lookup_fnfields (basetype_path, method_name, 0))
< return build_method_call (decl, method_name, parmlist, basetype_path,
---
> if ((t = lookup_fnfields (basetype_path, method_name, 0)))
> return build_method_call (decl,
> TREE_CODE (name) == TEMPLATE_ID_EXPR
> ? name : method_name,
> parmlist, basetype_path,
1852,1854c1500,1502
< if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))
< && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl)))
< return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist, NULL_TREE);
---
> if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))
> return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,
> parmlist, NULL_TREE);
1866,1867c1514,1515
< and then act as a pointer to member, for example CNAME :: FIELD
< can have its address taken by saying & CNAME :: FIELD.
---
> and then act as a pointer to member, for example TYPE :: FIELD
> can have its address taken by saying & TYPE :: FIELD.
1872a1521
>
1874,1875c1523,1524
< build_offset_ref (cname, name)
< tree cname, name;
---
> build_offset_ref (type, name)
> tree type, name;
1877,1879c1526,1528
< tree decl, type, fnfields, fields, t = error_mark_node;
< tree basetypes = NULL_TREE;
< int dtor = 0;
---
> tree decl, fnfields, fields, t = error_mark_node;
> tree basebinfo = NULL_TREE;
> tree orig_name = name;
1881,1882c1530,1532
< if (TREE_CODE (cname) == SCOPE_REF)
< cname = resolve_scope_to_name (NULL_TREE, cname);
---
> /* class templates can come in as TEMPLATE_DECLs here. */
> if (TREE_CODE (name) == TEMPLATE_DECL)
> return name;
1883a1534,1539
> if (type == std_node)
> return do_scoped_id (name, 0);
>
> if (processing_template_decl || uses_template_parms (type))
> return build_min_nt (SCOPE_REF, type, name);
>
1885,1886c1541
< if (TREE_CODE (cname) == IDENTIFIER_NODE
< && get_aggr_from_typedef (cname, 0) == 0)
---
> if (TREE_CODE (type) == NAMESPACE_DECL)
1888,1890c1543,1544
< tree ns = lookup_name (cname, 0);
< tree val;
< if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
---
> t = lookup_namespace_name (type, name);
> if (! type_unknown_p (t))
1892,1896c1546,1547
< val = lookup_namespace_name (ns, name);
< if (val)
< return val;
< cp_error ("namespace `%D' has no member named `%D'", ns, name);
< return error_mark_node;
---
> mark_used (t);
> t = convert_from_reference (t);
1897a1549
> return t;
1900c1552
< if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))
---
> if (type == NULL_TREE || ! is_aggr_type (type, 1))
1903c1555,1563
< type = IDENTIFIER_TYPE_VALUE (cname);
---
> if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
> {
> /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
> something like `a.template f<int>' or the like. For the most
> part, we treat this just like a.f. We do remember, however,
> the template-id that was used. */
> name = TREE_OPERAND (orig_name, 0);
> my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
> }
1907,1908c1567,1570
< dtor = 1;
< name = TREE_OPERAND (name, 0);
---
> if (! check_dtor_name (type, name))
> cp_error ("qualified type `%T' does not match destructor name `~%T'",
> type, TREE_OPERAND (name, 0));
> name = dtor_identifier;
1909a1572,1577
> #if 0
> /* I think this is wrong, but the draft is unclear. --jason 6/15/98 */
> else if (name == constructor_name_full (type)
> || name == constructor_name (type))
> name = ctor_identifier;
> #endif
1911c1579
< if (TYPE_SIZE (type) == 0)
---
> if (TYPE_SIZE (complete_type (type)) == 0)
1913c1581,1584
< t = IDENTIFIER_CLASS_VALUE (name);
---
> if (type == current_class_type)
> t = IDENTIFIER_CLASS_VALUE (name);
> else
> t = NULL_TREE;
1923c1594
< TREE_USED (t) = 1;
---
> mark_used (t);
1935,1941d1605
< #if 0
< if (TREE_CODE (name) == TYPE_EXPR)
< /* Pass a TYPE_DECL to build_component_type_expr. */
< return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)),
< name, NULL_TREE, 1);
< #endif
<
1943c1607
< || get_base_distance (type, current_class_type, 0, &basetypes) == -1)
---
> || get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
1945,1948c1609,1610
< basetypes = TYPE_BINFO (type);
< decl = build1 (NOP_EXPR,
< IDENTIFIER_TYPE_VALUE (cname),
< error_mark_node);
---
> basebinfo = TYPE_BINFO (type);
> decl = build1 (NOP_EXPR, type, error_mark_node);
1950,1952c1612,1613
< else if (current_class_decl == 0)
< decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname),
< error_mark_node);
---
> else if (current_class_ptr == 0)
> decl = build1 (NOP_EXPR, type, error_mark_node);
1954c1615
< decl = C_C_D;
---
> decl = current_class_ref;
1956,1957c1617,1618
< fnfields = lookup_fnfields (basetypes, name, 1);
< fields = lookup_field (basetypes, name, 0, 0);
---
> fnfields = lookup_fnfields (basebinfo, name, 1);
> fields = lookup_field (basebinfo, name, 0, 0);
1963c1624
< lookup_fnfield. */
---
> lookup_fnfield. */
1966c1627
< basetypes = TREE_PURPOSE (fnfields);
---
> extern int flag_save_memoized_contexts;
1971c1632
< if (fields)
---
> if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
1973,1987c1634,1652
< if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t))
< {
< error ("ambiguous member reference: member `%s' defined as both field and function",
< IDENTIFIER_POINTER (name));
< return error_mark_node;
< }
< if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t)))
< ;
< else if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields)))
< t = fields;
< else
< {
< error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice");
< return error_mark_node;
< }
---
> /* The FNFIELDS are going to contain functions that aren't
> necessarily templates, and templates that don't
> necessarily match the explicit template parameters. We
> save all the functions, and the explicit parameters, and
> then figure out exactly what to instantiate with what
> arguments in instantiate_type. */
>
> if (TREE_CODE (t) != OVERLOAD)
> /* The code in instantiate_type which will process this
> expects to encounter OVERLOADs, not raw functions. */
> t = ovl_cons (t, NULL_TREE);
>
> return build (OFFSET_REF,
> build_offset_type (type, unknown_type_node),
> decl,
> build (TEMPLATE_ID_EXPR,
> TREE_TYPE (t),
> t,
> TREE_OPERAND (orig_name, 1)));
1990c1655
< if (t == TREE_VALUE (fnfields))
---
> if (!really_overloaded_fn (t))
1992c1657
< extern int flag_save_memoized_contexts;
---
> tree access;
1994,1996c1659,1660
< if (DECL_CHAIN (t) == NULL_TREE || dtor)
< {
< enum access_type access;
---
> /* Get rid of a potential OVERLOAD around it */
> t = OVL_CURRENT (t);
1998,2014c1662,1669
< /* unique functions are handled easily. */
< unique:
< access = compute_access (basetypes, t);
< if (access == access_protected)
< {
< cp_error_at ("member function `%#D' is protected", t);
< error ("in this context");
< return error_mark_node;
< }
< if (access == access_private)
< {
< cp_error_at ("member function `%#D' is private", t);
< error ("in this context");
< return error_mark_node;
< }
< assemble_external (t);
< return build (OFFSET_REF, TREE_TYPE (t), decl, t);
---
> /* unique functions are handled easily. */
> basebinfo = TREE_PURPOSE (fnfields);
> access = compute_access (basebinfo, t);
> if (access == access_protected_node)
> {
> cp_error_at ("member function `%#D' is protected", t);
> error ("in this context");
> return error_mark_node;
2016,2018c1671
<
< /* overloaded functions may need more work. */
< if (cname == name)
---
> if (access == access_private_node)
2020,2025c1673,1675
< if (TYPE_HAS_DESTRUCTOR (type)
< && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE)
< {
< t = DECL_CHAIN (t);
< goto unique;
< }
---
> cp_error_at ("member function `%#D' is private", t);
> error ("in this context");
> return error_mark_node;
2027,2031c1677,1679
< /* FNFIELDS is most likely allocated on the search_obstack,
< which will go away after this class scope. If we need
< to save this value for later (either for memoization
< or for use as an initializer for a static variable), then
< do so here.
---
> mark_used (t);
> return build (OFFSET_REF, TREE_TYPE (t), decl, t);
> }
2033,2038c1681,1685
< ??? The smart thing to do for the case of saving initializers
< is to resolve them before we're done with this scope. */
< if (!TREE_PERMANENT (fnfields)
< && ((flag_save_memoized_contexts && global_bindings_p ())
< || ! allocation_temporary_p ()))
< fnfields = copy_list (fnfields);
---
> /* FNFIELDS is most likely allocated on the search_obstack,
> which will go away after this class scope. If we need
> to save this value for later (either for memoization
> or for use as an initializer for a static variable), then
> do so here.
2040,2041c1687,1692
< for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t))
< assemble_external (t);
---
> ??? The smart thing to do for the case of saving initializers
> is to resolve them before we're done with this scope. */
> if (!TREE_PERMANENT (fnfields)
> && ((flag_save_memoized_contexts && toplevel_bindings_p ())
> || ! allocation_temporary_p ()))
> fnfields = copy_list (fnfields);
2043,2046c1694,1696
< t = build_tree_list (error_mark_node, fnfields);
< TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
< return t;
< }
---
> t = build_tree_list (error_mark_node, fnfields);
> TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
> return t;
2053c1703
< t = lookup_field (basetypes, name, 1, 0);
---
> t = lookup_field (basebinfo, name, 1, 0);
2073,2075c1723,1724
< assemble_external (t);
< TREE_USED (t) = 1;
< return t;
---
> mark_used (t);
> return convert_from_reference (t);
2085c1734,1735
< if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
---
> if (TREE_CODE (t) == FUNCTION_DECL
> && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
2088,2089c1738,1740
< /* In member functions, the form `cname::name' is no longer
< equivalent to `this->cname::name'. */
---
> /* In member functions, the form `type::name' is no longer
> equivalent to `this->type::name', at least not until
> resolve_offset_ref. */
2093,2158d1743
< /* Given an object EXP and a member function reference MEMBER,
< return the address of the actual member function. */
< tree
< get_member_function (exp_addr_ptr, exp, member)
< tree *exp_addr_ptr;
< tree exp, member;
< {
< tree ctype = TREE_TYPE (exp);
< tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0));
<
< if (TYPE_VIRTUAL_P (ctype)
< || (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype)))
< {
< tree e0, e1, e3;
< tree exp_addr;
<
< /* Save away the unadulterated `this' pointer. */
< exp_addr = save_expr (*exp_addr_ptr);
<
< /* Cast function to signed integer. */
< e0 = build1 (NOP_EXPR, integer_type_node, function);
<
< /* There is a hack here that takes advantage of
< twos complement arithmetic, and the fact that
< there are more than one UNITS to the WORD.
< If the high bit is set for the `function',
< then we pretend it is a virtual function,
< and the array indexing will knock this bit
< out the top, leaving a valid index. */
< if (UNITS_PER_WORD <= 1)
< my_friendly_abort (54);
<
< e1 = build (GT_EXPR, boolean_type_node, e0, integer_zero_node);
< e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
< build_tree_list (NULL_TREE, e1)));
< e1 = save_expr (e1);
<
< if (TREE_SIDE_EFFECTS (*exp_addr_ptr))
< {
< exp = build_indirect_ref (exp_addr, NULL_PTR);
< *exp_addr_ptr = exp_addr;
< }
<
< /* This is really hairy: if the function pointer is a pointer
< to a non-virtual member function, then we can't go mucking
< with the `this' pointer (any more than we already have to
< this point). If it is a pointer to a virtual member function,
< then we have to adjust the `this' pointer according to
< what the virtual function table tells us. */
<
< e3 = build_vfn_ref (exp_addr_ptr, exp, e0);
< my_friendly_assert (e3 != error_mark_node, 213);
<
< /* Change this pointer type from `void *' to the
< type it is really supposed to be. */
< TREE_TYPE (e3) = TREE_TYPE (function);
<
< /* If non-virtual, use what we had originally. Otherwise,
< use the value we get from the virtual function table. */
< *exp_addr_ptr = build_conditional_expr (e1, exp_addr, *exp_addr_ptr);
<
< function = build_conditional_expr (e1, function, e3);
< }
< return build_indirect_ref (function, NULL_PTR);
< }
<
2172c1757,1760
< return build_unary_op (ADDR_EXPR, exp, 0);
---
> {
> cp_pedwarn ("assuming & on overloaded member function");
> return build_unary_op (ADDR_EXPR, exp, 0);
> }
2174c1762
< if (TREE_CODE (exp) != OFFSET_REF)
---
> if (TREE_CODE (exp) == OFFSET_REF)
2175a1764,1768
> member = TREE_OPERAND (exp, 1);
> base = TREE_OPERAND (exp, 0);
> }
> else
> {
2184c1777
< base = C_C_D;
---
> base = current_class_ref;
2186,2190d1778
< else
< {
< member = TREE_OPERAND (exp, 1);
< base = TREE_OPERAND (exp, 0);
< }
2194c1782,1783
< || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
---
> || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE
> || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
2201a1791,1794
> if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE
> && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE)
> return member;
>
2204c1797
< if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE)
---
> if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
2218c1811
< && (base == C_C_D
---
> && (base == current_class_ref
2222,2223c1815
< tree basetype_path;
< enum access_type access;
---
> tree basetype_path, access;
2230c1822
< base = current_class_decl;
---
> base = current_class_ptr;
2237c1829,1830
< addr = convert_pointer_to (basetype, base);
---
> /* Kludge: we need to use basetype_path now, because
> convert_pointer_to will bash it. */
2239c1832,1833
< if (access == access_public)
---
> addr = convert_pointer_to (basetype, base);
> if (access == access_public_node)
2242c1836
< if (access == access_protected)
---
> if (access == access_protected_node)
2248c1842
< if (access == access_private)
---
> if (access == access_private_node)
2257,2263c1851,1855
< /* If this is a reference to a member function, then return
< the address of the member function (which may involve going
< through the object's vtable), otherwise, return an expression
< for the dereferenced pointer-to-member construct. */
< addr = build_unary_op (ADDR_EXPR, base, 0);
<
< if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
---
> /* Ensure that we have an object. */
> if (TREE_CODE (base) == NOP_EXPR
> && TREE_OPERAND (base, 0) == error_mark_node)
> addr = error_mark_node;
> else
2265,2267c1857,1861
< basetype = DECL_CLASS_CONTEXT (member);
< addr = convert_pointer_to (basetype, addr);
< return build_unary_op (ADDR_EXPR, get_member_function (&addr, build_indirect_ref (addr, NULL_PTR), member), 0);
---
> /* If this is a reference to a member function, then return the
> address of the member function (which may involve going
> through the object's vtable), otherwise, return an expression
> for the dereferenced pointer-to-member construct. */
> addr = build_unary_op (ADDR_EXPR, base, 0);
2269c1863,1864
< else if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
---
>
> if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
2270a1866,1871
> if (addr == error_mark_node)
> {
> cp_error ("object missing in `%E'", exp);
> return error_mark_node;
> }
>
2273,2274c1874,1883
< member = convert (ptrdiff_type_node,
< build_unary_op (ADDR_EXPR, member, 0));
---
> member = cp_convert (ptrdiff_type_node,
> build_unary_op (ADDR_EXPR, member, 0));
>
> /* Pointer to data members are offset by one, so that a null
> pointer with a real value of 0 is distinguishable from an
> offset of the first member of a structure. */
> member = build_binary_op (MINUS_EXPR, member,
> cp_convert (ptrdiff_type_node, integer_one_node),
> 0);
>
2303c1912
< && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
---
> && DECL_INITIAL (decl) != error_mark_node
2321,2801d1929
< /* Friend handling routines. */
< /* Friend data structures:
<
< Lists of friend functions come from TYPE_DECL nodes. Since all
< aggregate types are automatically typedef'd, these nodes are guaranteed
< to exist.
<
< The TREE_PURPOSE of a friend list is the name of the friend,
< and its TREE_VALUE is another list.
<
< For each element of that list, either the TREE_VALUE or the TREE_PURPOSE
< will be filled in, but not both. The TREE_VALUE of that list is an
< individual function which is a friend. The TREE_PURPOSE of that list
< indicates a type in which all functions by that name are friends.
<
< Lists of friend classes come from _TYPE nodes. Love that consistency
< thang. */
<
< int
< is_friend_type (type1, type2)
< tree type1, type2;
< {
< return is_friend (type1, type2);
< }
<
< int
< is_friend (type, supplicant)
< tree type, supplicant;
< {
< int declp;
< register tree list;
<
< if (supplicant == NULL_TREE || type == NULL_TREE)
< return 0;
<
< declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd');
<
< if (declp)
< /* It's a function decl. */
< {
< tree list = DECL_FRIENDLIST (TYPE_NAME (type));
< tree name = DECL_NAME (supplicant);
< tree ctype;
<
< if (DECL_FUNCTION_MEMBER_P (supplicant))
< ctype = DECL_CLASS_CONTEXT (supplicant);
< else
< ctype = NULL_TREE;
<
< for (; list ; list = TREE_CHAIN (list))
< {
< if (name == TREE_PURPOSE (list))
< {
< tree friends = TREE_VALUE (list);
< name = DECL_ASSEMBLER_NAME (supplicant);
< for (; friends ; friends = TREE_CHAIN (friends))
< {
< if (ctype == TREE_PURPOSE (friends))
< return 1;
< if (name == DECL_ASSEMBLER_NAME (TREE_VALUE (friends)))
< return 1;
< }
< break;
< }
< }
< }
< else
< /* It's a type. */
< {
< if (type == supplicant)
< return 1;
<
< list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_NAME (type)));
< for (; list ; list = TREE_CHAIN (list))
< if (supplicant == TREE_VALUE (list))
< return 1;
< }
<
< {
< tree context;
<
< if (! declp)
< context = DECL_CONTEXT (TYPE_NAME (supplicant));
< else if (DECL_FUNCTION_MEMBER_P (supplicant))
< context = DECL_CLASS_CONTEXT (supplicant);
< else
< context = NULL_TREE;
<
< if (context)
< return is_friend (type, context);
< }
<
< return 0;
< }
<
< /* Add a new friend to the friends of the aggregate type TYPE.
< DECL is the FUNCTION_DECL of the friend being added. */
< static void
< add_friend (type, decl)
< tree type, decl;
< {
< tree typedecl = TYPE_NAME (type);
< tree list = DECL_FRIENDLIST (typedecl);
< tree name = DECL_NAME (decl);
<
< while (list)
< {
< if (name == TREE_PURPOSE (list))
< {
< tree friends = TREE_VALUE (list);
< for (; friends ; friends = TREE_CHAIN (friends))
< {
< if (decl == TREE_VALUE (friends))
< {
< cp_warning ("`%D' is already a friend of class `%T'",
< decl, type);
< cp_warning_at ("previous friend declaration of `%D'",
< TREE_VALUE (friends));
< return;
< }
< }
< TREE_VALUE (list) = tree_cons (error_mark_node, decl,
< TREE_VALUE (list));
< return;
< }
< list = TREE_CHAIN (list);
< }
< DECL_FRIENDLIST (typedecl)
< = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
< DECL_FRIENDLIST (typedecl));
< if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
< {
< tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
< TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
< if (parmtypes && TREE_CHAIN (parmtypes))
< {
< tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
< if (TREE_CODE (parmtype) == REFERENCE_TYPE
< && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
< TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
< }
< }
< }
<
< /* Declare that every member function NAME in FRIEND_TYPE
< (which may be NULL_TREE) is a friend of type TYPE. */
< static void
< add_friends (type, name, friend_type)
< tree type, name, friend_type;
< {
< tree typedecl = TYPE_NAME (type);
< tree list = DECL_FRIENDLIST (typedecl);
<
< while (list)
< {
< if (name == TREE_PURPOSE (list))
< {
< tree friends = TREE_VALUE (list);
< while (friends && TREE_PURPOSE (friends) != friend_type)
< friends = TREE_CHAIN (friends);
< if (friends)
< if (friend_type)
< warning ("method `%s::%s' is already a friend of class",
< TYPE_NAME_STRING (friend_type),
< IDENTIFIER_POINTER (name));
< else
< warning ("function `%s' is already a friend of class `%s'",
< IDENTIFIER_POINTER (name),
< IDENTIFIER_POINTER (DECL_NAME (typedecl)));
< else
< TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE,
< TREE_VALUE (list));
< return;
< }
< list = TREE_CHAIN (list);
< }
< DECL_FRIENDLIST (typedecl) =
< tree_cons (name,
< build_tree_list (friend_type, NULL_TREE),
< DECL_FRIENDLIST (typedecl));
< if (! strncmp (IDENTIFIER_POINTER (name),
< IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
< strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
< {
< TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
< sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
< }
< }
<
< /* Set up a cross reference so that type TYPE will make member function
< CTYPE::DECL a friend when CTYPE is finally defined. For more than
< one, set up a cross reference so that functions with the name DECL
< and type CTYPE know that they are friends of TYPE. */
< static void
< xref_friend (type, decl, ctype)
< tree type, decl, ctype;
< {
< tree friend_decl = TYPE_NAME (ctype);
< #if 0
< tree typedecl = TYPE_NAME (type);
< tree t = tree_cons (NULL_TREE, ctype, DECL_UNDEFINED_FRIENDS (typedecl));
<
< DECL_UNDEFINED_FRIENDS (typedecl) = t;
< #else
< tree t = 0;
< #endif
< SET_DECL_WAITING_FRIENDS (friend_decl,
< tree_cons (type, t,
< DECL_WAITING_FRIENDS (friend_decl)));
< TREE_TYPE (DECL_WAITING_FRIENDS (friend_decl)) = decl;
< }
<
< /* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
< been defined, we make all of its member functions friends of
< TYPE. If not, we make it a pending friend, which can later be added
< when its definition is seen. If a type is defined, then its TYPE_DECL's
< DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend
< classes that are not defined. If a type has not yet been defined,
< then the DECL_WAITING_FRIENDS contains a list of types
< waiting to make it their friend. Note that these two can both
< be in use at the same time! */
< void
< make_friend_class (type, friend_type)
< tree type, friend_type;
< {
< tree classes;
<
< if (IS_SIGNATURE (type))
< {
< error ("`friend' declaration in signature definition");
< return;
< }
< if (IS_SIGNATURE (friend_type))
< {
< error ("signature type `%s' declared `friend'",
< IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (friend_type))));
< return;
< }
< if (type == friend_type)
< {
< pedwarn ("class `%s' is implicitly friends with itself",
< TYPE_NAME_STRING (type));
< return;
< }
<
< GNU_xref_hier (TYPE_NAME_STRING (type),
< TYPE_NAME_STRING (friend_type), 0, 0, 1);
<
< classes = CLASSTYPE_FRIEND_CLASSES (type);
< while (classes && TREE_VALUE (classes) != friend_type)
< classes = TREE_CHAIN (classes);
< if (classes)
< warning ("class `%s' is already friends with class `%s'",
< TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type));
< else
< {
< CLASSTYPE_FRIEND_CLASSES (type)
< = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
< }
< }
<
< /* Main friend processor. This is large, and for modularity purposes,
< has been removed from grokdeclarator. It returns `void_type_node'
< to indicate that something happened, though a FIELD_DECL is
< not returned.
<
< CTYPE is the class this friend belongs to.
<
< DECLARATOR is the name of the friend.
<
< DECL is the FUNCTION_DECL that the friend is.
<
< In case we are parsing a friend which is part of an inline
< definition, we will need to store PARM_DECL chain that comes
< with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
<
< FLAGS is just used for `grokclassfn'.
<
< QUALS say what special qualifies should apply to the object
< pointed to by `this'. */
< tree
< do_friend (ctype, declarator, decl, parmdecls, flags, quals)
< tree ctype, declarator, decl, parmdecls;
< enum overload_flags flags;
< tree quals;
< {
< /* Every decl that gets here is a friend of something. */
< DECL_FRIEND_P (decl) = 1;
<
< if (ctype)
< {
< tree cname = TYPE_NAME (ctype);
< if (TREE_CODE (cname) == TYPE_DECL)
< cname = DECL_NAME (cname);
<
< /* A method friend. */
< if (TREE_CODE (decl) == FUNCTION_DECL)
< {
< if (flags == NO_SPECIAL && ctype && declarator == cname)
< DECL_CONSTRUCTOR_P (decl) = 1;
<
< /* This will set up DECL_ARGUMENTS for us. */
< grokclassfn (ctype, cname, decl, flags, quals);
< if (TYPE_SIZE (ctype) != 0)
< check_classfn (ctype, cname, decl);
<
< if (TREE_TYPE (decl) != error_mark_node)
< {
< if (TYPE_SIZE (ctype))
< {
< /* We don't call pushdecl here yet, or ever on this
< actual FUNCTION_DECL. We must preserve its TREE_CHAIN
< until the end. */
< make_decl_rtl (decl, NULL_PTR, 1);
< add_friend (current_class_type, decl);
< }
< else
< {
< register char *classname
< = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (ctype)));
<
< error ("member declared as friend before type `%s' defined",
< classname);
< }
< }
< }
< else
< {
< /* Possibly a bunch of method friends. */
<
< /* Get the class they belong to. */
< tree ctype = IDENTIFIER_TYPE_VALUE (cname);
<
< /* This class is defined, use its methods now. */
< if (TYPE_SIZE (ctype))
< {
< tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
< if (fields)
< add_friends (current_class_type, declarator, ctype);
< else
< error ("method `%s' is not a member of class `%s'",
< IDENTIFIER_POINTER (declarator),
< IDENTIFIER_POINTER (cname));
< }
< else
< /* Note: DECLARATOR actually has more than one; in this
< case, we're making sure that fns with the name DECLARATOR
< and type CTYPE know they are friends of the current
< class type. */
< xref_friend (current_class_type, declarator, ctype);
< decl = void_type_node;
< }
< }
< else if (TREE_CODE (decl) == FUNCTION_DECL
< && ((IDENTIFIER_LENGTH (declarator) == 4
< && IDENTIFIER_POINTER (declarator)[0] == 'm'
< && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
< || (IDENTIFIER_LENGTH (declarator) > 10
< && IDENTIFIER_POINTER (declarator)[0] == '_'
< && IDENTIFIER_POINTER (declarator)[1] == '_'
< && strncmp (IDENTIFIER_POINTER (declarator)+2,
< "builtin_", 8) == 0)))
< {
< /* raw "main", and builtin functions never gets overloaded,
< but they can become friends. */
< add_friend (current_class_type, decl);
< DECL_FRIEND_P (decl) = 1;
< decl = void_type_node;
< }
< /* A global friend.
< @@ or possibly a friend from a base class ?!? */
< else if (TREE_CODE (decl) == FUNCTION_DECL)
< {
< /* Friends must all go through the overload machinery,
< even though they may not technically be overloaded.
<
< Note that because classes all wind up being top-level
< in their scope, their friend wind up in top-level scope as well. */
< DECL_ASSEMBLER_NAME (decl)
< = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
< TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
< DECL_ARGUMENTS (decl) = parmdecls;
< DECL_CLASS_CONTEXT (decl) = current_class_type;
<
< /* We can call pushdecl here, because the TREE_CHAIN of this
< FUNCTION_DECL is not needed for other purposes. */
< decl = pushdecl (decl);
<
< make_decl_rtl (decl, NULL_PTR, 1);
< add_friend (current_class_type, decl);
<
< DECL_FRIEND_P (decl) = 1;
< #if 0
< TREE_OVERLOADED (declarator) = 1;
< #endif
< }
< else
< {
< /* @@ Should be able to ingest later definitions of this function
< before use. */
< tree decl = lookup_name_nonclass (declarator);
< if (decl == NULL_TREE)
< {
< warning ("implicitly declaring `%s' as struct",
< IDENTIFIER_POINTER (declarator));
< decl = xref_tag (record_type_node, declarator, NULL_TREE, 1);
< decl = TYPE_NAME (decl);
< }
<
< /* Allow abbreviated declarations of overloaded functions,
< but not if those functions are really class names. */
< if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
< {
< warning ("`friend %s' archaic, use `friend class %s' instead",
< IDENTIFIER_POINTER (declarator),
< IDENTIFIER_POINTER (declarator));
< decl = TREE_TYPE (TREE_PURPOSE (decl));
< }
<
< if (TREE_CODE (decl) == TREE_LIST)
< add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
< else
< make_friend_class (current_class_type, TREE_TYPE (decl));
< decl = void_type_node;
< }
< return decl;
< }
<
< /* TYPE has now been defined. It may, however, have a number of things
< waiting make make it their friend. We resolve these references
< here. */
< void
< embrace_waiting_friends (type)
< tree type;
< {
< tree decl = TYPE_NAME (type);
< tree waiters;
<
< if (TREE_CODE (decl) != TYPE_DECL)
< return;
<
< for (waiters = DECL_WAITING_FRIENDS (decl); waiters;
< waiters = TREE_CHAIN (waiters))
< {
< tree waiter = TREE_PURPOSE (waiters);
< #if 0
< tree waiter_prev = TREE_VALUE (waiters);
< #endif
< tree decl = TREE_TYPE (waiters);
< tree name = decl ? (TREE_CODE (decl) == IDENTIFIER_NODE
< ? decl : DECL_NAME (decl)) : NULL_TREE;
< if (name)
< {
< /* @@ There may be work to be done since we have not verified
< @@ consistency between original and friend declarations
< @@ of the functions waiting to become friends. */
< tree field = lookup_fnfields (TYPE_BINFO (type), name, 0);
< if (field)
< if (decl == name)
< add_friends (waiter, name, type);
< else
< add_friend (waiter, decl);
< else
< error_with_file_and_line (DECL_SOURCE_FILE (TYPE_NAME (waiter)),
< DECL_SOURCE_LINE (TYPE_NAME (waiter)),
< "no method `%s' defined in class `%s' to be friend",
< IDENTIFIER_POINTER (DECL_NAME (TREE_TYPE (waiters))),
< TYPE_NAME_STRING (type));
< }
< else
< make_friend_class (type, waiter);
<
< #if 0
< if (TREE_CHAIN (waiter_prev))
< TREE_CHAIN (waiter_prev) = TREE_CHAIN (TREE_CHAIN (waiter_prev));
< else
< DECL_UNDEFINED_FRIENDS (TYPE_NAME (waiter)) = NULL_TREE;
< #endif
< }
< }
<
2807c1935
< tree
---
> static tree
2813c1941
< tree rval = build (CALL_EXPR, type, node, arglist, 0);
---
> tree rval = build (CALL_EXPR, type, node, arglist, NULL_TREE);
2854,2856c1982,1983
< tree type, true_type, size, rval;
< tree nelts;
< tree alloc_expr, alloc_temp;
---
> tree type, rval;
> tree nelts = NULL_TREE, t;
2858d1984
< enum tree_code code = NEW_EXPR;
2869c1995
< int old_immediate_size_expand;
---
> int old_immediate_size_expand = 0;
2905a2032,2036
> else if (processing_template_decl)
> {
> nelts = this_nelts;
> absdcl = TREE_OPERAND (absdcl, 0);
> }
2908c2039
< this_nelts = save_expr (convert (sizetype, this_nelts));
---
> this_nelts = save_expr (cp_convert (sizetype, this_nelts));
2928c2059
< type = true_type = groktypename (decl);
---
> type = groktypename (decl);
2948c2079
< decl = TYPE_NAME (type);
---
> decl = TYPE_MAIN_DECL (type);
2957d2087
< true_type = type;
2962d2091
< true_type = type;
2967,2968c2096
< true_type = type;
< decl = TYPE_NAME (type);
---
> decl = TYPE_MAIN_DECL (type);
2970a2099,2112
> if (processing_template_decl)
> {
> if (has_array)
> t = min_tree_cons (min_tree_cons (NULL_TREE, type, NULL_TREE),
> build_min_nt (ARRAY_REF, NULL_TREE, nelts),
> NULL_TREE);
> else
> t = type;
>
> rval = build_min_nt (NEW_EXPR, placement, t, init);
> NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
> return rval;
> }
>
2977c2119
< type = true_type = TREE_TYPE (type);
---
> type = TREE_TYPE (type);
2993c2135
< type = true_type = TREE_TYPE (type);
---
> type = TREE_TYPE (type);
2995a2138,2186
> if (has_array)
> t = build_nt (ARRAY_REF, type, nelts);
> else
> t = type;
>
> rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
> NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
> TREE_SIDE_EFFECTS (rval) = 1;
>
> /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
> rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
> TREE_NO_UNUSED_WARNING (rval) = 1;
>
> if (pending_sizes)
> rval = build_compound_expr (chainon (pending_sizes,
> build_expr_list (NULL_TREE, rval)));
>
> return rval;
> }
>
> /* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
> value is immediately handed to expand_expr. */
>
> tree
> build_new_1 (exp)
> tree exp;
> {
> tree placement, init;
> tree type, true_type, size, rval;
> tree nelts = NULL_TREE;
> tree alloc_expr, alloc_node = NULL_TREE;
> int has_array = 0;
> enum tree_code code = NEW_EXPR;
> int use_cookie, nothrow, check_new;
> int use_global_new;
>
> placement = TREE_OPERAND (exp, 0);
> type = TREE_OPERAND (exp, 1);
> init = TREE_OPERAND (exp, 2);
> use_global_new = NEW_EXPR_USE_GLOBAL (exp);
>
> if (TREE_CODE (type) == ARRAY_REF)
> {
> has_array = 1;
> nelts = TREE_OPERAND (type, 1);
> type = TREE_OPERAND (type, 0);
> }
> true_type = type;
>
3006a2198,2201
>
> if (!complete_type_or_else (true_type))
> return error_mark_node;
>
3013c2208
< if (true_type == void_type_node)
---
> if (TREE_CODE (true_type) == VOID_TYPE)
3019,3024d2213
< if (TYPE_SIZE (true_type) == 0)
< {
< incomplete_type_error (0, true_type);
< return error_mark_node;
< }
<
3037a2227
> #if 1
3039,3040c2229,2242
< array. */
< if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
---
> array, if this isn't the default placement new. */
>
> use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
> && ! (placement && ! TREE_CHAIN (placement)
> && TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
> #else
> /* Get a little extra space to store a couple of things before the new'ed
> array, if this is either non-placement new or new (nothrow). */
>
> use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
> && (! placement || nothrow));
> #endif
>
> if (use_cookie)
3048,3055d2249
< code = VEC_NEW_EXPR;
<
< /* Allocate the object. */
< if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
< && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
< rval = build_opfncall (code, LOOKUP_NORMAL,
< build_pointer_type (true_type), size, placement);
< else if (placement)
3057,3059c2251,2254
< rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
< ptr_type_node, size, placement);
< rval = convert (build_pointer_type (true_type), rval);
---
> code = VEC_NEW_EXPR;
>
> if (init && pedantic)
> cp_pedwarn ("initialization in array new");
3061,3062c2256,2260
< else if (! has_array && flag_this_is_variable > 0
< && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
---
>
> /* Allocate the object. */
>
> if (! has_array && ! placement && flag_this_is_variable > 0
> && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
3074,3088c2272,2285
< rval = build_builtin_call (build_pointer_type (true_type),
< has_array ? BIVN : BIN,
< build_tree_list (NULL_TREE, size));
< #if 0
< /* See comment above as to why this is disabled. */
< if (alignment)
< {
< rval = build (PLUS_EXPR, build_pointer_type (true_type), rval,
< alignment);
< rval = build (BIT_AND_EXPR, build_pointer_type (true_type),
< rval, build1 (BIT_NOT_EXPR, integer_type_node,
< alignment));
< }
< #endif
< TREE_CALLS_NEW (rval) = 1;
---
> int susp;
>
> if (flag_exceptions)
> /* We will use RVAL when generating an exception handler for
> this new-expression, so we must save it. */
> susp = suspend_momentary ();
>
> rval = build_op_new_call
> (code, true_type, expr_tree_cons (NULL_TREE, size, placement),
> LOOKUP_NORMAL | (use_global_new * LOOKUP_GLOBAL));
> rval = cp_convert (build_pointer_type (true_type), rval);
>
> if (flag_exceptions)
> resume_momentary (susp);
3091c2288,2299
< if (flag_check_new && rval)
---
> /* unless an allocation function is declared with an empty excep-
> tion-specification (_except.spec_), throw(), it indicates failure to
> allocate storage by throwing a bad_alloc exception (clause _except_,
> _lib.bad.alloc_); it returns a non-null pointer otherwise If the allo-
> cation function is declared with an empty exception-specification,
> throw(), it returns null to indicate failure to allocate storage and a
> non-null pointer otherwise.
>
> So check for a null exception spec on the op new we just called. */
>
> nothrow = 0;
> if (rval)
3093,3095c2301,2305
< /* For array new, we need to make sure that the call to new is
< not expanded as part of the RTL_EXPR for the initialization,
< so we can't just use save_expr here. */
---
> /* The CALL_EXPR. */
> tree t = TREE_OPERAND (rval, 0);
> /* The function. */
> t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
> t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
3097,3100c2307,2308
< alloc_temp = get_temp_name (TREE_TYPE (rval), 0);
< alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval);
< TREE_SIDE_EFFECTS (alloc_expr) = 1;
< rval = alloc_temp;
---
> if (t && TREE_VALUE (t) == NULL_TREE)
> nothrow = 1;
3101a2310,2316
> check_new = flag_check_new || nothrow;
>
> if ((check_new || flag_exceptions) && rval)
> {
> alloc_expr = get_target_expr (rval);
> alloc_node = rval = TREE_OPERAND (alloc_expr, 0);
> }
3109c2324
< if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) && rval != NULL_TREE)
---
> if (use_cookie && rval != NULL_TREE)
3113,3114c2328
< rval = convert (ptr_type_node, rval); /* convert to void * first */
< rval = convert (string_type_node, rval); /* lets not add void* and ints */
---
> rval = convert (string_type_node, rval); /* for ptr arithmetic */
3117c2331,2332
< cookie = build_indirect_ref (build (MINUS_EXPR, build_pointer_type (BI_header_type),
---
> cookie = build_indirect_ref (build (MINUS_EXPR,
> build_pointer_type (BI_header_type),
3120c2335,2336
< build_component_ref (cookie, nc_nelts_field_id, 0, 0),
---
> build_component_ref (cookie, nc_nelts_field_id,
> NULL_TREE, 0),
3123,3127c2339,2342
< rval = convert (build_pointer_type (true_type), rval);
< TREE_CALLS_NEW (rval) = 1;
< TREE_SIDE_EFFECTS (rval) = 1;
< rval = build_compound_expr (tree_cons (NULL_TREE, exp1,
< build_tree_list (NULL_TREE, rval)));
---
> rval = cp_convert (build_pointer_type (true_type), rval);
> rval = build_compound_expr
> (expr_tree_cons (NULL_TREE, exp1,
> build_expr_list (NULL_TREE, rval)));
3166d2380
< TREE_CALLS_NEW (rval) = 1;
3178c2392
< init = tree_cons (NULL_TREE, integer_one_node, init);
---
> init = expr_tree_cons (NULL_TREE, integer_one_node, init);
3187,3188c2401,2402
< newrval = build_method_call (newrval, constructor_name_full (true_type),
< init, NULL_TREE, flags);
---
> newrval = build_method_call (newrval, ctor_identifier,
> init, TYPE_BINFO (true_type), flags);
3190,3200c2404,2405
< if (newrval)
< {
< rval = newrval;
< TREE_HAS_CONSTRUCTOR (rval) = 1;
< }
< else
< rval = error_mark_node;
< }
< else if (current_function_decl == NULL_TREE)
< {
< extern tree static_aggregates;
---
> if (newrval == NULL_TREE || newrval == error_mark_node)
> return error_mark_node;
3202,3211c2407,2408
< /* In case of static initialization, SAVE_EXPR is good enough. */
< rval = save_expr (rval);
< rval = copy_to_permanent (rval);
< init = copy_to_permanent (init);
< init = expand_vec_init (decl, rval,
< build_binary_op (MINUS_EXPR, nelts,
< integer_one_node, 1),
< init, 0);
< init = copy_to_permanent (init);
< static_aggregates = perm_tree_cons (init, rval, static_aggregates);
---
> rval = newrval;
> TREE_HAS_CONSTRUCTOR (rval) = 1;
3213a2411,2418
> rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
> save_expr (rval), init, nelts);
>
> /* If any part of the object initialization terminates by throwing
> an exception and the new-expression does not contain a
> new-placement, then the deallocation function is called to free
> the memory in which the object was being constructed. */
> if (flag_exceptions && alloc_expr)
3215,3219c2420,2422
< /* Have to wrap this in RTL_EXPR for two cases:
< in base or member initialization and if we
< are a branch of a ?: operator. Since we
< can't easily know the latter, just do it always. */
< tree xval = make_node (RTL_EXPR);
---
> 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);
3221,3226c2424,2427
< /* If we want to check the value of the allocation expression,
< and the number of elements in the array is not a constant, we
< *must* expand the SAVE_EXPR for nelts in alloc_expr before we
< expand it in the actual initialization. So we need to build up
< an RTL_EXPR for alloc_expr. Sigh. */
< if (alloc_expr && ! TREE_CONSTANT (nelts))
---
> /* All cleanups must last longer than normal. */
> int yes = suspend_momentary ();
>
> if (placement)
3228,3241c2429,2434
< tree xval = make_node (RTL_EXPR);
< rtx rtxval;
< TREE_TYPE (xval) = TREE_TYPE (alloc_expr);
< do_pending_stack_adjust ();
< start_sequence_for_rtl_expr (xval);
< emit_note (0, -1);
< rtxval = expand_expr (alloc_expr, NULL, VOIDmode, 0);
< do_pending_stack_adjust ();
< TREE_SIDE_EFFECTS (xval) = 1;
< RTL_EXPR_SEQUENCE (xval) = get_insns ();
< end_sequence ();
< RTL_EXPR_RTL (xval) = rtxval;
< TREE_TYPE (xval) = TREE_TYPE (alloc_expr);
< alloc_expr = xval;
---
> flags |= LOOKUP_SPECULATIVELY;
>
> /* We expect alloc_expr to look like a TARGET_EXPR around
> a NOP_EXPR around the CALL_EXPR we want. */
> fn = TREE_OPERAND (alloc_expr, 1);
> fn = TREE_OPERAND (fn, 0);
3244,3246c2437,2438
< TREE_TYPE (xval) = TREE_TYPE (rval);
< do_pending_stack_adjust ();
< start_sequence_for_rtl_expr (xval);
---
> /* Copy size to the saveable obstack. */
> size = copy_node (size);
3248,3249c2440
< /* As a matter of principle, `start_sequence' should do this. */
< emit_note (0, -1);
---
> cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
3251,3255c2442
< rval = save_expr (rval);
< rval = expand_vec_init (decl, rval,
< build_binary_op (MINUS_EXPR, nelts,
< integer_one_node, 1),
< init, 0);
---
> resume_momentary (yes);
3257c2444,2447
< do_pending_stack_adjust ();
---
> /* Ack! First we allocate the memory. Then we set our sentry
> variable to true, and expand a cleanup that deletes the memory
> if sentry is true. Then we run the constructor and store the
> returned pointer in buf. Then we clear sentry and return buf. */
3259,3264c2449
< TREE_SIDE_EFFECTS (xval) = 1;
< TREE_CALLS_NEW (xval) = 1;
< RTL_EXPR_SEQUENCE (xval) = get_insns ();
< end_sequence ();
<
< if (TREE_CODE (rval) == SAVE_EXPR)
---
> if (cleanup)
3266,3269c2451,2483
< /* Errors may cause this to not get evaluated. */
< if (SAVE_EXPR_RTL (rval) == 0)
< SAVE_EXPR_RTL (rval) = const0_rtx;
< RTL_EXPR_RTL (xval) = SAVE_EXPR_RTL (rval);
---
> #if 0
> /* Disable this until flow is fixed so that it doesn't
> think the initialization of sentry is a dead write. */
> tree end, sentry, begin, buf, t = TREE_TYPE (rval);
>
> begin = get_target_expr (boolean_true_node);
> sentry = TREE_OPERAND (begin, 0);
>
> yes = suspend_momentary ();
> TREE_OPERAND (begin, 2)
> = build (COND_EXPR, void_type_node, sentry,
> cleanup, void_zero_node);
> resume_momentary (yes);
>
> rval = get_target_expr (rval);
>
> end = build (MODIFY_EXPR, TREE_TYPE (sentry),
> sentry, boolean_false_node);
> TREE_SIDE_EFFECTS (end) = 1;
>
> buf = TREE_OPERAND (rval, 0);
>
> rval = build (COMPOUND_EXPR, t, begin,
> build (COMPOUND_EXPR, t, rval,
> build (COMPOUND_EXPR, t, end, buf)));
> #else
> /* FIXME: this is a workaround for a crash due to overlapping
> exception regions. Cleanups shouldn't really happen here. */
> rval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (rval), rval);
>
> rval = build (TRY_CATCH_EXPR, TREE_TYPE (rval), rval, cleanup);
> rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
> #endif
3271,3276d2484
< else
< {
< my_friendly_assert (TREE_CODE (rval) == VAR_DECL, 217);
< RTL_EXPR_RTL (xval) = DECL_RTL (rval);
< }
< rval = xval;
3284c2492
< if (alloc_expr)
---
> if (alloc_expr && rval == alloc_node)
3286,3294c2494,2495
< /* Did we modify the storage? */
< if (rval != alloc_temp)
< {
< tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
< integer_zero_node, 1);
< rval = build_conditional_expr (ifexp, rval, alloc_temp);
< }
< else
< rval = alloc_expr;
---
> rval = TREE_OPERAND (alloc_expr, 1);
> alloc_expr = NULL_TREE;
3297c2498
< if (rval && TREE_TYPE (rval) != build_pointer_type (type))
---
> if (check_new && alloc_expr)
3299,3300c2500,2503
< /* The type of new int [3][3] is not int *, but int [3] * */
< rval = build_c_cast (build_pointer_type (type), rval, 0);
---
> /* Did we modify the storage? */
> tree ifexp = build_binary_op (NE_EXPR, alloc_node,
> integer_zero_node, 1);
> rval = build_conditional_expr (ifexp, rval, alloc_node);
3303,3305c2506,2507
< if (pending_sizes)
< rval = build_compound_expr (chainon (pending_sizes,
< build_tree_list (NULL_TREE, rval)));
---
> if (alloc_expr)
> rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
3307c2509
< if (flag_gc)
---
> if (rval && TREE_TYPE (rval) != build_pointer_type (type))
3309,3322c2511,2512
< extern tree gc_visible;
< tree objbits;
< tree update_expr;
<
< rval = save_expr (rval);
< /* We don't need a `headof' operation to do this because
< we know where the object starts. */
< objbits = build1 (INDIRECT_REF, unsigned_type_node,
< build (MINUS_EXPR, ptr_type_node,
< rval, c_sizeof_nowarn (unsigned_type_node)));
< update_expr = build_modify_expr (objbits, BIT_IOR_EXPR, gc_visible);
< rval = build_compound_expr (tree_cons (NULL_TREE, rval,
< tree_cons (NULL_TREE, update_expr,
< build_tree_list (NULL_TREE, rval))));
---
> /* The type of new int [3][3] is not int *, but int [3] * */
> rval = build_c_cast (build_pointer_type (type), rval);
3336c2526
< tree ptype = build_pointer_type (type);
---
> tree ptype = build_pointer_type (type = complete_type (type));
3358,3360d2547
< /* This is the BLOCK to record the symbol binding for debugging. */
< tree block;
<
3376c2563
< controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
---
> controller = build (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
3378,3379d2564
< block = build_block (tbase, 0, 0, 0, 0);
< add_block_current_level (block);
3384,3388c2569,2573
< tree base_tbd = convert (ptype,
< build_binary_op (MINUS_EXPR,
< convert (ptr_type_node, base),
< BI_header_size,
< 1));
---
> tree base_tbd = cp_convert (ptype,
> build_binary_op (MINUS_EXPR,
> cp_convert (ptr_type_node, base),
> BI_header_size,
> 1));
3391c2576
< body = build_tree_list (NULL_TREE,
---
> body = build_expr_list (NULL_TREE,
3403c2588
< body = tree_cons (NULL_TREE,
---
> body = expr_tree_cons (NULL_TREE,
3408c2593
< body = tree_cons (NULL_TREE,
---
> body = expr_tree_cons (NULL_TREE,
3412c2597
< body = tree_cons (NULL_TREE,
---
> body = expr_tree_cons (NULL_TREE,
3419,3420c2604,2605
< loop = tree_cons (NULL_TREE, tbase_init,
< tree_cons (NULL_TREE, loop, NULL_TREE));
---
> loop = expr_tree_cons (NULL_TREE, tbase_init,
> expr_tree_cons (NULL_TREE, loop, NULL_TREE));
3441,3446c2626,2631
< base_tbd = convert (ptype,
< build_binary_op (MINUS_EXPR,
< convert (string_type_node, base),
< BI_header_size,
< 1));
< /* True size with header. */
---
> base_tbd = cp_convert (ptype,
> build_binary_op (MINUS_EXPR,
> cp_convert (string_type_node, base),
> BI_header_size,
> 1));
> /* True size with header. */
3461,3462c2646,2647
< body = tree_cons (NULL_TREE, loop,
< tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
---
> body = expr_tree_cons (NULL_TREE, loop,
> expr_tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
3480c2665
< return convert (void_type_node, body);
---
> return cp_convert (void_type_node, body);
3486a2672
>
3523c2709
< maxindex = convert (integer_type_node, maxindex);
---
> maxindex = cp_convert (ptrdiff_type_node, maxindex);
3541c2727
< convert (build_pointer_type (type), null_pointer_node));
---
> cp_convert (build_pointer_type (type), null_pointer_node));
3543c2729
< base = convert (build_pointer_type (type), base);
---
> base = cp_convert (build_pointer_type (type), base);
3549c2735
< && TREE_TYPE (init) == TREE_TYPE (decl))
---
> && (! decl || TREE_TYPE (init) == TREE_TYPE (decl)))
3577c2763
< iterator = get_temp_regvar (integer_type_node,
---
> iterator = get_temp_regvar (ptrdiff_type_node,
3599c2785
< iterator = get_temp_regvar (integer_type_node, maxindex);
---
> iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
3601a2788
> itype = NULL_TREE;
3632c2819
< start_protect ();
---
> expand_eh_region_start ();
3634a2822,2824
> /* The initialization of each array element is a full-expression. */
> expand_start_target_temps ();
>
3669a2860,2863
>
> /* Cleanup any temporaries needed for the initial value. */
> expand_end_target_temps ();
>
3672c2866
< build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
---
> build (PREDECREMENT_EXPR, ptrdiff_type_node, iterator, integer_one_node), minus_one));
3681,3687c2875,2903
< if (TYPE_NEEDS_DESTRUCTOR (type))
< end_protect (build_array_eh_cleanup (rval,
< build_binary_op (MINUS_EXPR,
< maxindex,
< iterator,
< 1),
< type));
---
> if (TYPE_NEEDS_DESTRUCTOR (type) && flag_exceptions)
> {
> /* We have to ensure that this can live to the cleanup
> expansion time, since we know it is only ever needed
> once, generate code now. */
> push_obstacks_nochange ();
> resume_temporary_allocation ();
> {
> tree e1, cleanup = make_node (RTL_EXPR);
> TREE_TYPE (cleanup) = void_type_node;
> RTL_EXPR_RTL (cleanup) = const0_rtx;
> TREE_SIDE_EFFECTS (cleanup) = 1;
> do_pending_stack_adjust ();
> start_sequence_for_rtl_expr (cleanup);
>
> e1 = build_array_eh_cleanup
> (rval,
> build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
> type);
> expand_expr (e1, const0_rtx, VOIDmode, EXPAND_NORMAL);
> do_pending_stack_adjust ();
> RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
> end_sequence ();
>
> cleanup = protect_with_terminate (cleanup);
> expand_eh_region_end (cleanup);
> }
> pop_obstacks ();
> }
3711a2928
>
3720d2936
< tree rval;
3721a2938
> int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL);
3723,3729c2940
< if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
< && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete)))
< rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
< else
< rval = build_builtin_call (void_type_node, use_vec_delete ? BIVD : BID,
< build_tree_list (NULL_TREE, addr));
< return rval;
---
> return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
3742a2954
>
3750d2961
< tree function, parms;
3754d2964
< int ptr;
3769,3773c2979,2980
< if (TYPE_SIZE (type) == 0)
< {
< incomplete_type_error (0, type);
< return error_mark_node;
< }
---
> if (!complete_type_or_else (type))
> return error_mark_node;
3780c2987
< build_tree_list (NULL_TREE, addr));
---
> build_expr_list (NULL_TREE, addr));
3788d2994
< ptr = 1;
3801d3006
< c_sizeof_nowarn (TREE_TYPE (type)),
3819,3824c3024
< if (TREE_CODE (addr) == NOP_EXPR
< && TREE_OPERAND (addr, 0) == current_class_decl)
< ref = C_C_D;
< else
< ref = build_indirect_ref (addr, NULL_PTR);
< ptr = 0;
---
> ref = build_indirect_ref (addr, NULL_PTR);
3834,3845c3034,3037
< /* Pass the size of the object down to the operator delete() in
< addition to the ADDR. */
< if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
< {
< tree virtual_size = c_sizeof_nowarn (type);
< return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
< virtual_size, NULL_TREE);
< }
<
< /* Call the builtin operator delete. */
< return build_builtin_call (void_type_node, BID,
< build_tree_list (NULL_TREE, addr));
---
> return build_op_delete_call
> (DELETE_EXPR, addr, c_sizeof_nowarn (type),
> LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
> NULL_TREE);
3847d3038
< parms = build_tree_list (NULL_TREE, addr);
3854,3855d3044
< tree dtor = DECL_MAIN_VARIANT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0));
< tree basetypes = TYPE_BINFO (type);
3857a3047
> tree ifexp;
3864c3054
< (void_type_node, BID, build_tree_list (NULL_TREE, addr));
---
> (void_type_node, BID, build_expr_list (NULL_TREE, addr));
3877,3879c3067,3069
< if (flags & LOOKUP_PROTECT)
< {
< enum access_type access = compute_access (basetypes, dtor);
---
> expr = build_method_call
> (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
> NULL_TREE, flags);
3881,3893c3071,3072
< if (access == access_private)
< {
< if (flags & LOOKUP_COMPLAIN)
< cp_error ("destructor for type `%T' is private in this scope", type);
< return error_mark_node;
< }
< else if (access == access_protected)
< {
< if (flags & LOOKUP_COMPLAIN)
< cp_error ("destructor for type `%T' is protected in this scope", type);
< return error_mark_node;
< }
< }
---
> if (do_delete)
> expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
3895,3942c3074,3076
< /* Once we are in a destructor, try not going through
< the virtual function table to find the next destructor. */
< if (DECL_VINDEX (dtor)
< && ! (flags & LOOKUP_NONVIRTUAL)
< && TREE_CODE (auto_delete) != PARM_DECL
< && (ptr == 1 || ! resolves_to_fixed_type_p (ref, 0)))
< {
< tree binfo, basetype;
< /* The code below is probably all broken. See call.c for the
< complete right way to do this. this offsets may not be right
< in the below. (mrs) */
< /* This destructor must be called via virtual function table. */
< dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (DECL_CONTEXT (dtor)), 0);
< basetype = DECL_CLASS_CONTEXT (dtor);
< binfo = get_binfo (basetype,
< TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))),
< 0);
< expr = convert_pointer_to_real (binfo, TREE_VALUE (parms));
< if (expr != TREE_VALUE (parms))
< {
< expr = fold (expr);
< ref = build_indirect_ref (expr, NULL_PTR);
< TREE_VALUE (parms) = expr;
< }
< function = build_vfn_ref (&TREE_VALUE (parms), ref, DECL_VINDEX (dtor));
< if (function == error_mark_node)
< return error_mark_node;
< TREE_TYPE (function) = build_pointer_type (TREE_TYPE (dtor));
< TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
< expr = build_function_call (function, parms);
< if (do_delete)
< expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
< if (ptr && (flags & LOOKUP_DESTRUCTOR) == 0)
< {
< /* Handle the case where a virtual destructor is
< being called on an item that is 0.
<
< @@ Does this really need to be done? */
< tree ifexp = build_binary_op(NE_EXPR, addr, integer_zero_node,1);
< #if 0
< if (TREE_CODE (ref) == VAR_DECL
< || TREE_CODE (ref) == COMPONENT_REF)
< warning ("losing in build_delete");
< #endif
< expr = build (COND_EXPR, void_type_node,
< ifexp, expr, void_zero_node);
< }
< }
---
> if (flags & LOOKUP_DESTRUCTOR)
> /* Explicit destructor call; don't check for null pointer. */
> ifexp = integer_one_node;
3944,3945c3078,3079
< {
< tree ifexp;
---
> /* Handle deleting a null pointer. */
> ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node, 1));
3947,3957c3081,3083
< if ((flags & LOOKUP_DESTRUCTOR)
< || TREE_CODE (ref) == VAR_DECL
< || TREE_CODE (ref) == PARM_DECL
< || TREE_CODE (ref) == COMPONENT_REF
< || TREE_CODE (ref) == ARRAY_REF)
< /* These can't be 0. */
< ifexp = integer_one_node;
< else
< /* Handle the case where a non-virtual destructor is
< being called on an item that is 0. */
< ifexp = build_binary_op (NE_EXPR, addr, integer_zero_node, 1);
---
> if (ifexp != integer_one_node)
> expr = build (COND_EXPR, void_type_node,
> ifexp, expr, void_zero_node);
3959,3971d3084
< /* Used to mean that this destructor was known to be empty,
< but that's now obsolete. */
< my_friendly_assert (DECL_INITIAL (dtor) != void_type_node, 221);
<
< TREE_CHAIN (parms) = build_tree_list (NULL_TREE, passed_auto_delete);
< expr = build_function_call (dtor, parms);
< if (do_delete)
< expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete);
<
< if (ifexp != integer_one_node)
< expr = build (COND_EXPR, void_type_node,
< ifexp, expr, void_zero_node);
< }
3976c3089
< /* This can get visibilities wrong. */
---
> /* We only get here from finish_function for a destructor. */
3984,4013c3097,3100
< /* If this type does not have a destructor, but does have
< operator delete, call the parent parent destructor (if any),
< but let this node do the deleting. Otherwise, it is ok
< to let the parent destructor do the deleting. */
< if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
< {
< parent_auto_delete = integer_zero_node;
< if (auto_delete == integer_zero_node)
< cond = NULL_TREE;
< else
< {
< tree virtual_size;
<
< /* This is probably wrong. It should be the size of the
< virtual object being deleted. */
< virtual_size = c_sizeof_nowarn (type);
<
< expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
< virtual_size, NULL_TREE);
< if (expr == error_mark_node)
< return error_mark_node;
< if (auto_delete != integer_one_node)
< cond = build (COND_EXPR, void_type_node,
< build (BIT_AND_EXPR, integer_type_node,
< auto_delete, integer_one_node),
< expr, void_zero_node);
< else
< cond = expr;
< }
< }
---
> /* If we have member delete or vbases, we call delete in
> finish_function. */
> if (auto_delete == integer_zero_node)
> cond = NULL_TREE;
4015,4016c3102
< || (TREE_VIA_VIRTUAL (base_binfo) == 0
< && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))))
---
> || ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
4018,4023d3103
< tree virtual_size;
<
< /* This is probably wrong. It should be the size of the virtual
< object being deleted. */
< virtual_size = c_sizeof_nowarn (type);
<
4027c3107
< build_tree_list (NULL_TREE, addr)),
---
> build_expr_list (NULL_TREE, addr)),
4034c3114
< exprstmt = build_tree_list (NULL_TREE, cond);
---
> exprstmt = build_expr_list (NULL_TREE, cond);
4047,4049c3127,3130
< expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), addr,
< this_auto_delete, flags, 0);
< exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
---
> expr = build_scoped_method_call
> (ref, base_binfo, dtor_identifier,
> build_expr_list (NULL_TREE, this_auto_delete));
> exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
4060,4062c3141,3143
< /* May be zero offset if other baseclasses are virtual. */
< expr = fold (build (PLUS_EXPR, build_pointer_type (BINFO_TYPE (base_binfo)),
< addr, BINFO_OFFSET (base_binfo)));
---
> expr = build_scoped_method_call
> (ref, base_binfo, dtor_identifier,
> build_expr_list (NULL_TREE, integer_zero_node));
4064,4068c3145
< expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr,
< integer_zero_node,
< flags, 0);
<
< exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
---
> exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
4077c3154
< tree this_member = build_component_ref (ref, DECL_NAME (member), 0, 0);
---
> tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
4080c3157
< exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
---
> exprstmt = expr_tree_cons (NULL_TREE, expr, exprstmt);
4107c3184
< result = tree_cons (NULL_TREE,
---
> result = expr_tree_cons (NULL_TREE,
4132a3210
>
4134c3212
< build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
---
> build_vec_delete (base, maxindex, auto_delete_vec, auto_delete,
4136c3214
< tree base, maxindex, elt_size;
---
> tree base, maxindex;
4149c3227
< /* Since we can use base many times, save_expr it. */
---
> /* Since we can use base many times, save_expr it. */
4159c3237
< maxindex = build_component_ref (cookie, nc_nelts_field_id, 0, 0);
---
> maxindex = build_component_ref (cookie, nc_nelts_field_id, NULL_TREE, 0);
4174c3252,3253
< error ("type to vector delete is neither pointer or array type");
---
> if (base != error_mark_node)
> error ("type to vector delete is neither pointer or array type");