Commit 72b7eeff by Mike Stump

76th Cygnus<->FSF merge

From-SVN: r10815
parent f82da7d2
...@@ -1658,6 +1658,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1658,6 +1658,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
} }
/* We already know whether it's needed or not for vec delete. */ /* We already know whether it's needed or not for vec delete. */
else if (name == ansi_opname[(int) VEC_DELETE_EXPR] else if (name == ansi_opname[(int) VEC_DELETE_EXPR]
&& TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
&& ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance))) && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))
TREE_CHAIN (parms) = NULL_TREE; TREE_CHAIN (parms) = NULL_TREE;
...@@ -2464,17 +2465,13 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2464,17 +2465,13 @@ build_method_call (instance, name, parms, basetype_path, flags)
return build_signature_method_call (basetype, instance, function, parms); return build_signature_method_call (basetype, instance, function, parms);
function = DECL_MAIN_VARIANT (function); function = DECL_MAIN_VARIANT (function);
/* Declare external function if necessary. */ mark_used (function);
assemble_external (function);
#if 1
/* Is it a synthesized method that needs to be synthesized? */ /* Is it a synthesized method that needs to be synthesized? */
if (DECL_ARTIFICIAL (function) && ! flag_no_inline if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
&& ! DECL_INITIAL (function)
/* Kludge: don't synthesize for default args. */ /* Kludge: don't synthesize for default args. */
&& current_function_decl) && current_function_decl)
synthesize_method (function); synthesize_method (function);
#endif
if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function) if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
&& ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)) && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
...@@ -2670,7 +2667,6 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2670,7 +2667,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (function) == FUNCTION_DECL) if (TREE_CODE (function) == FUNCTION_DECL)
{ {
is_constructor = DECL_CONSTRUCTOR_P (function); is_constructor = DECL_CONSTRUCTOR_P (function);
TREE_USED (function) = 1;
function = default_conversion (function); function = default_conversion (function);
} }
else else
......
...@@ -424,7 +424,6 @@ build_vfn_ref (ptr_to_instptr, instance, idx) ...@@ -424,7 +424,6 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
tree *ptr_to_instptr, instance; tree *ptr_to_instptr, instance;
tree idx; tree idx;
{ {
extern int building_cleanup;
tree vtbl, aref; tree vtbl, aref;
tree basetype = TREE_TYPE (instance); tree basetype = TREE_TYPE (instance);
...@@ -481,7 +480,7 @@ build_vfn_ref (ptr_to_instptr, instance, idx) ...@@ -481,7 +480,7 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
/* Save the intermediate result in a SAVE_EXPR so we don't have to /* Save the intermediate result in a SAVE_EXPR so we don't have to
compute each component of the virtual function pointer twice. */ compute each component of the virtual function pointer twice. */
if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF) if (TREE_CODE (aref) == INDIRECT_REF)
TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
if (flag_vtable_thunks) if (flag_vtable_thunks)
...@@ -1720,8 +1719,14 @@ finish_struct_bits (t, max_has_virtual) ...@@ -1720,8 +1719,14 @@ finish_struct_bits (t, max_has_virtual)
/* If this type has a copy constructor, force its mode to be BLKmode, and /* If this type has a copy constructor, force its mode to be BLKmode, and
force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to
be passed by invisible reference and prevent it from being returned in be passed by invisible reference and prevent it from being returned in
a register. */ a register.
if (! TYPE_HAS_TRIVIAL_INIT_REF (t))
Also do this if the class has BLKmode but can still be returned in
registers, since function_cannot_inline_p won't let us inline
functions returning such a type. This affects the HP-PA. */
if (! TYPE_HAS_TRIVIAL_INIT_REF (t)
|| (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t)
&& CLASSTYPE_NON_AGGREGATE (t)))
{ {
tree variants; tree variants;
if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
...@@ -1812,15 +1817,14 @@ grow_method (fn, method_vec_ptr) ...@@ -1812,15 +1817,14 @@ grow_method (fn, method_vec_ptr)
us to reduce search time in places like `build_method_call' to us to reduce search time in places like `build_method_call' to
consider only reasonably likely functions. */ consider only reasonably likely functions. */
static tree tree
finish_struct_methods (t, fn_fields, nonprivate_method) finish_struct_methods (t, fn_fields, nonprivate_method)
tree t; tree t;
tree fn_fields; tree fn_fields;
int nonprivate_method; int nonprivate_method;
{ {
tree method_vec; tree method_vec;
tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields); tree save_fn_fields = fn_fields;
tree lastp;
tree name = constructor_name (t); tree name = constructor_name (t);
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
...@@ -1837,7 +1841,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -1837,7 +1841,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
/* First fill in entry 0 with the constructors, and the next few with /* First fill in entry 0 with the constructors, and the next few with
type conversion operators (if any). */ type conversion operators (if any). */
for (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp)) for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
{ {
tree fn_name = DECL_NAME (fn_fields); tree fn_name = DECL_NAME (fn_fields);
if (fn_name == NULL_TREE) if (fn_name == NULL_TREE)
...@@ -1887,26 +1891,17 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -1887,26 +1891,17 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
grow_method (fn_fields, &method_vec); grow_method (fn_fields, &method_vec);
} }
else
{
lastp = fn_fields;
continue;
}
TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields);
TREE_CHAIN (fn_fields) = NULL_TREE;
} }
fn_fields = TREE_CHAIN (save_fn_fields); fn_fields = save_fn_fields;
while (fn_fields) for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
{ {
tree nextp;
tree fn_name = DECL_NAME (fn_fields); tree fn_name = DECL_NAME (fn_fields);
if (fn_name == NULL_TREE) if (fn_name == NULL_TREE)
fn_name = name; fn_name = name;
nextp = TREE_CHAIN (fn_fields); if (fn_name == name || IDENTIFIER_TYPENAME_P (fn_name))
TREE_CHAIN (fn_fields) = NULL_TREE; continue;
if (fn_name == ansi_opname[(int) MODIFY_EXPR]) if (fn_name == ansi_opname[(int) MODIFY_EXPR])
{ {
...@@ -1922,7 +1917,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -1922,7 +1917,6 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
} }
grow_method (fn_fields, &method_vec); grow_method (fn_fields, &method_vec);
fn_fields = nextp;
} }
TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack) TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
...@@ -2005,6 +1999,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -2005,6 +1999,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
obstack_free (current_obstack, baselink_vec); obstack_free (current_obstack, baselink_vec);
} }
#if 0
/* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */ /* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */
{ {
tree x, last_x = NULL_TREE; tree x, last_x = NULL_TREE;
...@@ -2040,6 +2035,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -2040,6 +2035,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
} }
TYPE_METHODS (t) = method_vec; TYPE_METHODS (t) = method_vec;
#endif
return method_vec; return method_vec;
} }
...@@ -2765,7 +2761,7 @@ finish_struct_1 (t, warn_anon) ...@@ -2765,7 +2761,7 @@ finish_struct_1 (t, warn_anon)
tree name = TYPE_IDENTIFIER (t); tree name = TYPE_IDENTIFIER (t);
enum tree_code code = TREE_CODE (t); enum tree_code code = TREE_CODE (t);
tree fields = TYPE_FIELDS (t); tree fields = TYPE_FIELDS (t);
tree fn_fields = CLASSTYPE_METHODS (t); tree fn_fields = TYPE_METHODS (t);
tree x, last_x, method_vec; tree x, last_x, method_vec;
int needs_virtual_dtor; int needs_virtual_dtor;
int all_virtual; int all_virtual;
...@@ -2920,7 +2916,7 @@ finish_struct_1 (t, warn_anon) ...@@ -2920,7 +2916,7 @@ finish_struct_1 (t, warn_anon)
else else
all_virtual = 0; all_virtual = 0;
for (x = CLASSTYPE_METHODS (t); x; x = TREE_CHAIN (x)) for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{ {
GNU_xref_member (current_class_name, x); GNU_xref_member (current_class_name, x);
...@@ -3197,7 +3193,7 @@ finish_struct_1 (t, warn_anon) ...@@ -3197,7 +3193,7 @@ finish_struct_1 (t, warn_anon)
{ {
tree type = TREE_TYPE (x); tree type = TREE_TYPE (x);
if (TREE_CODE (type) == ARRAY_TYPE) while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x) if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x)
...@@ -3681,19 +3677,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3681,19 +3677,6 @@ finish_struct_1 (t, warn_anon)
} }
} }
} }
/* Now fixup any virtual function entries from virtual bases
that have different deltas. */
vbases = CLASSTYPE_VBASECLASSES (t);
while (vbases)
{
/* We might be able to shorten the amount of work we do by
only doing this for vtables that come from virtual bases
that have differing offsets, but don't want to miss any
entries. */
fixup_vtable_deltas (vbases, 1, t);
vbases = TREE_CHAIN (vbases);
}
} }
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
...@@ -3736,6 +3719,27 @@ finish_struct_1 (t, warn_anon) ...@@ -3736,6 +3719,27 @@ finish_struct_1 (t, warn_anon)
TREE_VALUE (pending_hard_virtuals)); TREE_VALUE (pending_hard_virtuals));
pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals); pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
} }
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree vbases;
/* Now fixup any virtual function entries from virtual bases
that have different deltas. This has to come after we do the
pending hard virtuals, as we might have a function that comes
from multiple virtual base instances that is only overridden
by a hard virtual above. */
vbases = CLASSTYPE_VBASECLASSES (t);
while (vbases)
{
/* We might be able to shorten the amount of work we do by
only doing this for vtables that come from virtual bases
that have differing offsets, but don't want to miss any
entries. */
fixup_vtable_deltas (vbases, 1, t);
vbases = TREE_CHAIN (vbases);
}
}
doing_hard_virtuals = 0; doing_hard_virtuals = 0;
/* Under our model of GC, every C++ class gets its own virtual /* Under our model of GC, every C++ class gets its own virtual
...@@ -4045,8 +4049,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4045,8 +4049,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree list_of_fieldlists; tree list_of_fieldlists;
int warn_anon; int warn_anon;
{ {
tree fields = NULL_TREE, fn_fields, *tail; tree fields = NULL_TREE;
tree *tail_user_methods = &CLASSTYPE_METHODS (t); tree *tail = &TYPE_METHODS (t);
tree name = TYPE_NAME (t); tree name = TYPE_NAME (t);
tree x, last_x = NULL_TREE; tree x, last_x = NULL_TREE;
enum access_type access; enum access_type access;
...@@ -4071,7 +4075,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4071,7 +4075,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (IS_SIGNATURE (t)) if (IS_SIGNATURE (t))
append_signature_fields (list_of_fieldlists); append_signature_fields (list_of_fieldlists);
tail = &fn_fields;
if (last_x && list_of_fieldlists) if (last_x && list_of_fieldlists)
TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
...@@ -4130,11 +4133,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4130,11 +4133,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
{ {
if (last_x) if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x); TREE_CHAIN (last_x) = TREE_CHAIN (x);
/* Link x onto end of fn_fields and CLASSTYPE_METHODS. */ /* Link x onto end of TYPE_METHODS. */
*tail = x; *tail = x;
tail = &TREE_CHAIN (x); tail = &TREE_CHAIN (x);
*tail_user_methods = x;
tail_user_methods = &DECL_NEXT_METHOD (x);
continue; continue;
} }
...@@ -4167,12 +4168,12 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4167,12 +4168,12 @@ finish_struct (t, list_of_fieldlists, warn_anon)
} }
*tail = NULL_TREE; *tail = NULL_TREE;
*tail_user_methods = NULL_TREE;
TYPE_FIELDS (t) = fields; TYPE_FIELDS (t) = fields;
if (0 && processing_template_defn) if (0 && processing_template_defn)
{ {
CLASSTYPE_METHOD_VEC (t) = finish_struct_methods (t, fn_fields, 1); CLASSTYPE_METHOD_VEC (t)
= finish_struct_methods (t, TYPE_METHODS (t), 1);
return t; return t;
} }
else else
...@@ -4671,6 +4672,7 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4671,6 +4672,7 @@ instantiate_type (lhstype, rhs, complain)
return error_mark_node; return error_mark_node;
return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function)); return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
} }
mark_used (function);
return function; return function;
} }
...@@ -4687,6 +4689,7 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4687,6 +4689,7 @@ instantiate_type (lhstype, rhs, complain)
if (field) if (field)
{ {
TREE_OPERAND (rhs, 1) = field; TREE_OPERAND (rhs, 1) = field;
mark_used (field);
return rhs; return rhs;
} }
...@@ -4760,7 +4763,10 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4760,7 +4763,10 @@ instantiate_type (lhstype, rhs, complain)
if (! comptypes (lhstype, TREE_TYPE (elem), 1)) if (! comptypes (lhstype, TREE_TYPE (elem), 1))
elem = DECL_CHAIN (elem); elem = DECL_CHAIN (elem);
else else
return elem; {
mark_used (elem);
return elem;
}
/* No exact match found, look for a compatible template. */ /* No exact match found, look for a compatible template. */
{ {
...@@ -4815,6 +4821,7 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4815,6 +4821,7 @@ instantiate_type (lhstype, rhs, complain)
} }
return error_mark_node; return error_mark_node;
} }
mark_used (save_elem);
return save_elem; return save_elem;
} }
if (complain) if (complain)
...@@ -4848,7 +4855,10 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4848,7 +4855,10 @@ instantiate_type (lhstype, rhs, complain)
elem = TREE_VALUE (baselink); elem = TREE_VALUE (baselink);
while (elem) while (elem)
if (comptypes (lhstype, TREE_TYPE (elem), 1)) if (comptypes (lhstype, TREE_TYPE (elem), 1))
return elem; {
mark_used (elem);
return elem;
}
else else
elem = DECL_CHAIN (elem); elem = DECL_CHAIN (elem);
} }
...@@ -4874,6 +4884,7 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4874,6 +4884,7 @@ instantiate_type (lhstype, rhs, complain)
error ("ambiguous overload for overloaded method requested"); error ("ambiguous overload for overloaded method requested");
return error_mark_node; return error_mark_node;
} }
mark_used (save_elem);
return save_elem; return save_elem;
} }
name = DECL_NAME (TREE_VALUE (rhs)); name = DECL_NAME (TREE_VALUE (rhs));
......
...@@ -636,10 +636,6 @@ struct lang_type ...@@ -636,10 +636,6 @@ struct lang_type
/* The is the VAR_DECL that contains NODE's rtti. */ /* The is the VAR_DECL that contains NODE's rtti. */
#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti) #define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti)
/* List of all explicit methods (chained using DECL_NEXT_METHOD),
in order they were parsed. */
#define CLASSTYPE_METHODS(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */ /* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded) #define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded)
...@@ -660,7 +656,7 @@ struct lang_type ...@@ -660,7 +656,7 @@ struct lang_type
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE)) #define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
/* List of lists of member functions defined in this class. */ /* List of lists of member functions defined in this class. */
#define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE) #define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* The first type conversion operator in the class (the others can be /* The first type conversion operator in the class (the others can be
searched with TREE_CHAIN), or the first non-constructor function if searched with TREE_CHAIN), or the first non-constructor function if
...@@ -924,7 +920,7 @@ struct lang_type ...@@ -924,7 +920,7 @@ struct lang_type
#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE) #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
/* The binding level associated with the namespace. */ /* The binding level associated with the namespace. */
#define NAMESPACE_LEVEL(NODE) ((NODE)->decl.arguments) #define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
struct lang_decl_flags struct lang_decl_flags
{ {
...@@ -960,6 +956,7 @@ struct lang_decl_flags ...@@ -960,6 +956,7 @@ struct lang_decl_flags
tree access; tree access;
tree context; tree context;
tree memfunc_pointer_to; tree memfunc_pointer_to;
struct binding_level *level;
}; };
struct lang_decl struct lang_decl
...@@ -969,7 +966,6 @@ struct lang_decl ...@@ -969,7 +966,6 @@ struct lang_decl
struct template_info *template_info; struct template_info *template_info;
tree main_decl_variant; tree main_decl_variant;
struct pending_inline *pending_inline_info; struct pending_inline *pending_inline_info;
tree next_method;
tree chain; tree chain;
}; };
...@@ -1068,9 +1064,6 @@ struct lang_decl ...@@ -1068,9 +1064,6 @@ struct lang_decl
#define DECL_CHAIN(NODE) (TREE_CHAIN (NODE)) #define DECL_CHAIN(NODE) (TREE_CHAIN (NODE))
#endif #endif
/* Next method in CLASSTYPE_METHODS list. */
#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
/* In a VAR_DECL for a variable declared in a for statement, /* In a VAR_DECL for a variable declared in a for statement,
this is the shadowed variable. */ this is the shadowed variable. */
#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE) #define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE)
...@@ -1401,6 +1394,9 @@ extern int flag_new_for_scope; ...@@ -1401,6 +1394,9 @@ extern int flag_new_for_scope;
#define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE)) #define UPT_TEMPLATE(NODE) TREE_PURPOSE(TYPE_VALUES(NODE))
#define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE)) #define UPT_PARMS(NODE) TREE_VALUE(TYPE_VALUES(NODE))
#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
define_function (NAME, TYPE, CODE, (void (*)())pushdecl, LIBNAME)
/* An enumeration of the kind of tags that C++ accepts. */ /* An enumeration of the kind of tags that C++ accepts. */
enum tag_types { record_type, class_type, union_type, enum_type, enum tag_types { record_type, class_type, union_type, enum_type,
signature_type }; signature_type };
...@@ -1809,6 +1805,12 @@ extern int flag_alt_external_templates; ...@@ -1809,6 +1805,12 @@ extern int flag_alt_external_templates;
extern int flag_implicit_templates; extern int flag_implicit_templates;
/* Nonzero if we want to emit defined symbols with common-like linkage as
weak symbols where possible, in order to conform to C++ semantics.
Otherwise, emit them as local symbols. */
extern int flag_weak;
/* Current end of entries in the gc obstack for stack pointer variables. */ /* Current end of entries in the gc obstack for stack pointer variables. */
extern int current_function_obstack_index; extern int current_function_obstack_index;
...@@ -1844,6 +1846,9 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ ...@@ -1844,6 +1846,9 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already LOOKUP_HAS_IN_CHARGE means that the "in charge" variable is already
in the parameter list. in the parameter list.
LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried. LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried.
INDIRECT_BIND means that if a temporary is created, it should be created so
that it lives only as long as WITH_CLEANUP_EXPRs live, else if a temporary
is created then it should live as long as the current variable bindings.
LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are LOOKUP_SPECULATIVELY means return NULL_TREE if we cannot find what we are
after. Note, LOOKUP_COMPLAIN is checked and error messages printed after. Note, LOOKUP_COMPLAIN is checked and error messages printed
before LOOKUP_SPECULATIVELY is checked. before LOOKUP_SPECULATIVELY is checked.
...@@ -1860,7 +1865,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ ...@@ -1860,7 +1865,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define LOOKUP_HAS_IN_CHARGE (32) #define LOOKUP_HAS_IN_CHARGE (32)
#define LOOKUP_SPECULATIVELY (64) #define LOOKUP_SPECULATIVELY (64)
#define LOOKUP_ONLYCONVERTING (128) #define LOOKUP_ONLYCONVERTING (128)
/* 256 is free */ #define INDIRECT_BIND (256)
#define LOOKUP_NO_CONVERSION (512) #define LOOKUP_NO_CONVERSION (512)
#define LOOKUP_DESTRUCTOR (512) #define LOOKUP_DESTRUCTOR (512)
...@@ -2131,6 +2136,8 @@ extern void init_exception_processing PROTO((void)); ...@@ -2131,6 +2136,8 @@ extern void init_exception_processing PROTO((void));
extern void expand_builtin_throw PROTO((void)); extern void expand_builtin_throw PROTO((void));
extern void expand_start_eh_spec PROTO((void)); extern void expand_start_eh_spec PROTO((void));
extern void expand_end_eh_spec PROTO((tree)); extern void expand_end_eh_spec PROTO((tree));
extern tree build_cleanup PROTO((tree));
extern tree start_anon_func PROTO((void));
/* in expr.c */ /* in expr.c */
/* skip cplus_expand_expr */ /* skip cplus_expand_expr */
...@@ -2395,6 +2402,7 @@ extern tree array_type_nelts_total PROTO((tree)); ...@@ -2395,6 +2402,7 @@ extern tree array_type_nelts_total PROTO((tree));
extern tree array_type_nelts_top PROTO((tree)); extern tree array_type_nelts_top PROTO((tree));
extern tree break_out_target_exprs PROTO((tree)); extern tree break_out_target_exprs PROTO((tree));
extern tree build_unsave_expr PROTO((tree)); extern tree build_unsave_expr PROTO((tree));
extern tree unsave_expr PROTO((tree));
extern int cp_expand_decl_cleanup PROTO((tree, tree)); extern int cp_expand_decl_cleanup PROTO((tree, tree));
/* in typeck.c */ /* in typeck.c */
......
...@@ -311,6 +311,7 @@ convert_to_pointer_force (type, expr) ...@@ -311,6 +311,7 @@ convert_to_pointer_force (type, expr)
value we have to begin with is in ARG. value we have to begin with is in ARG.
FLAGS controls how we manage access checking. FLAGS controls how we manage access checking.
INDIRECT_BIND in FLAGS controls how any temporarys are generated.
CHECKCONST controls if we report error messages on const subversion. */ CHECKCONST controls if we report error messages on const subversion. */
static tree static tree
build_up_reference (type, arg, flags, checkconst) build_up_reference (type, arg, flags, checkconst)
...@@ -589,7 +590,15 @@ build_up_reference (type, arg, flags, checkconst) ...@@ -589,7 +590,15 @@ build_up_reference (type, arg, flags, checkconst)
{ {
tree temp; tree temp;
if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) if (flags&INDIRECT_BIND)
{
tree slot = build (VAR_DECL, argtype);
layout_decl (slot, 0);
rval = build (TARGET_EXPR, argtype, slot, arg, 0);
rval = build1 (ADDR_EXPR, type, rval);
goto done;
}
else if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
{ {
temp = build_cplus_new (argtype, targ, 1); temp = build_cplus_new (argtype, targ, 1);
if (TREE_CODE (temp) == WITH_CLEANUP_EXPR) if (TREE_CODE (temp) == WITH_CLEANUP_EXPR)
...@@ -1634,8 +1643,13 @@ build_expr_type_conversion (desires, expr, complain) ...@@ -1634,8 +1643,13 @@ build_expr_type_conversion (desires, expr, complain)
} }
if (winner) if (winner)
return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr, {
TREE_PURPOSE (winner), 1); tree type = TREE_VALUE (winner);
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
return build_type_conversion_1 (type, basetype, expr,
TREE_PURPOSE (winner), 1);
}
return NULL_TREE; return NULL_TREE;
} }
......
...@@ -36,7 +36,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -36,7 +36,6 @@ Boston, MA 02111-1307, USA. */
#include "decl.h" #include "decl.h"
#include "lex.h" #include "lex.h"
#include "output.h" #include "output.h"
#include "defaults.h"
extern tree get_file_function_name (); extern tree get_file_function_name ();
extern tree cleanups_this_call; extern tree cleanups_this_call;
...@@ -369,6 +368,12 @@ int flag_check_new; ...@@ -369,6 +368,12 @@ int flag_check_new;
int flag_new_for_scope = 1; int flag_new_for_scope = 1;
/* Nonzero if we want to emit defined symbols with common-like linkage as
weak symbols where possible, in order to conform to C++ semantics.
Otherwise, emit them as local symbols. */
int flag_weak = 1;
/* Table of language-dependent -f options. /* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable. STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE ON_VALUE is the value to store in VARIABLE
...@@ -416,7 +421,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -416,7 +421,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"operator-names", &flag_operator_names, 1}, {"operator-names", &flag_operator_names, 1},
{"check-new", &flag_check_new, 1}, {"check-new", &flag_check_new, 1},
{"repo", &flag_use_repository, 1}, {"repo", &flag_use_repository, 1},
{"for-scope", &flag_new_for_scope, 2} {"for-scope", &flag_new_for_scope, 2},
{"weak", &flag_weak, 1}
}; };
/* Decode the string P as a language-specific option. /* Decode the string P as a language-specific option.
...@@ -906,7 +912,7 @@ grokclassfn (ctype, cname, function, flags, quals) ...@@ -906,7 +912,7 @@ grokclassfn (ctype, cname, function, flags, quals)
/* Mark the artificial `__in_chrg' parameter as "artificial". */ /* Mark the artificial `__in_chrg' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm); SET_DECL_ARTIFICIAL (parm);
DECL_ARG_TYPE (parm) = integer_type_node; DECL_ARG_TYPE (parm) = integer_type_node;
DECL_REGISTER (parm) = 1; TREE_READONLY (parm) = 1;
TREE_CHAIN (parm) = last_function_parms; TREE_CHAIN (parm) = last_function_parms;
last_function_parms = parm; last_function_parms = parm;
} }
...@@ -948,18 +954,11 @@ grokclassfn (ctype, cname, function, flags, quals) ...@@ -948,18 +954,11 @@ grokclassfn (ctype, cname, function, flags, quals)
buf[len] = '\0'; buf[len] = '\0';
strcat (buf, dbuf); strcat (buf, dbuf);
DECL_ASSEMBLER_NAME (function) = get_identifier (buf); DECL_ASSEMBLER_NAME (function) = get_identifier (buf);
parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type); parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
/* Mark the artificial `__in_chrg' parameter as "artificial". */ /* Mark the artificial `__in_chrg' parameter as "artificial". */
SET_DECL_ARTIFICIAL (parm); SET_DECL_ARTIFICIAL (parm);
TREE_USED (parm) = 1;
#if 0
/* We don't need to mark the __in_chrg parameter itself as `const'
since its type is already `const int'. In fact we MUST NOT mark
it as `const' cuz that will screw up the debug info (causing it
to say that the type of __in_chrg is `const const int'). */
TREE_READONLY (parm) = 1; TREE_READONLY (parm) = 1;
#endif DECL_ARG_TYPE (parm) = integer_type_node;
DECL_ARG_TYPE (parm) = const_integer_type;
/* This is the same chain as DECL_ARGUMENTS (...). */ /* This is the same chain as DECL_ARGUMENTS (...). */
TREE_CHAIN (last_function_parms) = parm; TREE_CHAIN (last_function_parms) = parm;
...@@ -2030,7 +2029,7 @@ constructor_name_full (thing) ...@@ -2030,7 +2029,7 @@ constructor_name_full (thing)
if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
{ {
if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing)) if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing))
thing = DECL_NAME (TREE_VEC_ELT (TYPE_METHODS (thing), 0)); thing = DECL_NAME (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0));
else else
thing = TYPE_NAME (thing); thing = TYPE_NAME (thing);
} }
...@@ -2479,6 +2478,8 @@ coerce_delete_type (type) ...@@ -2479,6 +2478,8 @@ coerce_delete_type (type)
return type; return type;
} }
extern tree abort_fndecl;
static void static void
mark_vtable_entries (decl) mark_vtable_entries (decl)
tree decl; tree decl;
...@@ -2489,16 +2490,12 @@ mark_vtable_entries (decl) ...@@ -2489,16 +2490,12 @@ mark_vtable_entries (decl)
for (; entries; entries = TREE_CHAIN (entries)) for (; entries; entries = TREE_CHAIN (entries))
{ {
tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
: FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
tree fn = TREE_OPERAND (fnaddr, 0); tree fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1; TREE_ADDRESSABLE (fn) = 1;
if (DECL_ABSTRACT_VIRTUAL_P (fn)) if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
{ TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
extern tree abort_fndecl;
if (flag_vtable_thunks)
fnaddr = TREE_VALUE (entries);
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
}
assemble_external (fn); assemble_external (fn);
} }
} }
...@@ -2541,8 +2538,8 @@ import_export_vtable (decl, type, final) ...@@ -2541,8 +2538,8 @@ import_export_vtable (decl, type, final)
if (! found && ! final) if (! found && ! final)
{ {
tree method; tree method;
for (method = CLASSTYPE_METHODS (type); method != NULL_TREE; for (method = TYPE_METHODS (type); method != NULL_TREE;
method = DECL_NEXT_METHOD (method)) method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_THIS_INLINE (method) && ! DECL_THIS_INLINE (method)
&& ! DECL_ABSTRACT_VIRTUAL_P (method)) && ! DECL_ABSTRACT_VIRTUAL_P (method))
...@@ -2558,7 +2555,7 @@ import_export_vtable (decl, type, final) ...@@ -2558,7 +2555,7 @@ import_export_vtable (decl, type, final)
if (TREE_PUBLIC (decl)) if (TREE_PUBLIC (decl))
cp_error ("all virtual functions redeclared inline"); cp_error ("all virtual functions redeclared inline");
#endif #endif
if (SUPPORTS_WEAK) if (flag_weak)
DECL_WEAK (decl) = 1; DECL_WEAK (decl) = 1;
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
...@@ -2597,8 +2594,8 @@ finish_prevtable_vardecl (prev, vars) ...@@ -2597,8 +2594,8 @@ finish_prevtable_vardecl (prev, vars)
&& ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
{ {
tree method; tree method;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE; for (method = TYPE_METHODS (ctype); method != NULL_TREE;
method = DECL_NEXT_METHOD (method)) method = TREE_CHAIN (method))
{ {
if (DECL_VINDEX (method) != NULL_TREE if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_THIS_INLINE (method) && !DECL_THIS_INLINE (method)
...@@ -2782,7 +2779,7 @@ import_export_inline (decl) ...@@ -2782,7 +2779,7 @@ import_export_inline (decl)
{ {
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates) if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
{ {
if (SUPPORTS_WEAK) if (flag_weak)
DECL_WEAK (decl) = 1; DECL_WEAK (decl) = 1;
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
...@@ -2799,14 +2796,14 @@ import_export_inline (decl) ...@@ -2799,14 +2796,14 @@ import_export_inline (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype) = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_THIS_INLINE (decl) && ! flag_implement_inlines)); || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
} }
else if (SUPPORTS_WEAK) else if (flag_weak)
DECL_WEAK (decl) = 1; DECL_WEAK (decl) = 1;
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
} }
else if (DECL_C_STATIC (decl)) else if (DECL_C_STATIC (decl))
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
else if (SUPPORTS_WEAK) else if (flag_weak)
DECL_WEAK (decl) = 1; DECL_WEAK (decl) = 1;
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
...@@ -2814,6 +2811,26 @@ import_export_inline (decl) ...@@ -2814,6 +2811,26 @@ import_export_inline (decl)
DECL_INTERFACE_KNOWN (decl) = 1; DECL_INTERFACE_KNOWN (decl) = 1;
} }
tree
build_cleanup (decl)
tree decl;
{
tree temp;
tree type = TREE_TYPE (decl);
if (TREE_CODE (type) == ARRAY_TYPE)
temp = decl;
else
{
mark_addressable (decl);
temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
}
temp = build_delete (TREE_TYPE (temp), temp,
integer_two_node,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
return temp;
}
extern int parse_time, varconst_time; extern int parse_time, varconst_time;
#define TIMEVAR(VAR, BODY) \ #define TIMEVAR(VAR, BODY) \
...@@ -2895,14 +2912,12 @@ finish_file () ...@@ -2895,14 +2912,12 @@ finish_file ()
{ {
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars))
{ {
needs_cleaning = 1; needs_cleaning = 1;
needs_messing_up = 1;
break; break;
} }
else
needs_messing_up |= TYPE_NEEDS_CONSTRUCTING (type);
vars = TREE_CHAIN (vars); vars = TREE_CHAIN (vars);
} }
...@@ -2930,23 +2945,10 @@ finish_file () ...@@ -2930,23 +2945,10 @@ finish_file ()
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
tree temp = TREE_PURPOSE (vars); tree temp = TREE_PURPOSE (vars);
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars))
{ {
if (TREE_STATIC (vars)) temp = build_cleanup (decl);
expand_start_cond (build_binary_op (NE_EXPR, temp, integer_zero_node, 1), 0);
if (TREE_CODE (type) == ARRAY_TYPE)
temp = decl;
else
{
mark_addressable (decl);
temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
}
temp = build_delete (TREE_TYPE (temp), temp,
integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
expand_expr_stmt (temp); expand_expr_stmt (temp);
if (TREE_STATIC (vars))
expand_end_cond ();
} }
} }
...@@ -2987,9 +2989,15 @@ finish_file () ...@@ -2987,9 +2989,15 @@ finish_file ()
while (vars) while (vars)
{ {
extern int temp_slot_level;
extern int target_temp_slot_level;
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
tree init = TREE_PURPOSE (vars); tree init = TREE_PURPOSE (vars);
tree old_cleanups = cleanups_this_call; tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
/* If this was a static attribute within some function's scope, /* If this was a static attribute within some function's scope,
then don't initialize it here. Also, don't bother then don't initialize it here. Also, don't bother
...@@ -3024,7 +3032,6 @@ finish_file () ...@@ -3024,7 +3032,6 @@ finish_file ()
TREE_VEC_ELT (init, 1), TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0), TREE_VEC_ELT (init, 2), 0),
const0_rtx, VOIDmode, 0); const0_rtx, VOIDmode, 0);
free_temp_slots ();
} }
else else
expand_assignment (decl, init, 0, 0); expand_assignment (decl, init, 0, 0);
...@@ -3037,14 +3044,12 @@ finish_file () ...@@ -3037,14 +3044,12 @@ finish_file ()
{ {
/* a `new' expression at top level. */ /* a `new' expression at top level. */
expand_expr (decl, const0_rtx, VOIDmode, 0); expand_expr (decl, const0_rtx, VOIDmode, 0);
free_temp_slots ();
if (TREE_CODE (init) == TREE_VEC) if (TREE_CODE (init) == TREE_VEC)
{ {
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0), expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
TREE_VEC_ELT (init, 1), TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0), TREE_VEC_ELT (init, 2), 0),
const0_rtx, VOIDmode, 0); const0_rtx, VOIDmode, 0);
free_temp_slots ();
} }
else else
expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0); expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
...@@ -3053,9 +3058,14 @@ finish_file () ...@@ -3053,9 +3058,14 @@ finish_file ()
else if (decl == error_mark_node) else if (decl == error_mark_node)
; ;
else my_friendly_abort (22); else my_friendly_abort (22);
vars = TREE_CHAIN (vars);
/* Cleanup any temporaries needed for the initial value. */ /* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups); expand_cleanups_to (old_cleanups);
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
vars = TREE_CHAIN (vars);
} }
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors)) for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
...@@ -3509,3 +3519,11 @@ check_default_args (x) ...@@ -3509,3 +3519,11 @@ check_default_args (x)
} }
} }
} }
void
mark_used (decl)
tree decl;
{
TREE_USED (decl) = 1;
assemble_external (decl);
}
...@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h" #include "config.h"
#include "tree.h" #include "tree.h"
#include <stdio.h>
#include <ctype.h> #include <ctype.h>
/* cp_printer is the type of a function which converts an argument into /* cp_printer is the type of a function which converts an argument into
...@@ -195,8 +196,7 @@ cp_sprintf (format, arglist) ...@@ -195,8 +196,7 @@ cp_sprintf (format, arglist)
char *format; char *format;
arglist_dcl arglist_dcl
{ {
extern errorfn sprintf; cp_thing ((errorfn *) sprintf, 0, format, arglist);
cp_thing (sprintf, 0, format, arglist);
} }
void void
......
...@@ -950,12 +950,12 @@ dump_expr (t, nop) ...@@ -950,12 +950,12 @@ dump_expr (t, nop)
} }
else if (type == boolean_type_node) else if (type == boolean_type_node)
{ {
if (t == boolean_false_node) if (t == boolean_false_node
|| (TREE_INT_CST_LOW (t) == 0
&& TREE_INT_CST_HIGH (t) == 0))
OB_PUTS ("false"); OB_PUTS ("false");
else if (t == boolean_true_node) else if (t == boolean_true_node)
OB_PUTS ("true"); OB_PUTS ("true");
else
my_friendly_abort (366);
} }
else if (type == char_type_node) else if (type == char_type_node)
{ {
......
...@@ -43,6 +43,8 @@ Boston, MA 02111-1307, USA. */ ...@@ -43,6 +43,8 @@ Boston, MA 02111-1307, USA. */
line. Perhaps this was not intended. */ line. Perhaps this was not intended. */
tree current_base_init_list, current_member_init_list; tree current_base_init_list, current_member_init_list;
extern tree cleanups_this_call;
void emit_base_init (); void emit_base_init ();
void check_base_init (); void check_base_init ();
static void expand_aggr_vbase_init (); static void expand_aggr_vbase_init ();
...@@ -160,6 +162,13 @@ perform_member_init (member, name, init, explicit, protect_list) ...@@ -160,6 +162,13 @@ perform_member_init (member, name, init, explicit, protect_list)
{ {
tree decl; tree decl;
tree type = TREE_TYPE (member); tree type = TREE_TYPE (member);
extern int temp_slot_level;
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
if (TYPE_NEEDS_CONSTRUCTING (type) if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type))) || (init && TYPE_HAS_CONSTRUCTOR (type)))
...@@ -219,7 +228,16 @@ perform_member_init (member, name, init, explicit, protect_list) ...@@ -219,7 +228,16 @@ perform_member_init (member, name, init, explicit, protect_list)
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
} }
} }
expand_cleanups_to (NULL_TREE); expand_cleanups_to (old_cleanups);
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots ();
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type))
{ {
...@@ -577,11 +595,28 @@ emit_base_init (t, immediately) ...@@ -577,11 +595,28 @@ emit_base_init (t, immediately)
if (init != void_list_node) if (init != void_list_node)
{ {
extern int temp_slot_level;
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
member = convert_pointer_to_real (base_binfo, current_class_decl); member = convert_pointer_to_real (base_binfo, current_class_decl);
expand_aggr_init_1 (base_binfo, 0, expand_aggr_init_1 (base_binfo, 0,
build_indirect_ref (member, NULL_PTR), init, build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL); BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
expand_cleanups_to (NULL_TREE); expand_cleanups_to (old_cleanups);
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots ();
} }
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))) if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
...@@ -749,11 +784,30 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) ...@@ -749,11 +784,30 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
{ {
tree init = purpose_member (binfo, init_list); tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR); tree ref = build_indirect_ref (addr, NULL_PTR);
extern int temp_slot_level;
extern int target_temp_slot_level;
tree old_cleanups = cleanups_this_call;
int old_temp_level = target_temp_slot_level;
push_temp_slots ();
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
if (init) if (init)
init = TREE_VALUE (init); init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */ /* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN); expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
expand_cleanups_to (NULL_TREE);
expand_cleanups_to (old_cleanups);
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
/* There might something left from building the trees. */
if (cleanups_this_call)
{
expand_cleanups_to (NULL_TREE);
}
free_temp_slots ();
} }
/* Initialize this object's virtual base class pointers. This must be /* Initialize this object's virtual base class pointers. This must be
...@@ -818,8 +872,7 @@ do_member_init (s_id, name, init) ...@@ -818,8 +872,7 @@ do_member_init (s_id, name, init)
/* Function to give error message if member initialization specification /* Function to give error message if member initialization specification
is erroneous. FIELD is the member we decided to initialize. is erroneous. FIELD is the member we decided to initialize.
TYPE is the type for which the initialization is being performed. TYPE is the type for which the initialization is being performed.
FIELD must be a member of TYPE, or the base type from which FIELD FIELD must be a member of TYPE.
comes must not need a constructor.
MEMBER_NAME is the name of the member. */ MEMBER_NAME is the name of the member. */
...@@ -831,23 +884,12 @@ member_init_ok_or_else (field, type, member_name) ...@@ -831,23 +884,12 @@ member_init_ok_or_else (field, type, member_name)
{ {
if (field == error_mark_node) if (field == error_mark_node)
return 0; return 0;
if (field == NULL_TREE) if (field == NULL_TREE || DECL_CONTEXT (field) != type)
{ {
cp_error ("class `%T' does not have any field named `%s'", type, cp_error ("class `%T' does not have any field named `%s'", type,
member_name); member_name);
return 0; return 0;
} }
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;
}
if (TREE_STATIC (field)) if (TREE_STATIC (field))
{ {
cp_error ("field `%#D' is static; only point of initialization is its declaration", cp_error ("field `%#D' is static; only point of initialization is its declaration",
...@@ -960,6 +1002,12 @@ expand_member_init (exp, name, init) ...@@ -960,6 +1002,12 @@ expand_member_init (exp, name, init)
return; return;
} }
if (warn_reorder && current_member_init_list)
{
warning ("base initializer for `%s'", IDENTIFIER_POINTER (name));
warning (" will be re-ordered to precede member initializations");
}
base_init = build_tree_list (name, init); base_init = build_tree_list (name, init);
TREE_TYPE (base_init) = basetype; TREE_TYPE (base_init) = basetype;
current_base_init_list = chainon (current_base_init_list, base_init); current_base_init_list = chainon (current_base_init_list, base_init);
...@@ -1354,12 +1402,15 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) ...@@ -1354,12 +1402,15 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
} }
else else
{ {
#if 0
/* This causes testcase return2.C to fail. */
init = TREE_OPERAND (init, 1); init = TREE_OPERAND (init, 1);
init = build (CALL_EXPR, init_type, init = build (CALL_EXPR, init_type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0); TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);
TREE_SIDE_EFFECTS (init) = 1; TREE_SIDE_EFFECTS (init) = 1;
if (init_list) if (init_list)
TREE_VALUE (init_list) = init; TREE_VALUE (init_list) = init;
#endif
} }
} }
...@@ -1508,7 +1559,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) ...@@ -1508,7 +1559,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
cp_error ("ambiguity between conversion to `%T' and constructor", cp_error ("ambiguity between conversion to `%T' and constructor",
type); type);
else else
expand_assignment (exp, rval, 0, 0); expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags);
return; return;
} }
} }
...@@ -1920,7 +1971,7 @@ build_offset_ref (cname, name) ...@@ -1920,7 +1971,7 @@ build_offset_ref (cname, name)
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == CONST_DECL) || TREE_CODE (t) == CONST_DECL)
{ {
TREE_USED (t) = 1; mark_used (t);
return t; return t;
} }
if (TREE_CODE (t) == FIELD_DECL) if (TREE_CODE (t) == FIELD_DECL)
...@@ -2010,7 +2061,7 @@ build_offset_ref (cname, name) ...@@ -2010,7 +2061,7 @@ build_offset_ref (cname, name)
error ("in this context"); error ("in this context");
return error_mark_node; return error_mark_node;
} }
assemble_external (t); mark_used (t);
return build (OFFSET_REF, TREE_TYPE (t), decl, t); return build (OFFSET_REF, TREE_TYPE (t), decl, t);
} }
...@@ -2037,8 +2088,10 @@ build_offset_ref (cname, name) ...@@ -2037,8 +2088,10 @@ build_offset_ref (cname, name)
|| ! allocation_temporary_p ())) || ! allocation_temporary_p ()))
fnfields = copy_list (fnfields); fnfields = copy_list (fnfields);
#if 0
for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t)) for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t))
assemble_external (t); assemble_external (t);
#endif
t = build_tree_list (error_mark_node, fnfields); t = build_tree_list (error_mark_node, fnfields);
TREE_TYPE (t) = build_offset_type (type, unknown_type_node); TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
...@@ -2070,8 +2123,7 @@ build_offset_ref (cname, name) ...@@ -2070,8 +2123,7 @@ build_offset_ref (cname, name)
values can be returned without further ado. */ values can be returned without further ado. */
if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL) if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
{ {
assemble_external (t); mark_used (t);
TREE_USED (t) = 1;
return t; return t;
} }
......
...@@ -86,6 +86,8 @@ Boston, MA 02111-1307, USA. */ ...@@ -86,6 +86,8 @@ Boston, MA 02111-1307, USA. */
"-fno-this-is-variable", "-fno-this-is-variable",
"-fvtable-thunks", "-fvtable-thunks",
"-fno-vtable-thunks", "-fno-vtable-thunks",
"-fweak",
"-fno-weak",
"-fxref", "-fxref",
"-fno-xref", "-fno-xref",
......
...@@ -883,13 +883,16 @@ yyprint (file, yychar, yylval) ...@@ -883,13 +883,16 @@ yyprint (file, yychar, yylval)
static int *reduce_count; static int *reduce_count;
int *token_count; int *token_count;
#if 0
#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0])) #define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0])) #define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
#endif
int * int *
init_parse () init_parse ()
{ {
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1)); reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1)); bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
reduce_count += 1; reduce_count += 1;
...@@ -897,10 +900,12 @@ init_parse () ...@@ -897,10 +900,12 @@ init_parse ()
bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1)); bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
token_count += 1; token_count += 1;
#endif #endif
#endif
return token_count; return token_count;
} }
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
void void
yyhook (yyn) yyhook (yyn)
int yyn; int yyn;
...@@ -922,11 +927,13 @@ token_cmp (p, q) ...@@ -922,11 +927,13 @@ token_cmp (p, q)
return token_count[*q] - token_count[*p]; return token_count[*q] - token_count[*p];
} }
#endif #endif
#endif
void void
print_parse_statistics () print_parse_statistics ()
{ {
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
#if YYDEBUG != 0 #if YYDEBUG != 0
int i; int i;
int maxlen = REDUCE_LENGTH; int maxlen = REDUCE_LENGTH;
...@@ -969,6 +976,7 @@ print_parse_statistics () ...@@ -969,6 +976,7 @@ print_parse_statistics ()
fprintf (stderr, "\n"); fprintf (stderr, "\n");
#endif #endif
#endif #endif
#endif
} }
/* Sets the value of the 'yydebug' variable to VALUE. /* Sets the value of the 'yydebug' variable to VALUE.
...@@ -2590,6 +2598,10 @@ linenum: ...@@ -2590,6 +2598,10 @@ linenum:
p->name = input_filename; p->name = input_filename;
input_file_stack = p; input_file_stack = p;
input_file_stack_tick++; input_file_stack_tick++;
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
dbxout_start_new_source_file (input_filename);
#endif
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
if (debug_info_level == DINFO_LEVEL_VERBOSE if (debug_info_level == DINFO_LEVEL_VERBOSE
&& write_symbols == DWARF_DEBUG) && write_symbols == DWARF_DEBUG)
...@@ -2627,6 +2639,10 @@ linenum: ...@@ -2627,6 +2639,10 @@ linenum:
input_file_stack = p->next; input_file_stack = p->next;
free (p); free (p);
input_file_stack_tick++; input_file_stack_tick++;
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
dbxout_resume_previous_source_file ();
#endif
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
if (debug_info_level == DINFO_LEVEL_VERBOSE if (debug_info_level == DINFO_LEVEL_VERBOSE
&& write_symbols == DWARF_DEBUG) && write_symbols == DWARF_DEBUG)
...@@ -2872,6 +2888,9 @@ do_identifier (token) ...@@ -2872,6 +2888,9 @@ do_identifier (token)
{ {
register tree id = lastiddecl; register tree id = lastiddecl;
if (IDENTIFIER_OPNAME_P (token))
id = lookup_name (token, 0);
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
yychar = yylex (); yychar = yylex ();
/* Scope class declarations before global /* Scope class declarations before global
...@@ -2920,7 +2939,14 @@ do_identifier (token) ...@@ -2920,7 +2939,14 @@ do_identifier (token)
if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node) if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
return id; return id;
} }
if (yychar == '(' || yychar == LEFT_RIGHT)
if (IDENTIFIER_OPNAME_P (token))
{
if (token != ansi_opname[ERROR_MARK])
cp_error ("operator %O not defined", token);
id = error_mark_node;
}
else if (yychar == '(' || yychar == LEFT_RIGHT)
{ {
id = implicitly_declare (token); id = implicitly_declare (token);
} }
...@@ -4360,8 +4386,10 @@ real_yylex () ...@@ -4360,8 +4386,10 @@ real_yylex ()
done: done:
/* yylloc.last_line = lineno; */ /* yylloc.last_line = lineno; */
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
token_count[value] += 1; token_count[value] += 1;
#endif #endif
#endif
return value; return value;
} }
......
...@@ -178,8 +178,13 @@ report_type_mismatch (cp, parmtypes, name_kind) ...@@ -178,8 +178,13 @@ report_type_mismatch (cp, parmtypes, name_kind)
/* Happens when the implicit object parameter is rejected. */ /* Happens when the implicit object parameter is rejected. */
my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))), my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))),
241); 241);
cp_error ("call to non-const %s `%#D' with const object", if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))))
name_kind, cp->function); && ! TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (cp->function))))))
cp_error ("call to non-volatile %s `%#D' with volatile object",
name_kind, cp->function);
else
cp_error ("call to non-const %s `%#D' with const object",
name_kind, cp->function);
return; return;
} }
...@@ -1547,6 +1552,7 @@ hack_identifier (value, name, yychar) ...@@ -1547,6 +1552,7 @@ hack_identifier (value, name, yychar)
if (really_overloaded_fn (value)) if (really_overloaded_fn (value))
{ {
#if 0
tree t = get_first_fn (value); tree t = get_first_fn (value);
for (; t; t = DECL_CHAIN (t)) for (; t; t = DECL_CHAIN (t))
{ {
...@@ -1556,22 +1562,20 @@ hack_identifier (value, name, yychar) ...@@ -1556,22 +1562,20 @@ hack_identifier (value, name, yychar)
assemble_external (t); assemble_external (t);
TREE_USED (t) = 1; TREE_USED (t) = 1;
} }
#endif
} }
else if (TREE_CODE (value) == TREE_LIST) else if (TREE_CODE (value) == TREE_LIST)
{ {
/* Ambiguous reference to base members, possibly other cases?. */
tree t = value; tree t = value;
while (t && TREE_CODE (t) == TREE_LIST) while (t && TREE_CODE (t) == TREE_LIST)
{ {
assemble_external (TREE_VALUE (t)); mark_used (TREE_VALUE (t));
TREE_USED (t) = 1;
t = TREE_CHAIN (t); t = TREE_CHAIN (t);
} }
} }
else else
{ mark_used (value);
assemble_external (value);
TREE_USED (value) = 1;
}
if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
{ {
...@@ -1800,14 +1804,17 @@ make_thunk (function, delta) ...@@ -1800,14 +1804,17 @@ make_thunk (function, delta)
} }
if (thunk == NULL_TREE) if (thunk == NULL_TREE)
{ {
thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl)); thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
DECL_RESULT (thunk) DECL_RESULT (thunk)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type))); = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type)));
TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type)); TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type)); TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk); make_function_rtl (thunk);
TREE_SET_CODE (thunk, THUNK_DECL);
DECL_INITIAL (thunk) = function; DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta; THUNK_DELTA (thunk) = delta;
DECL_EXTERNAL (thunk) = 1;
TREE_PUBLIC (thunk) = 1;
/* So that finish_file can write out any thunks that need to be: */ /* So that finish_file can write out any thunks that need to be: */
pushdecl_top_level (thunk); pushdecl_top_level (thunk);
} }
...@@ -1845,16 +1852,11 @@ emit_thunk (thunk_fndecl) ...@@ -1845,16 +1852,11 @@ emit_thunk (thunk_fndecl)
TREE_ASM_WRITTEN (thunk_fndecl) = 1; TREE_ASM_WRITTEN (thunk_fndecl) = 1;
if (TREE_PUBLIC (function)) if (! TREE_PUBLIC (function))
{ TREE_PUBLIC (thunk_fndecl) = 0;
TREE_PUBLIC (thunk_fndecl) = 1; if (DECL_EXTERNAL (function))
if (DECL_EXTERNAL (function)) return;
{ DECL_EXTERNAL (thunk_fndecl) = 0;
DECL_EXTERNAL (thunk_fndecl) = 1;
assemble_external (thunk_fndecl);
return;
}
}
decl_printable_name = thunk_printable_name; decl_printable_name = thunk_printable_name;
if (current_function_decl) if (current_function_decl)
......
...@@ -661,8 +661,9 @@ fn.def1: ...@@ -661,8 +661,9 @@ fn.def1:
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = NULL_TREE; }
| declmods notype_declarator exception_specification_opt | declmods notype_declarator exception_specification_opt
{ tree specs = strip_attrs ($1); { tree specs, attrs;
if (! start_function (specs, $2, $3, NULL_TREE, 0)) split_specs_attrs ($1, &specs, &attrs);
if (! start_function (specs, $2, $3, attrs, 0))
YYERROR1; YYERROR1;
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = NULL_TREE; }
...@@ -1306,18 +1307,6 @@ primary: ...@@ -1306,18 +1307,6 @@ primary:
{ {
if (TREE_CODE ($$) == BIT_NOT_EXPR) if (TREE_CODE ($$) == BIT_NOT_EXPR)
$$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0)); $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
else if (IDENTIFIER_OPNAME_P ($$))
{
tree op = $$;
$$ = lookup_name (op, 0);
if ($$ == NULL_TREE)
{
if (op != ansi_opname[ERROR_MARK])
error ("operator %s not defined",
operator_name_string (op));
$$ = error_mark_node;
}
}
else else
$$ = do_identifier ($$); $$ = do_identifier ($$);
} }
...@@ -1531,10 +1520,9 @@ primary: ...@@ -1531,10 +1520,9 @@ primary:
else else
{ {
if (TREE_CODE ($$) == ADDR_EXPR) if (TREE_CODE ($$) == ADDR_EXPR)
assemble_external (TREE_OPERAND ($$, 0)); mark_used (TREE_OPERAND ($$, 0));
else else
assemble_external ($$); mark_used ($$);
TREE_USED ($$) = 1;
} }
if (TREE_CODE ($$) == CONST_DECL) if (TREE_CODE ($$) == CONST_DECL)
{ {
...@@ -3545,6 +3533,9 @@ for.init.statement: ...@@ -3545,6 +3533,9 @@ for.init.statement:
{ if ($1) cplus_expand_expr_stmt ($1); } { if ($1) cplus_expand_expr_stmt ($1); }
| decl | decl
| '{' compstmtend | '{' compstmtend
{ if (pedantic)
pedwarn ("ANSI C++ forbids compound statements inside for initializations");
}
; ;
/* Either a type-qualifier or nothing. First thing in an `asm' statement. */ /* Either a type-qualifier or nothing. First thing in an `asm' statement. */
......
...@@ -2400,7 +2400,7 @@ do_pending_expansions () ...@@ -2400,7 +2400,7 @@ do_pending_expansions ()
if (i->interface == 1) if (i->interface == 1)
/* OK, it was an implicit instantiation. */ /* OK, it was an implicit instantiation. */
{ {
if (SUPPORTS_WEAK) if (flag_weak)
DECL_WEAK (t) = 1; DECL_WEAK (t) = 1;
else else
TREE_PUBLIC (t) = 0; TREE_PUBLIC (t) = 0;
...@@ -2533,6 +2533,8 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2533,6 +2533,8 @@ do_function_instantiation (declspecs, declarator, storage)
fn = IDENTIFIER_GLOBAL_VALUE (name), fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (fn)) fn && DECL_TEMPLATE_INSTANTIATION (fn))
result = fn; result = fn;
else if (fn && DECL_CONTEXT (fn))
;
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn) else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{ {
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn)) for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
......
...@@ -3507,11 +3507,17 @@ static void ...@@ -3507,11 +3507,17 @@ static void
add_conversions (binfo) add_conversions (binfo)
tree binfo; tree binfo;
{ {
tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo)); int i;
for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)); tree vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tmp = TREE_CHAIN (tmp))
conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)), for (i = 1; i < TREE_VEC_LENGTH (vec); ++i)
conversions); {
tree tmp = TREE_VEC_ELT (vec, i);
if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)))
break;
conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
conversions);
}
} }
tree tree
......
...@@ -1766,7 +1766,7 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1766,7 +1766,7 @@ build_component_ref (datum, component, basetype_path, protect)
my_friendly_assert (datum != error_mark_node, 310); my_friendly_assert (datum != error_mark_node, 310);
fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl)); fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
} }
assemble_external (fndecl); mark_used (fndecl);
return fndecl; return fndecl;
} }
if (access == access_protected) if (access == access_protected)
...@@ -1781,8 +1781,10 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1781,8 +1781,10 @@ build_component_ref (datum, component, basetype_path, protect)
not matter unless we're actually calling the function. */ not matter unless we're actually calling the function. */
tree t; tree t;
#if 0
for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t)) for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t))
assemble_external (t); assemble_external (t);
#endif
t = build_tree_list (error_mark_node, fndecls); t = build_tree_list (error_mark_node, fndecls);
TREE_TYPE (t) = build_offset_type (basetype, TREE_TYPE (t) = build_offset_type (basetype,
...@@ -1809,9 +1811,10 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1809,9 +1811,10 @@ build_component_ref (datum, component, basetype_path, protect)
cp_error ("invalid use of type decl `%#D' as expression", field); cp_error ("invalid use of type decl `%#D' as expression", field);
return error_mark_node; return error_mark_node;
} }
if (DECL_RTL (field) != 0) else if (DECL_RTL (field) != 0)
assemble_external (field); mark_used (field);
TREE_USED (field) = 1; else
TREE_USED (field) = 1;
return field; return field;
} }
} }
...@@ -2347,7 +2350,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) ...@@ -2347,7 +2350,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
/* Save the intermediate result in a SAVE_EXPR so we don't have to /* Save the intermediate result in a SAVE_EXPR so we don't have to
compute each component of the virtual function pointer twice. */ compute each component of the virtual function pointer twice. */
if (/* !building_cleanup && */ TREE_CODE (aref) == INDIRECT_REF) if (TREE_CODE (aref) == INDIRECT_REF)
TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
delta = build_binary_op (PLUS_EXPR, delta = build_binary_op (PLUS_EXPR,
...@@ -2400,7 +2403,7 @@ build_function_call_real (function, params, require_complete, flags) ...@@ -2400,7 +2403,7 @@ build_function_call_real (function, params, require_complete, flags)
GNU_xref_call (current_function_decl, GNU_xref_call (current_function_decl,
IDENTIFIER_POINTER (name ? name IDENTIFIER_POINTER (name ? name
: TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function)))); : TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function))));
assemble_external (function); mark_used (function);
fndecl = function; fndecl = function;
/* Convert anything with function type to a pointer-to-function. */ /* Convert anything with function type to a pointer-to-function. */
...@@ -2426,8 +2429,7 @@ build_function_call_real (function, params, require_complete, flags) ...@@ -2426,8 +2429,7 @@ build_function_call_real (function, params, require_complete, flags)
if (DECL_INLINE (function)) if (DECL_INLINE (function))
{ {
/* Is it a synthesized method that needs to be synthesized? */ /* Is it a synthesized method that needs to be synthesized? */
if (DECL_ARTIFICIAL (function) && ! flag_no_inline if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
&& ! DECL_INITIAL (function)
/* Kludge: don't synthesize for default args. */ /* Kludge: don't synthesize for default args. */
&& current_function_decl) && current_function_decl)
synthesize_method (function); synthesize_method (function);
...@@ -2438,11 +2440,7 @@ build_function_call_real (function, params, require_complete, flags) ...@@ -2438,11 +2440,7 @@ build_function_call_real (function, params, require_complete, flags)
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
} }
else else
{ function = default_conversion (function);
assemble_external (function);
TREE_USED (function) = 1;
function = default_conversion (function);
}
} }
else else
{ {
...@@ -2718,7 +2716,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) ...@@ -2718,7 +2716,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
type = integer_type_node; type = integer_type_node;
#endif #endif
parmval = convert_for_initialization (return_loc, type, val, flags, parmval = convert_for_initialization (return_loc, type, val,
flags|INDIRECT_BIND,
"argument passing", fndecl, i); "argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES #ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE if ((TREE_CODE (type) == INTEGER_TYPE
...@@ -3554,6 +3553,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3554,6 +3553,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree primop0 = get_narrower (op0, &unsignedp0); tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1); tree primop1 = get_narrower (op1, &unsignedp1);
/* Check for comparison of different enum types. */
if (flag_int_enum_equivalence == 0
&& TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
!= TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
{
cp_warning ("comparison between `%#T' and `%#T'",
TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
}
/* Give warnings for comparisons between signed and unsigned /* Give warnings for comparisons between signed and unsigned
quantities that may fail. */ quantities that may fail. */
/* Do the checking based on the original operand trees, so that /* Do the checking based on the original operand trees, so that
...@@ -4068,7 +4078,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4068,7 +4078,7 @@ build_unary_op (code, xarg, noconvert)
case FIX_ROUND_EXPR: case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR: case FIX_CEIL_EXPR:
{ {
tree incremented, modify, value; tree incremented, modify, value, compound;
if (! lvalue_p (arg) && pedantic) if (! lvalue_p (arg) && pedantic)
pedwarn ("cast to non-reference type used as lvalue"); pedwarn ("cast to non-reference type used as lvalue");
arg = stabilize_reference (arg); arg = stabilize_reference (arg);
...@@ -4081,8 +4091,13 @@ build_unary_op (code, xarg, noconvert) ...@@ -4081,8 +4091,13 @@ build_unary_op (code, xarg, noconvert)
? PLUS_EXPR : MINUS_EXPR), ? PLUS_EXPR : MINUS_EXPR),
argtype, value, inc); argtype, value, inc);
TREE_SIDE_EFFECTS (incremented) = 1; TREE_SIDE_EFFECTS (incremented) = 1;
modify = build_modify_expr (arg, NOP_EXPR, incremented); modify = build_modify_expr (arg, NOP_EXPR, incremented);
return build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value); compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
/* Eliminate warning about unused result of + or -. */
TREE_NO_UNUSED_WARNING (compound) = 1;
return compound;
} }
} }
...@@ -4549,8 +4564,6 @@ mark_addressable (exp) ...@@ -4549,8 +4564,6 @@ mark_addressable (exp)
TREE_ADDRESSABLE (x) = 1; TREE_ADDRESSABLE (x) = 1;
TREE_USED (x) = 1; TREE_USED (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
if (asm_out_file)
assemble_external (x);
return 1; return 1;
default: default:
...@@ -5563,9 +5576,19 @@ tree ...@@ -5563,9 +5576,19 @@ tree
expand_target_expr (t) expand_target_expr (t)
tree t; tree t;
{ {
extern int temp_slot_level;
extern int target_temp_slot_level;
int old_temp_level = target_temp_slot_level;
tree xval = make_node (RTL_EXPR); tree xval = make_node (RTL_EXPR);
rtx rtxval; rtx rtxval;
/* Any TARGET_EXPR temps live only as long as the outer temp level.
Since they are preserved in this new inner level, we know they
will make it into the outer level. */
push_temp_slots ();
target_temp_slot_level = temp_slot_level;
do_pending_stack_adjust (); do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval); start_sequence_for_rtl_expr (xval);
emit_note (0, -1); emit_note (0, -1);
...@@ -5576,6 +5599,10 @@ expand_target_expr (t) ...@@ -5576,6 +5599,10 @@ expand_target_expr (t)
end_sequence (); end_sequence ();
RTL_EXPR_RTL (xval) = rtxval; RTL_EXPR_RTL (xval) = rtxval;
TREE_TYPE (xval) = TREE_TYPE (t); TREE_TYPE (xval) = TREE_TYPE (t);
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
return xval; return xval;
} }
......
...@@ -569,8 +569,6 @@ store_init_value (decl, init) ...@@ -569,8 +569,6 @@ store_init_value (decl, init)
if (TREE_CODE (init) == CONSTRUCTOR) if (TREE_CODE (init) == CONSTRUCTOR)
{ {
tree field; tree field;
tree funcs;
int func;
/* Check that we're really an aggregate as ARM 8.4.1 defines it. */ /* Check that we're really an aggregate as ARM 8.4.1 defines it. */
if (CLASSTYPE_N_BASECLASSES (type)) if (CLASSTYPE_N_BASECLASSES (type))
...@@ -588,16 +586,11 @@ store_init_value (decl, init) ...@@ -588,16 +586,11 @@ store_init_value (decl, init)
cp_error_at ("initializer list construction invalid for `%D'", decl); cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field); cp_error_at ("due to non-public access of member `%D'", field);
} }
funcs = TYPE_METHODS (type); for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
if (funcs) if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
for (func = 0; func < TREE_VEC_LENGTH (funcs); func++)
{ {
field = TREE_VEC_ELT (funcs, func); cp_error_at ("initializer list construction invalid for `%D'", decl);
if (field && (TREE_PRIVATE (field) || TREE_PROTECTED (field))) cp_error_at ("due to non-public access of member `%D'", field);
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
} }
} }
#endif #endif
...@@ -894,10 +887,16 @@ digest_init (type, init, tail) ...@@ -894,10 +887,16 @@ digest_init (type, init, tail)
return process_init_constructor (type, init, (tree *)0); return process_init_constructor (type, init, (tree *)0);
else if (TYPE_NON_AGGREGATE_CLASS (type)) else if (TYPE_NON_AGGREGATE_CLASS (type))
{ {
#if 0
/* This isn't true. */
/* This can only be reached when caller is initializing /* This can only be reached when caller is initializing
ARRAY_TYPE. In that case, we don't want to convert ARRAY_TYPE. In that case, we don't want to convert
INIT to TYPE. We will let `expand_vec_init' do it. */ INIT to TYPE. We will let `expand_vec_init' do it. */
return init; return init;
#else
return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0);
#endif
} }
else if (tail != 0) else if (tail != 0)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment