Commit f376e137 by Mike Stump

47th Cygnus<->FSF merge

From-SVN: r8129
parent 96f218bb
...@@ -1814,7 +1814,11 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1814,7 +1814,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
} }
else else
{ {
if (TREE_CODE (instance) != CALL_EXPR) if (TREE_CODE (instance) != CALL_EXPR
#ifdef PCC_STATIC_STRUCT_RETURN
&& TREE_CODE (instance) != RTL_EXPR
#endif
)
my_friendly_abort (125); my_friendly_abort (125);
if (TYPE_NEEDS_CONSTRUCTING (basetype)) if (TYPE_NEEDS_CONSTRUCTING (basetype))
instance = build_cplus_new (basetype, instance, 0); instance = build_cplus_new (basetype, instance, 0);
...@@ -1943,7 +1947,9 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1943,7 +1947,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
constp = 0; constp = 0;
volatilep = 0; volatilep = 0;
parms = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node), parms); parms = tree_cons (NULL_TREE,
build1 (NOP_EXPR, TYPE_POINTER_TO (basetype),
integer_zero_node), parms);
} }
else else
{ {
...@@ -2023,6 +2029,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2023,6 +2029,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
return error_mark_node; return error_mark_node;
#if 0
/* Now, go look for this method name. We do not find destructors here. /* Now, go look for this method name. We do not find destructors here.
Putting `void_list_node' on the end of the parmtypes Putting `void_list_node' on the end of the parmtypes
...@@ -2032,6 +2039,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2032,6 +2039,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
1 + (name == constructor_name (save_basetype) 1 + (name == constructor_name (save_basetype)
|| name == constructor_name_full (save_basetype))); || name == constructor_name_full (save_basetype)));
TREE_CHAIN (last) = NULL_TREE; TREE_CHAIN (last) = NULL_TREE;
#endif
for (pass = 0; pass < 2; pass++) for (pass = 0; pass < 2; pass++)
{ {
...@@ -2073,7 +2081,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2073,7 +2081,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
tree new_type; tree new_type;
parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
new_type = c_build_type_variant (TREE_TYPE (parm), constp, new_type = cp_build_type_variant (TREE_TYPE (parm), constp,
volatilep); volatilep);
new_type = build_reference_type (new_type); new_type = build_reference_type (new_type);
parm = convert (new_type, parm); parm = convert (new_type, parm);
...@@ -2158,9 +2166,11 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2158,9 +2166,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& ! DECL_STATIC_FUNCTION_P (function)) && ! DECL_STATIC_FUNCTION_P (function))
continue; continue;
#if 0
if (pass == 0 if (pass == 0
&& DECL_ASSEMBLER_NAME (function) == method_name) && DECL_ASSEMBLER_NAME (function) == method_name)
goto found; goto found;
#endif
if (pass > 0) if (pass > 0)
{ {
...@@ -2255,6 +2265,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2255,6 +2265,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (cp - candidates > 1) if (cp - candidates > 1)
{ {
int n_candidates = cp - candidates; int n_candidates = cp - candidates;
extern int warn_synth;
TREE_VALUE (parms) = instance_ptr; TREE_VALUE (parms) = instance_ptr;
cp = ideal_candidate (save_basetype, candidates, cp = ideal_candidate (save_basetype, candidates,
n_candidates, parms, len); n_candidates, parms, len);
...@@ -2262,14 +2273,25 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2262,14 +2273,25 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
if (flags & LOOKUP_COMPLAIN) if (flags & LOOKUP_COMPLAIN)
{ {
cp_error ("call of overloaded %s `%D' is ambiguous", TREE_CHAIN (last) = void_list_node;
name_kind, name); cp_error ("call of overloaded %s `%D(%A)' is ambiguous",
name_kind, name, TREE_CHAIN (parmtypes));
print_n_candidates (candidates, n_candidates); print_n_candidates (candidates, n_candidates);
} }
return error_mark_node; return error_mark_node;
} }
if (cp->h.code & EVIL_CODE) if (cp->h.code & EVIL_CODE)
return error_mark_node; return error_mark_node;
if (warn_synth
&& DECL_NAME (cp->function) == ansi_opname[MODIFY_EXPR]
&& DECL_ARTIFICIAL (cp->function)
&& n_candidates == 2)
{
cp_warning ("using synthesized `%#D' for copy assignment",
cp->function);
cp_warning_at (" where cfront would use `%#D'",
candidates->function);
}
} }
else if (cp[-1].h.code & EVIL_CODE) else if (cp[-1].h.code & EVIL_CODE)
{ {
......
...@@ -2743,6 +2743,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2743,6 +2743,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
will fill in the right line number. (mrs) */ will fill in the right line number. (mrs) */
if (DECL_SOURCE_LINE (name)) if (DECL_SOURCE_LINE (name))
DECL_SOURCE_LINE (name) = lineno; DECL_SOURCE_LINE (name) = lineno;
CLASSTYPE_SOURCE_LINE (t) = lineno;
} }
name = DECL_NAME (name); name = DECL_NAME (name);
} }
...@@ -2772,6 +2773,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2772,6 +2773,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_GOT_SEMICOLON (t) = 0;
#if 0
/* This is in general too late to do this. I moved the main case up to /* This is in general too late to do this. I moved the main case up to
left_curly, what else needs to move? */ left_curly, what else needs to move? */
if (! IS_SIGNATURE (t)) if (! IS_SIGNATURE (t))
...@@ -2779,6 +2781,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2779,6 +2781,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999);
my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999); my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999);
} }
#endif
if (flag_dossier) if (flag_dossier)
build_t_desc (t, 0); build_t_desc (t, 0);
...@@ -2841,6 +2844,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2841,6 +2844,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
needs_virtual_dtor = 0; needs_virtual_dtor = 0;
} }
#if 0
/* Both of these should be done before now. */ /* Both of these should be done before now. */
if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t) if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t)
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
...@@ -2848,6 +2852,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -2848,6 +2852,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999);
my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999); my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999);
} }
#endif
/* The three of these are approximations which may later be /* The three of these are approximations which may later be
modified. Needed at this point to make add_virtual_function modified. Needed at this point to make add_virtual_function
...@@ -3004,6 +3009,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3004,6 +3009,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
} }
if (DECL_NAME (x) == constructor_name (t))
cant_have_default_ctor = cant_synth_copy_ctor = 1;
if (TREE_TYPE (x) == error_mark_node) if (TREE_TYPE (x) == error_mark_node)
continue; continue;
...@@ -3270,12 +3278,14 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3270,12 +3278,14 @@ finish_struct (t, list_of_fieldlists, warn_anon)
CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init; CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals; CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
&& !IS_SIGNATURE (t)) && !IS_SIGNATURE (t))
{ {
/* Here we must cons up a destructor on the fly. */ /* Here we must cons up a destructor on the fly. */
tree dtor = cons_up_default_function (t, name, fields, tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0);
needs_virtual_dtor != 0);
/* If we couldn't make it work, then pretend we didn't need it. */ /* If we couldn't make it work, then pretend we didn't need it. */
if (dtor == void_type_node) if (dtor == void_type_node)
...@@ -3304,9 +3314,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3304,9 +3314,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
if (! fn_fields) if (! fn_fields)
nonprivate_method = 1; nonprivate_method = 1;
...@@ -3324,7 +3331,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3324,7 +3331,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
{ {
tree default_fn = cons_up_default_function (t, name, fields, 2); tree default_fn = cons_up_default_function (t, name, 2);
TREE_CHAIN (default_fn) = fn_fields; TREE_CHAIN (default_fn) = fn_fields;
fn_fields = default_fn; fn_fields = default_fn;
} }
...@@ -3335,9 +3342,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3335,9 +3342,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
{ {
/* ARM 12.18: You get either X(X&) or X(const X&), but /* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */ not both. --Chip */
tree default_fn = tree default_fn = cons_up_default_function (t, name,
cons_up_default_function (t, name, fields, 3 + cant_have_const_ctor);
cant_have_const_ctor ? 4 : 3);
TREE_CHAIN (default_fn) = fn_fields; TREE_CHAIN (default_fn) = fn_fields;
fn_fields = default_fn; fn_fields = default_fn;
} }
...@@ -3351,9 +3357,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3351,9 +3357,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
{ {
tree default_fn = tree default_fn = cons_up_default_function (t, name,
cons_up_default_function (t, name, fields, 5 + no_const_asn_ref);
no_const_asn_ref ? 6 : 5);
TREE_CHAIN (default_fn) = fn_fields; TREE_CHAIN (default_fn) = fn_fields;
fn_fields = default_fn; fn_fields = default_fn;
} }
...@@ -3404,7 +3409,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3404,7 +3409,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree flist = NULL_TREE; tree flist = NULL_TREE;
tree name; tree name;
enum access_type access = (enum access_type)TREE_PURPOSE(access_decls); enum access_type access = (enum access_type)TREE_PURPOSE(access_decls);
int i = 0; int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1;
tree tmp; tree tmp;
if (TREE_CODE (fdecl) == TREE_LIST) if (TREE_CODE (fdecl) == TREE_LIST)
...@@ -3512,28 +3517,24 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3512,28 +3517,24 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* Delete all duplicate fields from the fields */ /* Delete all duplicate fields from the fields */
delete_duplicate_fields (fields); delete_duplicate_fields (fields);
/* Catch function/field name conflict, removing the field (since it's /* Catch function/field name conflict. We don't need to do this for a
easier). */ signature, since it can only contain the fields constructed in
append_signature_fields. */
if (! IS_SIGNATURE (t))
{ {
int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
tree last = NULL_TREE;
for (x = fields; x; x = TREE_CHAIN (x)) for (x = fields; x; x = TREE_CHAIN (x))
{ {
tree name = DECL_NAME (x); tree name = DECL_NAME (x);
int i; int i = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1;
for (i = 0; i < n_methods; ++i) for (; i < n_methods; ++i)
if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name) if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
{ {
cp_error_at ("data member `%#D' conflicts with", x); cp_error_at ("data member `%#D' conflicts with", x);
cp_error_at ("function member `%#D'", cp_error_at ("function member `%#D'",
TREE_VEC_ELT (method_vec, i)); TREE_VEC_ELT (method_vec, i));
if (last)
TREE_CHAIN (last) = TREE_CHAIN (x);
else
fields = TREE_CHAIN (x);
break; break;
} }
last = x;
} }
} }
...@@ -4967,12 +4968,14 @@ instantiate_type (lhstype, rhs, complain) ...@@ -4967,12 +4968,14 @@ instantiate_type (lhstype, rhs, complain)
} }
TREE_TYPE (rhs) = lhstype; TREE_TYPE (rhs) = lhstype;
lhstype = TREE_TYPE (lhstype); lhstype = TREE_TYPE (lhstype);
TREE_OPERAND (rhs, 0) {
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node) if (fn == error_mark_node)
return error_mark_node; return error_mark_node;
mark_addressable (fn);
mark_addressable (TREE_OPERAND (rhs, 0)); TREE_OPERAND (rhs, 0) = fn;
TREE_CONSTANT (rhs) = staticp (fn);
}
return rhs; return rhs;
case ENTRY_VALUE_EXPR: case ENTRY_VALUE_EXPR:
......
...@@ -502,8 +502,12 @@ struct lang_type ...@@ -502,8 +502,12 @@ struct lang_type
union tree_node *signature; union tree_node *signature;
union tree_node *signature_pointer_to; union tree_node *signature_pointer_to;
union tree_node *signature_reference_to; union tree_node *signature_reference_to;
int linenum;
}; };
#define CLASSTYPE_SOURCE_LINE(NODE) (TYPE_LANG_SPECIFIC(NODE)->linenum)
/* Indicates whether or not (and how) a template was expanded for this class. /* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class 0=no information yet/non-template class
1=implicit template instantiation 1=implicit template instantiation
...@@ -1355,7 +1359,7 @@ extern void check_function_format PROTO((tree, tree, tree)); ...@@ -1355,7 +1359,7 @@ extern void check_function_format PROTO((tree, tree, tree));
/* Print an error message for invalid operands to arith operation CODE. /* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */ NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code)); extern void binary_op_error PROTO((enum tree_code));
extern tree c_build_type_variant PROTO((tree, int, int)); extern tree cp_build_type_variant PROTO((tree, int, int));
extern void c_expand_expr_stmt PROTO((tree)); extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */ /* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PROTO((tree)); extern tree check_case_value PROTO((tree));
...@@ -2011,7 +2015,7 @@ extern void expand_end_all_catch PROTO((void)); ...@@ -2011,7 +2015,7 @@ extern void expand_end_all_catch PROTO((void));
extern void start_catch_block PROTO((tree, tree)); extern void start_catch_block PROTO((tree, tree));
extern void end_catch_block PROTO((void)); extern void end_catch_block PROTO((void));
extern void expand_throw PROTO((tree)); extern void expand_throw PROTO((tree));
extern void build_exception_table PROTO((void)); extern int build_exception_table PROTO((void));
extern tree build_throw PROTO((tree)); extern tree build_throw PROTO((tree));
extern void init_exception_processing PROTO((void)); extern void init_exception_processing PROTO((void));
...@@ -2091,7 +2095,7 @@ extern void reinit_parse_for_method PROTO((int, tree)); ...@@ -2091,7 +2095,7 @@ extern void reinit_parse_for_method PROTO((int, tree));
#if 0 #if 0
extern void reinit_parse_for_block PROTO((int, struct obstack *, int)); extern void reinit_parse_for_block PROTO((int, struct obstack *, int));
#endif #endif
extern tree cons_up_default_function PROTO((tree, tree, tree, int)); extern tree cons_up_default_function PROTO((tree, tree, int));
extern void check_for_missing_semicolon PROTO((tree)); extern void check_for_missing_semicolon PROTO((tree));
extern void note_got_semicolon PROTO((tree)); extern void note_got_semicolon PROTO((tree));
extern void note_list_got_semicolon PROTO((tree)); extern void note_list_got_semicolon PROTO((tree));
...@@ -2141,6 +2145,7 @@ extern void clear_anon_parm_name PROTO((void)); ...@@ -2141,6 +2145,7 @@ extern void clear_anon_parm_name PROTO((void));
extern void do_inline_function_hair PROTO((tree, tree)); extern void do_inline_function_hair PROTO((tree, tree));
/* skip report_type_mismatch */ /* skip report_type_mismatch */
extern char *build_overload_name PROTO((tree, int, int)); extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, tree));
extern tree cplus_exception_name PROTO((tree)); extern tree cplus_exception_name PROTO((tree));
extern tree build_decl_overload PROTO((tree, tree, int)); extern tree build_decl_overload PROTO((tree, tree, int));
extern tree build_typename_overload PROTO((tree)); extern tree build_typename_overload PROTO((tree));
......
...@@ -304,7 +304,7 @@ build_up_reference (type, arg, flags, checkconst) ...@@ -304,7 +304,7 @@ build_up_reference (type, arg, flags, checkconst)
/* Pass along const and volatile down into the type. */ /* Pass along const and volatile down into the type. */
if (TYPE_READONLY (type) || TYPE_VOLATILE (type)) if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
target_type = c_build_type_variant (target_type, TYPE_READONLY (type), target_type = cp_build_type_variant (target_type, TYPE_READONLY (type),
TYPE_VOLATILE (type)); TYPE_VOLATILE (type));
targ = arg; targ = arg;
if (TREE_CODE (targ) == SAVE_EXPR) if (TREE_CODE (targ) == SAVE_EXPR)
...@@ -494,6 +494,8 @@ build_up_reference (type, arg, flags, checkconst) ...@@ -494,6 +494,8 @@ build_up_reference (type, arg, flags, checkconst)
return rval; return rval;
} }
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
case INIT_EXPR: case INIT_EXPR:
{ {
...@@ -634,7 +636,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ...@@ -634,7 +636,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{ {
int r = TREE_READONLY (expr); int r = TREE_READONLY (expr);
int v = TREE_THIS_VOLATILE (expr); int v = TREE_THIS_VOLATILE (expr);
ttr = c_build_type_variant (TREE_TYPE (expr), r, v); ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
} }
if (! lvalue_p (expr) && if (! lvalue_p (expr) &&
...@@ -2041,5 +2043,5 @@ type_promotes_to (type) ...@@ -2041,5 +2043,5 @@ type_promotes_to (type)
else if (type == float_type_node) else if (type == float_type_node)
type = double_type_node; type = double_type_node;
return c_build_type_variant (type, constp, volatilep); return cp_build_type_variant (type, constp, volatilep);
} }
...@@ -212,6 +212,12 @@ int warn_nonvdtor; ...@@ -212,6 +212,12 @@ int warn_nonvdtor;
/* Non-zero means warn when a function is declared extern and later inline. */ /* Non-zero means warn when a function is declared extern and later inline. */
int warn_extern_inline; int warn_extern_inline;
/* Non-zero means warn when the compiler will reorder code. */
int warn_reorder;
/* Non-zero means warn when sysnthesis behavior differs from Cfront's. */
int warn_synth;
/* Nonzero means `$' can be in an identifier. /* Nonzero means `$' can be in an identifier.
See cccp.c for reasons why this breaks some obscure ANSI C programs. */ See cccp.c for reasons why this breaks some obscure ANSI C programs. */
...@@ -521,6 +527,10 @@ lang_decode_option (p) ...@@ -521,6 +527,10 @@ lang_decode_option (p)
warn_nonvdtor = setting; warn_nonvdtor = setting;
else if (!strcmp (p, "extern-inline")) else if (!strcmp (p, "extern-inline"))
warn_extern_inline = setting; warn_extern_inline = setting;
else if (!strcmp (p, "reorder"))
warn_reorder = setting;
else if (!strcmp (p, "synth"))
warn_synth = setting;
else if (!strcmp (p, "comment")) else if (!strcmp (p, "comment"))
; /* cpp handles this one. */ ; /* cpp handles this one. */
else if (!strcmp (p, "comments")) else if (!strcmp (p, "comments"))
...@@ -547,6 +557,7 @@ lang_decode_option (p) ...@@ -547,6 +557,7 @@ lang_decode_option (p)
if (warn_uninitialized != 1) if (warn_uninitialized != 1)
warn_uninitialized = (setting ? 2 : 0); warn_uninitialized = (setting ? 2 : 0);
warn_template_debugging = setting; warn_template_debugging = setting;
warn_reorder = setting;
} }
else if (!strcmp (p, "overloaded-virtual")) else if (!strcmp (p, "overloaded-virtual"))
...@@ -1065,12 +1076,21 @@ delete_sanity (exp, size, doing_vec, use_global_delete) ...@@ -1065,12 +1076,21 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return build1 (NOP_EXPR, void_type_node, t); return build1 (NOP_EXPR, void_type_node, t);
} }
if (code == POINTER_TYPE)
{
/* You can't delete a pointer to constant. */ /* You can't delete a pointer to constant. */
if (code == POINTER_TYPE && TREE_READONLY (TREE_TYPE (type))) if (TREE_READONLY (TREE_TYPE (type)))
{ {
error ("`const *' cannot be deleted"); error ("`const *' cannot be deleted");
return error_mark_node; return error_mark_node;
} }
/* You also can't delete functions. */
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
error ("cannot delete a function");
return error_mark_node;
}
}
#if 0 #if 0
/* If the type has no destructor, then we should build a regular /* If the type has no destructor, then we should build a regular
...@@ -1309,19 +1329,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) ...@@ -1309,19 +1329,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
/* current_class_type can be NULL_TREE in case of error. */ /* current_class_type can be NULL_TREE in case of error. */
if (asmspec == 0 && current_class_type) if (asmspec == 0 && current_class_type)
{ {
tree name;
char *buf, *buf2;
buf2 = build_overload_name (current_class_type, 1, 1);
buf = (char *)alloca (IDENTIFIER_LENGTH (DECL_NAME (value))
+ sizeof (STATIC_NAME_FORMAT)
+ strlen (buf2));
sprintf (buf, STATIC_NAME_FORMAT, buf2,
IDENTIFIER_POINTER (DECL_NAME (value)));
name = get_identifier (buf);
TREE_PUBLIC (value) = 1; TREE_PUBLIC (value) = 1;
DECL_INITIAL (value) = error_mark_node; DECL_INITIAL (value) = error_mark_node;
DECL_ASSEMBLER_NAME (value) = name; DECL_ASSEMBLER_NAME (value)
= build_static_name (current_class_type, DECL_NAME (value));
} }
pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics); pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
...@@ -1374,9 +1385,11 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree) ...@@ -1374,9 +1385,11 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
if (DECL_FRIEND_P (value)) if (DECL_FRIEND_P (value))
return void_type_node; return void_type_node;
#if 0 /* Just because a fn is declared doesn't mean we'll try to define it. */
if (current_function_decl && ! IS_SIGNATURE (current_class_type)) if (current_function_decl && ! IS_SIGNATURE (current_class_type))
cp_error ("method `%#D' of local class must be defined in class body", cp_error ("method `%#D' of local class must be defined in class body",
value); value);
#endif
DECL_IN_AGGR_P (value) = 1; DECL_IN_AGGR_P (value) = 1;
return value; return value;
...@@ -2591,8 +2604,7 @@ finish_file () ...@@ -2591,8 +2604,7 @@ finish_file ()
tree fnname; tree fnname;
tree vars = static_aggregates; tree vars = static_aggregates;
int needs_cleaning = 0, needs_messing_up = 0; int needs_cleaning = 0, needs_messing_up = 0;
int have_exception_handlers = build_exception_table ();
build_exception_table ();
if (flag_detailed_statistics) if (flag_detailed_statistics)
dump_tree_statistics (); dump_tree_statistics ();
...@@ -2686,7 +2698,7 @@ finish_file () ...@@ -2686,7 +2698,7 @@ finish_file ()
mess_up: mess_up:
/* Must do this while we think we are at the top level. */ /* Must do this while we think we are at the top level. */
vars = nreverse (static_aggregates); vars = nreverse (static_aggregates);
if (vars != NULL_TREE) if (vars != NULL_TREE || have_exception_handlers)
{ {
fnname = get_file_function_name ('I'); fnname = get_file_function_name ('I');
start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
...@@ -2698,6 +2710,9 @@ finish_file () ...@@ -2698,6 +2710,9 @@ finish_file ()
push_momentary (); push_momentary ();
expand_start_bindings (0); expand_start_bindings (0);
if (have_exception_handlers)
register_exception_table ();
while (vars) while (vars)
{ {
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
......
...@@ -571,7 +571,8 @@ dump_decl (t, v) ...@@ -571,7 +571,8 @@ dump_decl (t, v)
{ {
/* Don't say 'typedef class A' */ /* Don't say 'typedef class A' */
tree type = TREE_TYPE (t); tree type = TREE_TYPE (t);
if (IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type) if (((IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type))
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& type == TYPE_MAIN_VARIANT (type)) && type == TYPE_MAIN_VARIANT (type))
{ {
dump_type (type, v); dump_type (type, v);
...@@ -668,7 +669,7 @@ dump_decl (t, v) ...@@ -668,7 +669,7 @@ dump_decl (t, v)
case TEMPLATE_DECL: case TEMPLATE_DECL:
{ {
tree args = DECL_TEMPLATE_PARMS (t); tree args = DECL_TEMPLATE_PARMS (t);
int i, len = TREE_VEC_LENGTH (args); int i, len = args ? TREE_VEC_LENGTH (args) : 0;
OB_PUTS ("template <"); OB_PUTS ("template <");
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
...@@ -691,6 +692,7 @@ dump_decl (t, v) ...@@ -691,6 +692,7 @@ dump_decl (t, v)
OB_PUTC2 (',', ' '); OB_PUTC2 (',', ' ');
} }
if (len != 0)
OB_UNPUT (2); OB_UNPUT (2);
OB_PUTC2 ('>', ' '); OB_PUTC2 ('>', ' ');
...@@ -1350,12 +1352,26 @@ int ...@@ -1350,12 +1352,26 @@ int
cp_line_of (t) cp_line_of (t)
tree t; tree t;
{ {
int line = 0;
if (TREE_CODE (t) == PARM_DECL) if (TREE_CODE (t) == PARM_DECL)
return DECL_SOURCE_LINE (DECL_CONTEXT (t)); line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
return DECL_SOURCE_LINE (TYPE_NAME (t)); t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
if (IS_AGGR_TYPE (t))
line = CLASSTYPE_SOURCE_LINE (t);
else else
return DECL_SOURCE_LINE (t); line = DECL_SOURCE_LINE (TYPE_NAME (t));
}
else
line = DECL_SOURCE_LINE (t);
if (line == 0)
return lineno;
return line;
} }
char * char *
......
...@@ -59,11 +59,6 @@ sorry_no_eh () ...@@ -59,11 +59,6 @@ sorry_no_eh ()
} }
void void
build_exception_table ()
{
}
void
expand_exception_blocks () expand_exception_blocks ()
{ {
} }
...@@ -180,29 +175,9 @@ output_exception_table_entry (file, start_label, end_label, eh_label) ...@@ -180,29 +175,9 @@ output_exception_table_entry (file, start_label, end_label, eh_label)
{ {
char label[100]; char label[100];
fprintf (file, "\t%s\t ", ASM_LONG); assemble_integer (start_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
if (GET_CODE (start_label) == CODE_LABEL) assemble_integer (end_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
{ assemble_integer (eh_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (start_label));
assemble_name (file, label);
}
else if (GET_CODE (start_label) == SYMBOL_REF)
{
fprintf (stderr, "YYYYYYYYYEEEEEEEESSSSSSSSSSSS!!!!!!!!!!\n");
assemble_name (file, XSTR (start_label, 0));
}
putc ('\n', file);
fprintf (file, "\t%s\t ", ASM_LONG);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (end_label));
assemble_name (file, label);
putc ('\n', file);
fprintf (file, "\t%s\t ", ASM_LONG);
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (eh_label));
assemble_name (file, label);
putc ('\n', file);
putc ('\n', file); /* blank line */ putc ('\n', file); /* blank line */
} }
...@@ -1436,39 +1411,62 @@ expand_throw (exp) ...@@ -1436,39 +1411,62 @@ expand_throw (exp)
emit_jump (throw_label); emit_jump (throw_label);
} }
/* end of: my-cp-except.c */
#endif
/* output the exception table */
void /* Output the exception table.
Return the number of handlers. */
int
build_exception_table () build_exception_table ()
{ {
int count = 0;
#ifdef TRY_NEW_EH
extern FILE *asm_out_file; extern FILE *asm_out_file;
struct ehEntry *entry; struct ehEntry *entry;
tree eh_node_decl;
if (! doing_eh (0)) if (! doing_eh (0))
return; return 0;
while (entry = dequeue_eh_entry (&eh_table_output_queue))
{
if (count == 0)
{
exception_section (); exception_section ();
/* Beginning marker for table. */ /* Beginning marker for table. */
fprintf (asm_out_file, " .global ___EXCEPTION_TABLE__\n"); ASM_OUTPUT_ALIGN (asm_out_file, 2);
fprintf (asm_out_file, " .align 4\n"); ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
fprintf (asm_out_file, "___EXCEPTION_TABLE__:\n");
fprintf (asm_out_file, " .word 0, 0, 0\n"); fprintf (asm_out_file, " .word 0, 0, 0\n");
}
while (entry = dequeue_eh_entry (&eh_table_output_queue)) { count++;
output_exception_table_entry (asm_out_file, output_exception_table_entry (asm_out_file,
entry->start_label, entry->end_label, entry->exception_handler_label); entry->start_label, entry->end_label,
entry->exception_handler_label);
} }
if (count)
{
/* Ending marker for table. */ /* Ending marker for table. */
fprintf (asm_out_file, " .global ___EXCEPTION_END__\n"); ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
fprintf (asm_out_file, "___EXCEPTION_END__:\n");
fprintf (asm_out_file, " .word -1, -1, -1\n"); fprintf (asm_out_file, " .word -1, -1, -1\n");
} }
/* end of: my-cp-except.c */ #endif /* TRY_NEW_EH */
#endif return count;
}
void
register_exception_table ()
{
#ifdef TRY_NEW_EH
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
VOIDmode, 1,
gen_rtx (SYMBOL_REF, PTRmode, "__EXCEPTION_TABLE__"),
Pmode);
#endif /* TRY_NEW_EH */
}
/* Build a throw expression. */ /* Build a throw expression. */
tree tree
......
...@@ -227,6 +227,7 @@ static tree ...@@ -227,6 +227,7 @@ static tree
sort_member_init (t) sort_member_init (t)
tree t; tree t;
{ {
extern int warn_reorder;
tree x, member, name, field, init; tree x, member, name, field, init;
tree init_list = NULL_TREE; tree init_list = NULL_TREE;
tree fields_to_unmark = NULL_TREE; tree fields_to_unmark = NULL_TREE;
...@@ -270,7 +271,7 @@ sort_member_init (t) ...@@ -270,7 +271,7 @@ sort_member_init (t)
} }
else else
{ {
if (pos < last_pos && extra_warnings) if (pos < last_pos && warn_reorder)
{ {
cp_warning_at ("member initializers for `%#D'", last_field); cp_warning_at ("member initializers for `%#D'", last_field);
cp_warning_at (" and `%#D'", field); cp_warning_at (" and `%#D'", field);
...@@ -1130,7 +1131,11 @@ expand_aggr_init (exp, init, alias_this) ...@@ -1130,7 +1131,11 @@ expand_aggr_init (exp, init, alias_this)
int was_const_elts = TYPE_READONLY (TREE_TYPE (type)); int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
tree itype = init ? TREE_TYPE (init) : NULL_TREE; tree itype = init ? TREE_TYPE (init) : NULL_TREE;
if (was_const_elts) if (was_const_elts)
{
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (init)
TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
}
if (init && TREE_TYPE (init) == NULL_TREE) if (init && TREE_TYPE (init) == NULL_TREE)
{ {
/* Handle bad initializers like: /* Handle bad initializers like:
...@@ -1152,7 +1157,8 @@ expand_aggr_init (exp, init, alias_this) ...@@ -1152,7 +1157,8 @@ expand_aggr_init (exp, init, alias_this)
init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1)); init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
TREE_TYPE (exp) = type; TREE_TYPE (exp) = type;
if (init) TREE_TYPE (init) = itype; if (init)
TREE_TYPE (init) = itype;
return; return;
} }
...@@ -1200,6 +1206,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1200,6 +1206,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)) else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))
{ {
rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0); rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
TREE_USED (rval) = 1;
expand_expr_stmt (rval); expand_expr_stmt (rval);
return; return;
} }
......
...@@ -75,6 +75,12 @@ void yyerror (); ...@@ -75,6 +75,12 @@ void yyerror ();
struct obstack inline_text_obstack; struct obstack inline_text_obstack;
static char *inline_text_firstobj; static char *inline_text_firstobj;
/* This obstack is used to hold information about methods to be
synthesized. It should go away when synthesized methods are handled
properly (i.e. only when needed). */
struct obstack synth_obstack;
static char *synth_firstobj;
int end_of_file; int end_of_file;
/* Pending language change. /* Pending language change.
...@@ -564,6 +570,8 @@ init_lex () ...@@ -564,6 +570,8 @@ init_lex ()
init_error (); init_error ();
gcc_obstack_init (&inline_text_obstack); gcc_obstack_init (&inline_text_obstack);
inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0); inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
gcc_obstack_init (&synth_obstack);
synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0);
/* Start it at 0, because check_newline is called at the very beginning /* Start it at 0, because check_newline is called at the very beginning
and will increment it to 1. */ and will increment it to 1. */
...@@ -1086,30 +1094,60 @@ set_vardecl_interface_info (prev, vars) ...@@ -1086,30 +1094,60 @@ set_vardecl_interface_info (prev, vars)
void void
do_pending_inlines () do_pending_inlines ()
{ {
struct pending_inline *prev = 0, *tail;
struct pending_inline *t; struct pending_inline *t;
/* Oops, we're still dealing with the last batch. */ /* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL) if (yychar == PRE_PARSED_FUNCTION_DECL)
return; return;
/* Note that we've seen these inlines and are dealing with them. */
for (t = pending_inlines; t; t = t->next)
t->deja_vu = 1;
/* Reverse the pending inline functions, since /* Reverse the pending inline functions, since
they were cons'd instead of appended. */ they were cons'd instead of appended. */
{
struct pending_inline *prev = 0, *tail;
t = pending_inlines;
pending_inlines = 0;
for (t = pending_inlines; t; t = tail) for (; t; t = tail)
{ {
t->deja_vu = 1;
tail = t->next; tail = t->next;
/* This kludge should go away when synthesized methods are handled
properly, i.e. only when needed. */
if (t->lineno <= 0)
{
tree f = t->fndecl;
DECL_PENDING_INLINE_INFO (f) = 0;
switch (- t->lineno)
{
case 0: case 1:
build_dtor (f); break;
case 2:
build_default_constructor (f); break;
case 3: case 4:
build_copy_constructor (f); break;
case 5: case 6:
build_assign_ref (f); break;
default:
;
}
obstack_free (&synth_obstack, t);
continue;
}
t->next = prev; t->next = prev;
prev = t; prev = t;
} }
/* Reset to zero so that if the inline functions we are currently t = prev;
processing define inline functions of their own, that is handled }
correctly. ??? This hasn't been checked in a while. */
pending_inlines = 0; if (t == 0)
return;
/* Now start processing the first inline function. */ /* Now start processing the first inline function. */
t = prev;
my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE), my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
226); 226);
if (t->parm_vec) if (t->parm_vec)
...@@ -1651,8 +1689,8 @@ reinit_parse_for_block (yychar, obstackp, is_template) ...@@ -1651,8 +1689,8 @@ reinit_parse_for_block (yychar, obstackp, is_template)
When KIND == 6, build default operator = (X&). */ When KIND == 6, build default operator = (X&). */
tree tree
cons_up_default_function (type, name, fields, kind) cons_up_default_function (type, name, kind)
tree type, name, fields; tree type, name;
int kind; int kind;
{ {
extern tree void_list_node; extern tree void_list_node;
...@@ -1676,14 +1714,6 @@ cons_up_default_function (type, name, fields, kind) ...@@ -1676,14 +1714,6 @@ cons_up_default_function (type, name, fields, kind)
case 2: case 2:
/* Default constructor. */ /* Default constructor. */
args = void_list_node; args = void_list_node;
{
if (declspecs)
declspecs = decl_tree_cons (NULL_TREE,
ridpointers [(int) RID_INLINE],
declspecs);
else
declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_INLINE]);
}
break; break;
case 3: case 3:
...@@ -1691,16 +1721,12 @@ cons_up_default_function (type, name, fields, kind) ...@@ -1691,16 +1721,12 @@ cons_up_default_function (type, name, fields, kind)
/* Fall through... */ /* Fall through... */
case 4: case 4:
/* According to ARM $12.8, the default copy ctor will be declared, but /* According to ARM $12.8, the default copy ctor will be declared, but
not defined, unless it's needed. So we mark this as `inline'; that not defined, unless it's needed. */
way, if it's never used it won't be emitted. */
declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_INLINE]);
argtype = build_reference_type (type); argtype = build_reference_type (type);
args = tree_cons (NULL_TREE, args = tree_cons (NULL_TREE,
build_tree_list (hash_tree_chain (argtype, NULL_TREE), build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")), get_identifier ("_ctor_arg")),
void_list_node); void_list_node);
default_copy_constructor_body (&func_buf, &func_len, type, fields);
break; break;
case 5: case 5:
...@@ -1708,11 +1734,7 @@ cons_up_default_function (type, name, fields, kind) ...@@ -1708,11 +1734,7 @@ cons_up_default_function (type, name, fields, kind)
/* Fall through... */ /* Fall through... */
case 6: case 6:
retref = 1; retref = 1;
declspecs = declspecs = build_decl_list (NULL_TREE, name);
decl_tree_cons (NULL_TREE, name,
decl_tree_cons (NULL_TREE,
ridpointers [(int) RID_INLINE],
NULL_TREE));
name = ansi_opname [(int) MODIFY_EXPR]; name = ansi_opname [(int) MODIFY_EXPR];
...@@ -1721,19 +1743,14 @@ cons_up_default_function (type, name, fields, kind) ...@@ -1721,19 +1743,14 @@ cons_up_default_function (type, name, fields, kind)
build_tree_list (hash_tree_chain (argtype, NULL_TREE), build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")), get_identifier ("_ctor_arg")),
void_list_node); void_list_node);
default_assign_ref_body (&func_buf, &func_len, type, fields);
break; break;
default: default:
my_friendly_abort (59); my_friendly_abort (59);
} }
if (!func_buf) declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE],
{ declspecs);
func_len = 2;
func_buf = obstack_alloc (&inline_text_obstack, func_len);
strcpy (func_buf, "{}");
}
TREE_PARMLIST (args) = 1; TREE_PARMLIST (args) = 1;
...@@ -1742,45 +1759,23 @@ cons_up_default_function (type, name, fields, kind) ...@@ -1742,45 +1759,23 @@ cons_up_default_function (type, name, fields, kind)
if (retref) if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator); declarator = build_parse_node (ADDR_EXPR, declarator);
fn = start_method (declspecs, declarator, NULL_TREE); fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
} }
if (fn == void_type_node) if (fn == void_type_node)
return fn; return fn;
current_base_init_list = NULL_TREE; /* This kludge should go away when synthesized methods are handled
current_member_init_list = NULL_TREE; properly, i.e. only when needed. */
{ {
struct pending_inline *t; struct pending_inline *t;
t = (struct pending_inline *)
t = (struct pending_inline *) obstack_alloc (&inline_text_obstack, obstack_alloc (&synth_obstack, sizeof (struct pending_inline));
sizeof (struct pending_inline)); t->lineno = -kind;
t->lineno = lineno; t->can_free = 0;
#if 1
t->filename = input_filename;
#else /* This breaks; why? */
#define MGMSG "(synthetic code at) "
t->filename = obstack_alloc (&inline_text_obstack,
strlen (input_filename) + sizeof (MGMSG) + 1);
strcpy (t->filename, MGMSG);
strcat (t->filename, input_filename);
#endif
t->token = YYEMPTY;
t->token_value = 0;
t->buf = func_buf;
t->len = func_len;
t->can_free = 1;
t->deja_vu = 0;
if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (fn))
warn_if_unknown_interface ();
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
store_pending_inline (fn, t); store_pending_inline (fn, t);
} }
finish_method (fn);
#ifdef DEBUG_DEFAULT_FUNCTIONS #ifdef DEBUG_DEFAULT_FUNCTIONS
{ char *fn_type = NULL; { char *fn_type = NULL;
tree t = name; tree t = name;
...@@ -1802,14 +1797,13 @@ cons_up_default_function (type, name, fields, kind) ...@@ -1802,14 +1797,13 @@ cons_up_default_function (type, name, fields, kind)
} }
#endif /* DEBUG_DEFAULT_FUNCTIONS */ #endif /* DEBUG_DEFAULT_FUNCTIONS */
DECL_CLASS_CONTEXT (fn) = TYPE_MAIN_VARIANT (type);
/* Show that this function was generated by the compiler. */ /* Show that this function was generated by the compiler. */
SET_DECL_ARTIFICIAL (fn); SET_DECL_ARTIFICIAL (fn);
return fn; return fn;
} }
#if 0
/* Used by default_copy_constructor_body. For the anonymous union /* Used by default_copy_constructor_body. For the anonymous union
in TYPE, return the member that is at least as large as the rest in TYPE, return the member that is at least as large as the rest
of the members, so we can copy it. */ of the members, so we can copy it. */
...@@ -2155,6 +2149,7 @@ default_copy_constructor_body (bufp, lenp, type, fields) ...@@ -2155,6 +2149,7 @@ default_copy_constructor_body (bufp, lenp, type, fields)
strcpy (*bufp, prologue.object_base); strcpy (*bufp, prologue.object_base);
strcat (*bufp, "{}"); strcat (*bufp, "{}");
} }
#endif
/* Heuristic to tell whether the user is missing a semicolon /* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message after a struct or enum declaration. Emit an error message
......
...@@ -313,6 +313,7 @@ flush_repeats (type) ...@@ -313,6 +313,7 @@ flush_repeats (type)
OB_PUTC ('_'); OB_PUTC ('_');
} }
static int numeric_outputed_need_bar = 0;
static void build_overload_identifier (); static void build_overload_identifier ();
static void static void
...@@ -476,11 +477,17 @@ build_overload_identifier (name) ...@@ -476,11 +477,17 @@ build_overload_identifier (name)
/* It's a PARM_DECL. */ /* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0); build_overload_name (TREE_TYPE (parm), 0, 0);
build_overload_value (parm, arg); build_overload_value (parm, arg);
numeric_outputed_need_bar = 1;
} }
} }
} }
else else
{ {
if (numeric_outputed_need_bar)
{
OB_PUTC ('_');
numeric_outputed_need_bar = 0;
}
icat (IDENTIFIER_LENGTH (name)); icat (IDENTIFIER_LENGTH (name));
OB_PUTID (name); OB_PUTID (name);
} }
...@@ -772,6 +779,7 @@ build_overload_name (parmtypes, begin, end) ...@@ -772,6 +779,7 @@ build_overload_name (parmtypes, begin, end)
icat (i); icat (i);
if (i > 9) if (i > 9)
OB_PUTC ('_'); OB_PUTC ('_');
numeric_outputed_need_bar = 0;
build_overload_nested_name (TYPE_NAME (parmtype)); build_overload_nested_name (TYPE_NAME (parmtype));
} }
else else
...@@ -818,6 +826,18 @@ build_overload_name (parmtypes, begin, end) ...@@ -818,6 +826,18 @@ build_overload_name (parmtypes, begin, end)
return (char *)obstack_base (&scratch_obstack); return (char *)obstack_base (&scratch_obstack);
} }
tree
build_static_name (basetype, name)
tree basetype, name;
{
char *basename = build_overload_name (basetype, 1, 1);
char *buf = (char *) alloca (IDENTIFIER_LENGTH (name)
+ sizeof (STATIC_NAME_FORMAT)
+ strlen (basename));
sprintf (buf, STATIC_NAME_FORMAT, basename, IDENTIFIER_POINTER (name));
return get_identifier (buf);
}
/* Generate an identifier that encodes the (ANSI) exception TYPE. */ /* Generate an identifier that encodes the (ANSI) exception TYPE. */
/* This should be part of `ansi_opname', or at least be defined by the std. */ /* This should be part of `ansi_opname', or at least be defined by the std. */
...@@ -1945,3 +1965,173 @@ emit_thunk (thunk_fndecl) ...@@ -1945,3 +1965,173 @@ emit_thunk (thunk_fndecl)
decl_printable_name = save_decl_printable_name; decl_printable_name = save_decl_printable_name;
current_function_decl = 0; current_function_decl = 0;
} }
/* Code for synthesizing methods which have default semantics defined. */
void
build_default_constructor (fndecl)
tree fndecl;
{
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
setup_vtbl_ptr ();
finish_function (lineno, 0);
}
/* Generate code for default X(X&) constructor. */
void
build_copy_constructor (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree t;
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
clear_last_expr ();
push_momentary ();
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm);
if (! TYPE_HAS_COMPLEX_INIT_REF (current_class_type))
{
t = build (INIT_EXPR, void_type_node, C_C_D, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
}
else
{
tree fields = TYPE_FIELDS (current_class_type);
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
int i;
for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
t = TREE_CHAIN (t))
{
tree basetype = BINFO_TYPE (t);
tree p = convert (build_reference_type (basetype), parm);
p = convert_from_reference (p);
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
p, current_base_init_list);
}
for (i = 0; i < n_bases; ++i)
{
tree p, basetype = TREE_VEC_ELT (binfos, i);
if (TREE_VIA_VIRTUAL (basetype))
continue;
basetype = BINFO_TYPE (basetype);
p = convert (build_reference_type (basetype), parm);
p = convert_from_reference (p);
current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype),
p, current_base_init_list);
}
for (; fields; fields = TREE_CHAIN (fields))
{
tree name, init;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
{
if (VFIELD_NAME_P (DECL_NAME (fields)))
continue;
if (VBASE_NAME_P (DECL_NAME (fields)))
continue;
/* True for duplicate members. */
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
init = build_tree_list (NULL_TREE, init);
current_member_init_list
= tree_cons (DECL_NAME (fields), init, current_member_init_list);
}
current_member_init_list = nreverse (current_member_init_list);
setup_vtbl_ptr ();
}
pop_momentary ();
finish_function (lineno, 0);
}
void
build_assign_ref (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
push_momentary ();
parm = convert_from_reference (parm);
if (! TYPE_HAS_COMPLEX_ASSIGN_REF (current_class_type))
{
tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
}
else
{
tree fields = TYPE_FIELDS (current_class_type);
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
int i;
for (i = 0; i < n_bases; ++i)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
if (TYPE_HAS_ASSIGN_REF (basetype))
{
tree p = convert (build_reference_type (basetype), parm);
p = convert_from_reference (p);
p = build_member_call (TYPE_NESTED_NAME (basetype),
ansi_opname [MODIFY_EXPR],
build_tree_list (NULL_TREE, p));
expand_expr_stmt (p);
}
}
for (; fields; fields = TREE_CHAIN (fields))
{
tree comp, init;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
{
if (VFIELD_NAME_P (DECL_NAME (fields)))
continue;
if (VBASE_NAME_P (DECL_NAME (fields)))
continue;
/* True for duplicate members. */
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
comp = build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields);
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
}
}
c_expand_return (C_C_D);
pop_momentary ();
finish_function (lineno, 0);
}
void
build_dtor (fndecl)
tree fndecl;
{
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
finish_function (lineno, 0);
}
...@@ -3436,6 +3436,8 @@ label_colon: ...@@ -3436,6 +3436,8 @@ label_colon:
} }
| PTYPENAME ':' | PTYPENAME ':'
{ goto do_label; } { goto do_label; }
| TYPENAME ':'
{ goto do_label; }
; ;
forhead.1: forhead.1:
......
...@@ -333,7 +333,7 @@ grok_template_type (tvec, type) ...@@ -333,7 +333,7 @@ grok_template_type (tvec, type)
{ {
/* we are here for cases like const T* etc. */ /* we are here for cases like const T* etc. */
grok_template_type (tvec, &TYPE_MAIN_VARIANT (*type)); grok_template_type (tvec, &TYPE_MAIN_VARIANT (*type));
*type = c_build_type_variant (TYPE_MAIN_VARIANT (*type), *type = cp_build_type_variant (TYPE_MAIN_VARIANT (*type),
TYPE_READONLY (*type), TYPE_READONLY (*type),
TYPE_VOLATILE (*type)); TYPE_VOLATILE (*type));
} }
...@@ -430,7 +430,8 @@ coerce_template_parms (parms, arglist, in_decl) ...@@ -430,7 +430,8 @@ coerce_template_parms (parms, arglist, in_decl)
if (is_type != requires_type) if (is_type != requires_type)
{ {
if (in_decl) if (in_decl)
cp_error_at ("type/value mismatch in template parameter list for `%D'", in_decl); cp_error ("type/value mismatch in template parameter list for `%D'",
in_decl);
lost++; lost++;
TREE_VEC_ELT (vec, i) = error_mark_node; TREE_VEC_ELT (vec, i) = error_mark_node;
continue; continue;
...@@ -897,6 +898,8 @@ instantiate_member_templates (classname) ...@@ -897,6 +898,8 @@ instantiate_member_templates (classname)
&TREE_VEC_ELT (parmvec, 0)); &TREE_VEC_ELT (parmvec, 0));
type = IDENTIFIER_TYPE_VALUE (id); type = IDENTIFIER_TYPE_VALUE (id);
my_friendly_assert (type != 0, 277); my_friendly_assert (type != 0, 277);
if (flag_external_templates)
{
if (CLASSTYPE_INTERFACE_UNKNOWN (type)) if (CLASSTYPE_INTERFACE_UNKNOWN (type))
{ {
DECL_EXTERNAL (t2) = 0; DECL_EXTERNAL (t2) = 0;
...@@ -907,6 +910,7 @@ instantiate_member_templates (classname) ...@@ -907,6 +910,7 @@ instantiate_member_templates (classname)
DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type); DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type);
TREE_PUBLIC (t2) = 1; TREE_PUBLIC (t2) = 1;
} }
}
break; break;
case 1: case 1:
/* Failure. */ /* Failure. */
...@@ -1157,7 +1161,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1157,7 +1161,7 @@ tsubst (t, args, nargs, in_decl)
&& type != integer_type_node && type != integer_type_node
&& type != void_type_node && type != void_type_node
&& type != char_type_node) && type != char_type_node)
type = c_build_type_variant (tsubst (type, args, nargs, in_decl), type = cp_build_type_variant (tsubst (type, args, nargs, in_decl),
TYPE_READONLY (type), TYPE_READONLY (type),
TYPE_VOLATILE (type)); TYPE_VOLATILE (type));
switch (TREE_CODE (t)) switch (TREE_CODE (t))
...@@ -1194,7 +1198,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1194,7 +1198,7 @@ tsubst (t, args, nargs, in_decl)
tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl)); tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
return c_build_type_variant (args[TEMPLATE_TYPE_IDX (t)], return cp_build_type_variant (args[TEMPLATE_TYPE_IDX (t)],
TYPE_READONLY (t), TYPE_READONLY (t),
TYPE_VOLATILE (t)); TYPE_VOLATILE (t));
...@@ -1388,9 +1392,10 @@ tsubst (t, args, nargs, in_decl) ...@@ -1388,9 +1392,10 @@ tsubst (t, args, nargs, in_decl)
if (!got_it) if (!got_it)
{ {
r = build_decl_overload (r, TYPE_VALUES (type), tree a = build_decl_overload (r, TYPE_VALUES (type),
DECL_CONTEXT (t) != NULL_TREE); DECL_CONTEXT (t) != NULL_TREE);
r = build_lang_decl (FUNCTION_DECL, r, type); r = build_lang_decl (FUNCTION_DECL, r, type);
DECL_ASSEMBLER_NAME (r) = a;
} }
else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r)) else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r))
{ {
...@@ -1424,9 +1429,11 @@ tsubst (t, args, nargs, in_decl) ...@@ -1424,9 +1429,11 @@ tsubst (t, args, nargs, in_decl)
make_decl_rtl (r, NULL_PTR, 1); make_decl_rtl (r, NULL_PTR, 1);
DECL_ARGUMENTS (r) = fnargs; DECL_ARGUMENTS (r) = fnargs;
DECL_RESULT (r) = result; DECL_RESULT (r) = result;
#if 0
if (DECL_CONTEXT (t) == NULL_TREE if (DECL_CONTEXT (t) == NULL_TREE
|| TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't') || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')
push_overloaded_decl_top_level (r, 0); push_overloaded_decl_top_level (r, 0);
#endif
return r; return r;
} }
...@@ -1504,7 +1511,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1504,7 +1511,7 @@ tsubst (t, args, nargs, in_decl)
r = build_pointer_type (type); r = build_pointer_type (type);
else else
r = build_reference_type (type); r = build_reference_type (type);
r = c_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t)); r = cp_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t));
/* Will this ever be needed for TYPE_..._TO values? */ /* Will this ever be needed for TYPE_..._TO values? */
layout_type (r); layout_type (r);
return r; return r;
...@@ -2137,7 +2144,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2137,7 +2144,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
case REAL_TYPE: case REAL_TYPE:
case INTEGER_TYPE: case INTEGER_TYPE:
if (TREE_CODE (parm) == INTEGER_TYPE && TREE_CODE (arg) == INTEGER_TYPE) if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
if (TREE_CODE (parm) == INTEGER_TYPE)
{ {
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, ntparms, && unify (tparms, targs, ntparms,
...@@ -2464,6 +2474,8 @@ do_type_instantiation (name, storage) ...@@ -2464,6 +2474,8 @@ do_type_instantiation (name, storage)
return; return;
} }
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t); SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
if (! extern_p) if (! extern_p)
{ {
...@@ -2474,12 +2486,20 @@ do_type_instantiation (name, storage) ...@@ -2474,12 +2486,20 @@ do_type_instantiation (name, storage)
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0; TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
rest_of_type_compilation (t, 1); rest_of_type_compilation (t, 1);
} }
}
instantiate_member_templates (TYPE_IDENTIFIER (t));
/* this should really be done by instantiate_member_templates */ /* this should really be done by instantiate_member_templates */
{ {
tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; tmp; tmp = TREE_CHAIN (tmp)) for (; tmp; tmp = TREE_CHAIN (tmp))
{ {
if (DECL_TEMPLATE_SPECIALIZATION (tmp)
|| (DECL_USE_TEMPLATE (tmp) == 0
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (t)))
continue;
SET_DECL_EXPLICIT_INSTANTIATION (tmp); SET_DECL_EXPLICIT_INSTANTIATION (tmp);
if (! extern_p) if (! extern_p)
{ {
...@@ -2498,7 +2518,8 @@ do_type_instantiation (name, storage) ...@@ -2498,7 +2518,8 @@ do_type_instantiation (name, storage)
#endif #endif
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp)) for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
do_type_instantiation (TREE_VALUE (tmp), storage); if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
} }
} }
......
...@@ -177,7 +177,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) ...@@ -177,7 +177,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
} }
else else
{ {
tree sig_tbl_type = c_build_type_variant (to_type, 1, 0); tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0);
sptr = build_lang_field_decl (FIELD_DECL, sptr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_SPTR_NAME), get_identifier (SIGNATURE_SPTR_NAME),
......
...@@ -230,12 +230,15 @@ break_out_calls (exp) ...@@ -230,12 +230,15 @@ break_out_calls (exp)
return exp; return exp;
case 'd': /* A decl node */ case 'd': /* A decl node */
#if 0 /* This is bogus. jason 9/21/94 */
t1 = break_out_calls (DECL_INITIAL (exp)); t1 = break_out_calls (DECL_INITIAL (exp));
if (t1 != DECL_INITIAL (exp)) if (t1 != DECL_INITIAL (exp))
{ {
exp = copy_node (exp); exp = copy_node (exp);
DECL_INITIAL (exp) = t1; DECL_INITIAL (exp) = t1;
} }
#endif
return exp; return exp;
case 'b': /* A block node */ case 'b': /* A block node */
...@@ -388,6 +391,40 @@ build_cplus_array_type (elt_type, index_type) ...@@ -388,6 +391,40 @@ build_cplus_array_type (elt_type, index_type)
return t; return t;
} }
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
tree
cp_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree real_main_variant = TYPE_MAIN_VARIANT (type);
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),
constp, volatilep),
TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
make a copy. (TYPE might have come from the hash table and
REAL_MAIN_VARIANT might be in some function's obstack.) */
if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant))
{
type = copy_node (type);
TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0;
}
TYPE_MAIN_VARIANT (type) = real_main_variant;
pop_obstacks ();
}
return build_type_variant (type, constp, volatilep);
}
/* Add OFFSET to all base types of T. /* Add OFFSET to all base types of T.
OFFSET, which is a type offset, is number of bytes. OFFSET, which is a type offset, is number of bytes.
......
...@@ -161,7 +161,7 @@ qualify_type (type, like) ...@@ -161,7 +161,7 @@ qualify_type (type, like)
int constflag = TYPE_READONLY (type) || TYPE_READONLY (like); int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like); int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
/* @@ Must do member pointers here. */ /* @@ Must do member pointers here. */
return c_build_type_variant (type, constflag, volflag); return cp_build_type_variant (type, constflag, volflag);
} }
/* Return the common type of two parameter lists. /* Return the common type of two parameter lists.
...@@ -372,7 +372,7 @@ common_type (t1, t2) ...@@ -372,7 +372,7 @@ common_type (t1, t2)
= TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2)); = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
int volatilep int volatilep
= TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2)); = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
target = c_build_type_variant (target, constp, volatilep); target = cp_build_type_variant (target, constp, volatilep);
if (code1 == POINTER_TYPE) if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target); t1 = build_pointer_type (target);
else else
...@@ -1378,7 +1378,7 @@ default_conversion (exp) ...@@ -1378,7 +1378,7 @@ default_conversion (exp)
restype = TREE_TYPE (type); restype = TREE_TYPE (type);
if (TYPE_READONLY (type) || TYPE_VOLATILE (type) if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
|| constp || volatilep) || constp || volatilep)
restype = c_build_type_variant (restype, restype = cp_build_type_variant (restype,
TYPE_READONLY (type) || constp, TYPE_READONLY (type) || constp,
TYPE_VOLATILE (type) || volatilep); TYPE_VOLATILE (type) || volatilep);
ptrtype = build_pointer_type (restype); ptrtype = build_pointer_type (restype);
...@@ -1533,8 +1533,7 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1533,8 +1533,7 @@ build_component_ref (datum, component, basetype_path, protect)
register tree field = NULL; register tree field = NULL;
register tree ref; register tree ref;
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */
unless we are not to support things not strictly ANSI. */
switch (TREE_CODE (datum)) switch (TREE_CODE (datum))
{ {
case COMPOUND_EXPR: case COMPOUND_EXPR:
...@@ -1706,7 +1705,8 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -1706,7 +1705,8 @@ build_component_ref (datum, component, basetype_path, protect)
datum = build_indirect_ref (addr, NULL_PTR); datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 311); my_friendly_assert (datum != error_mark_node, 311);
} }
ref = build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field); ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
break_out_cleanups (datum), field));
if (TREE_READONLY (datum) || TREE_READONLY (field)) if (TREE_READONLY (datum) || TREE_READONLY (field))
TREE_READONLY (ref) = 1; TREE_READONLY (ref) = 1;
...@@ -2619,7 +2619,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) ...@@ -2619,7 +2619,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* See if there are default arguments that can be used */ /* See if there are default arguments that can be used */
if (TREE_PURPOSE (typetail)) if (TREE_PURPOSE (typetail))
{ {
while (typetail != void_list_node) for (; typetail != void_list_node; ++i)
{ {
tree type = TREE_VALUE (typetail); tree type = TREE_VALUE (typetail);
tree val = TREE_PURPOSE (typetail); tree val = TREE_PURPOSE (typetail);
...@@ -4102,42 +4102,16 @@ build_unary_op (code, xarg, noconvert) ...@@ -4102,42 +4102,16 @@ build_unary_op (code, xarg, noconvert)
if (TREE_CODE (arg) == TREE_LIST) if (TREE_CODE (arg) == TREE_LIST)
{ {
/* Look at methods with only this name. */ if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL
if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL) && DECL_CHAIN (TREE_VALUE (arg)) == NULL_TREE)
{ /* Unique overloaded non-member function. */
tree targ = TREE_VALUE (arg); return build_unary_op (ADDR_EXPR, TREE_VALUE (arg), 0);
/* If this function is unique, or it is a unique
constructor, we can take its address easily. */
if (DECL_CHAIN (targ) == NULL_TREE
|| (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (targ))
&& DECL_CHAIN (DECL_CHAIN (targ)) == NULL_TREE))
{
if (DECL_CHAIN (targ))
targ = DECL_CHAIN (targ);
if (DECL_CLASS_CONTEXT (targ))
targ = build (OFFSET_REF, TREE_TYPE (targ), C_C_D, targ);
val = unary_complex_lvalue (ADDR_EXPR, targ);
if (val)
return val;
}
/* This possible setting of TREE_CONSTANT is what makes it possible
with an initializer list to emit the entire thing in the data
section, rather than a run-time initialization. */
arg = build1 (ADDR_EXPR, unknown_type_node, arg);
if (staticp (targ))
TREE_CONSTANT (arg) = 1;
return arg;
}
if (TREE_CHAIN (arg) == NULL_TREE if (TREE_CHAIN (arg) == NULL_TREE
&& TREE_CODE (TREE_VALUE (arg)) == TREE_LIST && TREE_CODE (TREE_VALUE (arg)) == TREE_LIST
&& DECL_CHAIN (TREE_VALUE (TREE_VALUE (arg))) == NULL_TREE) && DECL_CHAIN (TREE_VALUE (TREE_VALUE (arg))) == NULL_TREE)
{
/* Unique overloaded member function. */ /* Unique overloaded member function. */
return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)), 0); return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)),
} 0);
return build1 (ADDR_EXPR, unknown_type_node, arg); return build1 (ADDR_EXPR, unknown_type_node, arg);
} }
...@@ -4179,7 +4153,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4179,7 +4153,7 @@ build_unary_op (code, xarg, noconvert)
|| TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
{ {
if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)) if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
argtype = c_build_type_variant (argtype, argtype = cp_build_type_variant (argtype,
TREE_READONLY (arg), TREE_READONLY (arg),
TREE_THIS_VOLATILE (arg)); TREE_THIS_VOLATILE (arg));
} }
...@@ -4587,7 +4561,7 @@ build_conditional_expr (ifexp, op1, op2) ...@@ -4587,7 +4561,7 @@ build_conditional_expr (ifexp, op1, op2)
else if (TREE_READONLY_DECL_P (op2)) else if (TREE_READONLY_DECL_P (op2))
op2 = decl_constant_value (op2); op2 = decl_constant_value (op2);
if (type1 != type2) if (type1 != type2)
type1 = c_build_type_variant type1 = cp_build_type_variant
(type1, (type1,
TREE_READONLY (op1) || TREE_READONLY (op2), TREE_READONLY (op1) || TREE_READONLY (op2),
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
...@@ -4636,7 +4610,7 @@ build_conditional_expr (ifexp, op1, op2) ...@@ -4636,7 +4610,7 @@ build_conditional_expr (ifexp, op1, op2)
if (type1 == type2) if (type1 == type2)
result_type = type1; result_type = type1;
else else
result_type = c_build_type_variant result_type = cp_build_type_variant
(type1, (type1,
TREE_READONLY (op1) || TREE_READONLY (op2), TREE_READONLY (op1) || TREE_READONLY (op2),
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
...@@ -5025,6 +4999,9 @@ build_c_cast (type, expr) ...@@ -5025,6 +4999,9 @@ build_c_cast (type, expr)
warning ("cast to pointer from integer of different size"); warning ("cast to pointer from integer of different size");
#endif #endif
if (TREE_READONLY_DECL_P (value))
value = decl_constant_value (value);
ovalue = value; ovalue = value;
value = convert_force (type, value); value = convert_force (type, value);
...@@ -5349,13 +5326,13 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5349,13 +5326,13 @@ build_modify_expr (lhs, modifycode, rhs)
tree olhstype = lhstype; tree olhstype = lhstype;
tree olhs = lhs; tree olhs = lhs;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
/* Avoid duplicate error messages from operands that had errors. */ /* Avoid duplicate error messages from operands that had errors. */
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
return error_mark_node; return error_mark_node;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
/* Decide early if we are going to protect RHS from GC /* Decide early if we are going to protect RHS from GC
before assigning it to LHS. */ before assigning it to LHS. */
if (type_needs_gc_entry (TREE_TYPE (rhs)) if (type_needs_gc_entry (TREE_TYPE (rhs))
...@@ -5786,10 +5763,12 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5786,10 +5763,12 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_CODE (lhstype) == ARRAY_TYPE) if (TREE_CODE (lhstype) == ARRAY_TYPE)
{ {
int from_array;
/* Allow array assignment in compiler-generated code. */ /* Allow array assignment in compiler-generated code. */
if ((pedantic || flag_ansi) if ((pedantic || flag_ansi)
&& ! DECL_ARTIFICIAL (current_function_decl)) && ! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ANSI C++ forbids assignment between arrays"); pedwarn ("ANSI C++ forbids assignment of arrays");
/* Have to wrap this in RTL_EXPR for two cases: /* Have to wrap this in RTL_EXPR for two cases:
in base or member initialization and if we in base or member initialization and if we
...@@ -5805,8 +5784,10 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5805,8 +5784,10 @@ build_modify_expr (lhs, modifycode, rhs)
/* As a matter of principle, `start_sequence' should do this. */ /* As a matter of principle, `start_sequence' should do this. */
emit_note (0, -1); emit_note (0, -1);
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs, expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs,
1 + (modifycode != INIT_EXPR)); from_array);
do_pending_stack_adjust (); do_pending_stack_adjust ();
...@@ -6124,11 +6105,14 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6124,11 +6105,14 @@ build_ptrmemfunc (type, pfn, force)
return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
} }
if (TREE_CODE (pfn) == TREE_LIST) if (TREE_CODE (pfn) == TREE_LIST
|| (TREE_CODE (pfn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
{ {
pfn = instantiate_type (type, pfn, 1); pfn = instantiate_type (type, pfn, 1);
if (pfn == error_mark_node) if (pfn == error_mark_node)
return error_mark_node; return error_mark_node;
if (TREE_CODE (pfn) != ADDR_EXPR)
pfn = build_unary_op (ADDR_EXPR, pfn, 0); pfn = build_unary_op (ADDR_EXPR, pfn, 0);
} }
...@@ -6585,10 +6569,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) ...@@ -6585,10 +6569,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
} }
return null_pointer_node; return null_pointer_node;
} }
else if (codel == INTEGER_TYPE else if ((codel == INTEGER_TYPE || codel == BOOLEAN_TYPE)
&& (coder == POINTER_TYPE && (coder == POINTER_TYPE
|| (coder == RECORD_TYPE || (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype) && (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype))))) || IS_SIGNATURE_REFERENCE (rhstype)))))
{ {
if (fndecl) if (fndecl)
...@@ -6741,7 +6726,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -6741,7 +6726,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))) && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
return build_signature_pointer_constructor (type, rhs); return build_signature_pointer_constructor (type, rhs);
if (IS_AGGR_TYPE (type) && TYPE_NEEDS_CONSTRUCTING (type)) if (IS_AGGR_TYPE (type)
&& (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
{ {
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{ {
...@@ -6997,8 +6983,11 @@ c_expand_return (retval) ...@@ -6997,8 +6983,11 @@ c_expand_return (retval)
while (TREE_CODE (whats_returned) == NEW_EXPR while (TREE_CODE (whats_returned) == NEW_EXPR
|| TREE_CODE (whats_returned) == TARGET_EXPR || TREE_CODE (whats_returned) == TARGET_EXPR
|| TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR) || TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR)
{
/* Get the target. */ /* Get the target. */
whats_returned = TREE_OPERAND (whats_returned, 0); whats_returned = TREE_OPERAND (whats_returned, 0);
warning ("returning reference to temporary");
}
} }
if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned)) if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
......
...@@ -599,6 +599,7 @@ store_init_value (decl, init) ...@@ -599,6 +599,7 @@ store_init_value (decl, init)
)) ))
return value; return value;
#if 0 /* No, that's C. jason 9/19/94 */
else else
{ {
if (pedantic && TREE_CODE (value) == CONSTRUCTOR if (pedantic && TREE_CODE (value) == CONSTRUCTOR
...@@ -613,6 +614,7 @@ store_init_value (decl, init) ...@@ -613,6 +614,7 @@ store_init_value (decl, init)
pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions"); pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions");
} }
} }
#endif
DECL_INITIAL (decl) = value; DECL_INITIAL (decl) = value;
return NULL_TREE; return NULL_TREE;
} }
...@@ -659,8 +661,9 @@ digest_init (type, init, tail) ...@@ -659,8 +661,9 @@ digest_init (type, init, tail)
if (init && TYPE_PTRMEMFUNC_P (type) if (init && TYPE_PTRMEMFUNC_P (type)
&& ((TREE_CODE (init) == ADDR_EXPR && ((TREE_CODE (init) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE && ((TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE) && TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
|| TREE_CODE (TREE_OPERAND (init, 0)) == TREE_LIST))
|| TREE_CODE (init) == TREE_LIST || TREE_CODE (init) == TREE_LIST
|| integer_zerop (init) || integer_zerop (init)
|| (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init))))) || (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
......
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