diff options
-rw-r--r-- | gcc/cp/ChangeLog | 127 | ||||
-rw-r--r-- | gcc/cp/call.c | 8 | ||||
-rw-r--r-- | gcc/cp/class.c | 48 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 519 | ||||
-rw-r--r-- | gcc/cp/decl.c | 153 | ||||
-rw-r--r-- | gcc/cp/error.c | 3 | ||||
-rw-r--r-- | gcc/cp/except.c | 2 | ||||
-rw-r--r-- | gcc/cp/gxxint.texi | 6 | ||||
-rw-r--r-- | gcc/cp/init.c | 5 | ||||
-rw-r--r-- | gcc/cp/lex.c | 101 | ||||
-rw-r--r-- | gcc/cp/method.c | 57 | ||||
-rw-r--r-- | gcc/cp/pt.c | 5 | ||||
-rw-r--r-- | gcc/cp/search.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 39 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 11 |
16 files changed, 768 insertions, 319 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f0dd601c72a..1f6eeb971e2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -3,6 +3,131 @@ Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com> * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef. (finish_file): Likewise. +Wed May 29 17:04:33 1996 Mike Stump <mrs@cygnus.com> + + * cvt.c (build_up_reference): Redo how and when temporaries are + created. + * decl.c (grok_reference_init): Don't try and be smart about + running cleanups. + +Wed May 29 16:02:08 1996 Mike Stump <mrs@cygnus.com> + + * cvt.c (build_up_reference): Add NULL_TREE to all calls to build + (TARGET_EXPR...), now that it has 4 arguments. + * tree.c (build_cplus_new): Ditto. + +Thu May 23 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com> + + * error.c (dump_expr, case CAST_EXPR): Handle T() properly. + + * pt.c (instantiate_decl): Don't call push/pop_cp_function_context. + * decl.c (struct saved_scope): Remove named_labels, + {base,member}_init_list. + (maybe_push_to_top_level): Don't set them. Call + push_cp_function_context if appropriate. + (pop_from_top_level): Likewise. + + * method.c (do_build_assign_ref): Remove obsolete check of + TYPE_HAS_ASSIGN_REF (basetype). + + * decl.c (grokfndecl): Diagnose user definition of + implicitly-declared methods. + +Thu May 23 12:13:08 1996 Bob Manson <manson@charmed.cygnus.com> + + * method.c (do_build_copy_constructor): Add code to give + meaningful error messages instead of crashing. + (do_build_assign_ref): Don't synthesize assignment operators for + classes containing reference or const members. + + * class.c (struct base_info): Remove cant_synth_copy_ctor + and cant_synth_asn_ref. + (finish_base_struct): Remove the code that tries to conditionalize + synthesis of copy constructors & assignment operators based on + access permissions. Instead, let it fail when it tries to + synthesize the copy constructor. This will give meaningful error + messages instead of silently generating code to perform a bitcopy. + +Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com> + + * lex.c (real_yylex): Remove old-n-crufty #if 0 code for + determining types for constant values. + + * decl.c (struct named_label_list): Use instead of stuffing + random items into a TREE_LIST node. + (named_label_uses): Use the new struct. + (poplevel): Ditto. + (lookup_label): Ditto. + (define_label): Add an error message to tell the user the line + where the goto is located in addition to the destination of the + goto. + (init_decl_processing): Use NULL instead of NULL_TREE to initialize + named_label_uses. + (finish_function): Ditto. + + (start_decl): Complain about defining a static data member + in a different type from which it was declared. + +Wed May 22 09:33:23 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (build_expr_type_conversion): Adjust. + +Tue May 21 11:21:56 1996 Jason Merrill <jason@yorick.cygnus.com> + + * call.c (build_method_call): Always convert 'this' to the + appropriate type. + + * search.c (add_conversions): Put the conversion function in + TREE_VALUE, the type in TREE_PURPOSE. + * cvt.c (build_type_conversion): Adjust. + * call.c (user_harshness): Adjust. + + * method.c (emit_thunk): Call temporary_allocation and + permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too. + + * tree.c (build_cplus_array_type): Handle tweaking of + TYPE_MAIN_VARIANT here. + * typeck.c (common_type): Not here. + + * typeck.c (complete_type): Only try to complete an array type if + it has a domain. + +Mon May 20 14:55:59 1996 Jason Merrill <jason@yorick.cygnus.com> + + * decl.c (grokvardecl): Call complete_type. + (grokdeclarator): Call complete_type for PARM_DECLs. + +Fri May 17 16:41:17 1996 Jason Merrill <jason@yorick.cygnus.com> + + * pt.c (instantiate_class_template): Re-set + CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1. + +Fri May 17 14:56:55 1996 Mike Stump <mrs@cygnus.com> + + * cp-tree.h (cp_expand_decl_cleanup): Remove, the backend is now + smart enough to do it right. + * tree.c (cp_expand_decl_cleanup): Ditto. + * decl.c (cp_finish_decl): Use expand_decl_cleanup instead of + cp_expand_decl_cleanup. + (store_parm_decls): Ditto. + (hack_incomplete_structures): Ditto. + * except.c (push_eh_cleanup): Ditto. + +Fri May 17 13:13:51 1996 Mike Stump <mrs@cygnus.com> + + * expr.c (expand_expr, cond UNSAVE_EXPR): Move from the C++ + frontend to the backend where it belongs. + * tree.c (unsave_expr): Ditto. + (unsave_expr_now): Ditto. + * tree.def (UNSAVE_EXPR): Ditto. + * cp-tree.h (unsave_expr): Ditto. + (unsave_expr_now): Ditto. + +Fri May 17 11:02:41 1996 Mike Stump <mrs@cygnus.com> + + * init.c (emit_base_init): Make sure the partial EH cleanups live + on the function_obstack. + Thu May 16 15:29:33 1996 Bob Manson <manson@charmed.cygnus.com> * expr.c (do_case): Don't try to dereference null TREE_TYPEs @@ -2369,7 +2494,7 @@ Mon Nov 13 15:45:34 1995 Mike Stump <mrs@cygnus.com> indirect binding. * decl.c (cp_finish_decl): Ensure that we reuse stack slots as fast as they are unused. - (expand_static_init): Diotto. + (expand_static_init): Ditto. (cplus_expand_expr_stmt): Ditto. * decl2.c (finish_file): Ditto. * init.c (perform_member_init): Ditto. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 6e2132de058..3accebcbe60 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -641,10 +641,10 @@ user_harshness (type, parmtype) { struct harshness_code tmp; - if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + if (winner && TREE_VALUE (winner) == TREE_VALUE (conv)) continue; - if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE), + if (tmp = convert_harshness (type, TREE_PURPOSE (conv), NULL_TREE), (tmp.code < USER_CODE) && (tmp.distance >= 0)) { if (winner) @@ -2531,8 +2531,8 @@ build_method_call (instance, name, parms, basetype_path, flags) { int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL; basetype = TREE_TYPE (instance); - if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype) - && TYPE_USES_COMPLEX_INHERITANCE (basetype)) + if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) + != TYPE_MAIN_VARIANT (basetype)) { basetype = DECL_CLASS_CONTEXT (function); instance_ptr = convert_pointer_to (basetype, instance_ptr); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4c6cf3ecd71..9227baf13aa 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1408,8 +1408,6 @@ struct base_info tree rtti; char cant_have_default_ctor; char cant_have_const_ctor; - char cant_synth_copy_ctor; - char cant_synth_asn_ref; char no_const_asn_ref; char base_has_virtual; }; @@ -1465,13 +1463,8 @@ finish_base_struct (t, b, t_binfo) TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); } - if (TYPE_HAS_INIT_REF (basetype) - && !TYPE_HAS_CONST_INIT_REF (basetype)) + if (! TYPE_HAS_CONST_INIT_REF (basetype)) b->cant_have_const_ctor = 1; - if (! TYPE_HAS_INIT_REF (basetype) - || (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2 - && ! is_friend_type (t, basetype))) - b->cant_synth_copy_ctor = 1; if (TYPE_HAS_CONSTRUCTOR (basetype) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) @@ -1488,11 +1481,6 @@ finish_base_struct (t, b, t_binfo) if (TYPE_HAS_ASSIGN_REF (basetype) && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) b->no_const_asn_ref = 1; - if (! TYPE_HAS_ASSIGN_REF (basetype) - || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2 - && ! is_friend_type (t, basetype))) - b->cant_synth_asn_ref = 1; b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype); TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); @@ -1645,8 +1633,6 @@ finish_base_struct (t, b, t_binfo) { cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity", basetype, t); - b->cant_synth_asn_ref = 1; - b->cant_synth_copy_ctor = 1; } } { @@ -1660,8 +1646,6 @@ finish_base_struct (t, b, t_binfo) if (extra_warnings) cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", basetype, t); - b->cant_synth_asn_ref = 1; - b->cant_synth_copy_ctor = 1; } } } @@ -3016,8 +3000,6 @@ finish_struct_1 (t, attributes, warn_anon) tree vfields; int cant_have_default_ctor; int cant_have_const_ctor; - int cant_synth_copy_ctor; - int cant_synth_asn_ref; int no_const_asn_ref; /* The index of the first base class which has virtual @@ -3108,8 +3090,6 @@ finish_struct_1 (t, attributes, warn_anon) CLASSTYPE_RTTI (t) = base_info.rtti; cant_have_default_ctor = base_info.cant_have_default_ctor; cant_have_const_ctor = base_info.cant_have_const_ctor; - cant_synth_copy_ctor = base_info.cant_synth_copy_ctor; - cant_synth_asn_ref = base_info.cant_synth_asn_ref; no_const_asn_ref = base_info.no_const_asn_ref; base_has_virtual = base_info.base_has_virtual; n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); @@ -3126,8 +3106,6 @@ finish_struct_1 (t, attributes, warn_anon) last_x = NULL_TREE; cant_have_default_ctor = 0; cant_have_const_ctor = 0; - cant_synth_copy_ctor = 0; - cant_synth_asn_ref = 0; no_const_asn_ref = 0; base_has_virtual = 0; } @@ -3273,7 +3251,7 @@ finish_struct_1 (t, attributes, warn_anon) #if 0 if (DECL_NAME (x) == constructor_name (t)) - cant_have_default_ctor = cant_synth_copy_ctor = 1; + cant_have_default_ctor = 1; #endif if (TREE_TYPE (x) == error_mark_node) @@ -3313,8 +3291,8 @@ finish_struct_1 (t, attributes, warn_anon) aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ - cant_synth_asn_ref = 1; cant_have_default_ctor = 1; + TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) { @@ -3336,8 +3314,8 @@ finish_struct_1 (t, attributes, warn_anon) aggregate, initialization by a brace-enclosed list) is the only way to initialize nonstatic const and reference members. */ - cant_synth_asn_ref = 1; cant_have_default_ctor = 1; + TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) && extra_warnings) @@ -3508,18 +3486,10 @@ finish_struct_1 (t, attributes, warn_anon) TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); } - if (! TYPE_HAS_INIT_REF (type) - || (TYPE_HAS_NONPUBLIC_CTOR (type) - && ! is_friend (t, type))) - cant_synth_copy_ctor = 1; - else if (!TYPE_HAS_CONST_INIT_REF (type)) + if (!TYPE_HAS_CONST_INIT_REF (type)) cant_have_const_ctor = 1; - if (! TYPE_HAS_ASSIGN_REF (type) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type) - && ! is_friend (t, type))) - cant_synth_asn_ref = 1; - else if (!TYPE_HAS_CONST_ASSIGN_REF (type)) + if (!TYPE_HAS_CONST_ASSIGN_REF (type)) no_const_asn_ref = 1; if (TYPE_HAS_CONSTRUCTOR (type) @@ -3614,8 +3584,7 @@ finish_struct_1 (t, attributes, warn_anon) } /* Create default copy constructor, if needed. */ - if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor - && ! IS_SIGNATURE (t)) + if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t)) { /* ARM 12.18: You get either X(X&) or X(const X&), but not both. --Chip */ @@ -3630,8 +3599,7 @@ finish_struct_1 (t, attributes, warn_anon) TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); - if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref - && ! IS_SIGNATURE (t)) + if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t)) { tree default_fn = cons_up_default_function (t, name, 5 + no_const_asn_ref); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 272ac1b4e2b..d1317743ac3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2403,7 +2403,6 @@ extern void print_lang_statistics PROTO((void)); extern tree array_type_nelts_total PROTO((tree)); extern tree array_type_nelts_top PROTO((tree)); extern tree break_out_target_exprs PROTO((tree)); -extern int cp_expand_decl_cleanup PROTO((tree, tree)); extern tree get_type_decl PROTO((tree)); extern tree vec_binfo_member PROTO((tree, tree)); extern tree hack_decl_function_context PROTO((tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 972939e6e4c..3672ee5b7fa 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -596,13 +596,24 @@ build_up_reference (type, arg, flags, checkconst) if (TREE_ADDRESSABLE (targ) == 0) { - tree temp; + if (! (flags&INDIRECT_BIND) + && toplevel_bindings_p ()) + { + tree temp = get_temp_name (argtype, 0); + /* Give this new temp some rtl and initialize it. */ + DECL_INITIAL (temp) = targ; + TREE_STATIC (temp) = 1; + cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); + /* Do this after declaring it static. */ + rval = build_unary_op (ADDR_EXPR, temp, 0); + TREE_TYPE (rval) = type; + literal_flag = TREE_CONSTANT (rval); + goto done; + } if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) { - temp = build_cplus_new (argtype, targ); - rval = build1 (ADDR_EXPR, type, temp); - goto done; + arg = build_cplus_new (argtype, targ); } else if (flags&INDIRECT_BIND) { @@ -611,41 +622,41 @@ build_up_reference (type, arg, flags, checkconst) use INDIRECT_BIND. */ tree slot = build (VAR_DECL, argtype); layout_decl (slot, 0); - rval = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE); - rval = build1 (ADDR_EXPR, type, rval); - goto done; + arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE); } else { - temp = get_temp_name (argtype, 0); - if (toplevel_bindings_p ()) - { - /* Give this new temp some rtl and initialize it. */ - DECL_INITIAL (temp) = targ; - TREE_STATIC (temp) = 1; - cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); - /* Do this after declaring it static. */ - rval = build_unary_op (ADDR_EXPR, temp, 0); - TREE_TYPE (rval) = type; - literal_flag = TREE_CONSTANT (rval); - goto done; - } + tree temp = get_temp_name (argtype, 0); + rval = build_unary_op (ADDR_EXPR, temp, 0); + if (binfo && !BINFO_OFFSET_ZEROP (binfo)) + rval = convert_pointer_to (target_type, rval); else - { - rval = build_unary_op (ADDR_EXPR, temp, 0); - if (binfo && !BINFO_OFFSET_ZEROP (binfo)) - rval = convert_pointer_to (target_type, rval); - else - TREE_TYPE (rval) = type; + TREE_TYPE (rval) = type; + + temp = build (MODIFY_EXPR, argtype, temp, arg); + TREE_SIDE_EFFECTS (temp) = 1; + return build (COMPOUND_EXPR, type, temp, rval); + } + } + + if (! (flags&INDIRECT_BIND)) + { + if (TREE_CODE (arg) == TARGET_EXPR) + { + tree decl = TREE_OPERAND (arg, 0); + tree cleanup; - temp = build (MODIFY_EXPR, argtype, temp, arg); - TREE_SIDE_EFFECTS (temp) = 1; - return build (COMPOUND_EXPR, type, temp, rval); + if (! toplevel_bindings_p ()) + { + expand_decl (decl); + cleanup = maybe_build_cleanup (decl); + if (cleanup) + expand_decl_cleanup (decl, cleanup); } } } - else - rval = build1 (ADDR_EXPR, type, arg); + + rval = build1 (ADDR_EXPR, type, arg); done: if (TYPE_USES_COMPLEX_INHERITANCE (argtype) @@ -1498,10 +1509,10 @@ build_type_conversion (code, xtype, expr, for_sure) /* Nope; try looking for others. */ for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) { - if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + if (winner && TREE_VALUE (winner) == TREE_VALUE (conv)) continue; - if (can_convert (xtype, TREE_VALUE (conv))) + if (can_convert (xtype, TREE_PURPOSE (conv))) { if (winner) { @@ -1510,7 +1521,7 @@ build_type_conversion (code, xtype, expr, for_sure) cp_error ("ambiguous conversion from `%T' to `%T'", basetype, xtype); cp_error (" candidate conversions include `%T' and `%T'", - TREE_VALUE (winner), TREE_VALUE (conv)); + TREE_PURPOSE (winner), TREE_PURPOSE (conv)); } return NULL_TREE; } @@ -1521,7 +1532,7 @@ build_type_conversion (code, xtype, expr, for_sure) if (winner) return build_type_conversion_1 (xtype, basetype, expr, - TREE_PURPOSE (winner), for_sure); + DECL_NAME (TREE_VALUE (winner)), for_sure); return NULL_TREE; } @@ -1580,10 +1591,10 @@ build_expr_type_conversion (desires, expr, complain) int win = 0; tree candidate; - if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + if (winner && TREE_VALUE (winner) == TREE_VALUE (conv)) continue; - candidate = TREE_VALUE (conv); + candidate = TREE_PURPOSE (conv); if (TREE_CODE (candidate) == REFERENCE_TYPE) candidate = TREE_TYPE (candidate); @@ -1609,7 +1620,7 @@ build_expr_type_conversion (desires, expr, complain) cp_error ("ambiguous default type conversion from `%T'", basetype); cp_error (" candidate conversions include `%T' and `%T'", - TREE_VALUE (winner), TREE_VALUE (conv)); + TREE_PURPOSE (winner), TREE_PURPOSE (conv)); } return error_mark_node; } @@ -1620,11 +1631,11 @@ build_expr_type_conversion (desires, expr, complain) if (winner) { - tree type = TREE_VALUE (winner); + tree type = TREE_PURPOSE (winner); if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); return build_type_conversion_1 (type, basetype, expr, - TREE_PURPOSE (winner), 1); + DECL_NAME (TREE_VALUE (winner)), 1); } return NULL_TREE; @@ -1820,6 +1831,41 @@ null_ptr_cst (t) } tree +build_conv (code, type, from) + enum tree_code code; + tree type, from; +{ + tree t = build1 (code, type, from); + int rank = ICS_STD_RANK (from); + switch (code) + { + case PROMO_CONV: + if (rank < PROMO_RANK) + rank = PROMO_RANK; + break; + + case PTR_CONV: + case PMEM_CONV: + case BASE_CONV: + case STD_CONV: + if (rank < STD_RANK) + rank = STD_RANK; + break; + + case PBOOL_CONV: + if (rank < PBOOL_RANK) + rank = PBOOL_RANK; + break; + + default: + break; + } + ICS_STD_RANK (t) = rank; + ICS_USER_FLAG (t) = ICS_USER_FLAG (from); + return t; +} + +tree standard_conversion (to, from, expr) tree to, from, expr; { @@ -1830,25 +1876,27 @@ standard_conversion (to, from, expr) if (from == to) return from; - conv = from; + conv = build1 (EXACT_CONV, from, expr); + if (TREE_CODE (expr) == USER_CONV) + ICS_USER_FLAG (conv) = 1; if (fcode == FUNCTION_TYPE) { from = build_pointer_type (from); fcode = TREE_CODE (from); - conv = build1 (LVALUE_CONV, from, conv); + conv = build_conv (LVALUE_CONV, from, conv); } else if (fcode == ARRAY_TYPE) { from = build_pointer_type (TREE_TYPE (from)); fcode = TREE_CODE (from); - conv = build1 (LVALUE_CONV, from, conv); + conv = build_conv (LVALUE_CONV, from, conv); } if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) && expr && null_ptr_cst (expr)) { - conv = build1 (CONV_CONV, to, conv); + conv = build_conv (STD_CONV, to, conv); } else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) { @@ -1864,7 +1912,7 @@ standard_conversion (to, from, expr) from = cp_build_type_variant (void_type_node, TYPE_READONLY (TREE_TYPE (from)), TYPE_VOLATILE (TREE_TYPE (from))); - conv = build1 (CONV_CONV, from, conv); + conv = build_conv (PTR_CONV, from, conv); } else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) { @@ -1877,7 +1925,7 @@ standard_conversion (to, from, expr) 1))) { from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); - conv = build1 (CONV_CONV, from, conv); + conv = build_conv (PMEM_CONV, from, conv); } else return 0; @@ -1890,7 +1938,7 @@ standard_conversion (to, from, expr) from = cp_build_type_variant (TREE_TYPE (to), TYPE_READONLY (TREE_TYPE (from)), TYPE_VOLATILE (TREE_TYPE (from))); - conv = build1 (CONV_CONV, from, conv); + conv = build_conv (PTR_CONV, from, conv); } else return 0; @@ -1901,7 +1949,7 @@ standard_conversion (to, from, expr) if (! comptypes (from, to, 1) && comp_ptr_ttypes (to, from)) { from = to; - conv = build1 (QUAL_CONV, from, conv); + conv = build_conv (QUAL_CONV, from, conv); } } else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from)) @@ -1923,29 +1971,32 @@ standard_conversion (to, from, expr) TYPE_VOLATILE (fbase)); from = build_cplus_method_type (from, TREE_TYPE (fromfn), TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); - conv = build1 (CONV_CONV, from, conv); + conv = build_conv (PMEM_CONV, from, conv); } else if (tcode == BOOLEAN_TYPE) { - if (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE - || fcode == POINTER_TYPE) - return build1 (CONV_CONV, to, conv); - else + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE + || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) return 0; + + if (fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)) + conv = build_conv (PBOOL_CONV, to, conv); + else + conv = build_conv (STD_CONV, to, conv); } else if (INTEGRAL_CODE_P (tcode) || tcode == REAL_TYPE) { if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) return 0; else if (to == type_promotes_to (from)) - conv = build1 (PROMO_CONV, to, conv); + conv = build_conv (PROMO_CONV, to, conv); else - conv = build1 (CONV_CONV, to, conv); + conv = build_conv (STD_CONV, to, conv); } else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) && DERIVED_FROM_P (to, from)) { - conv = build1 (CONV_CONV, to, conv); + conv = build_conv (BASE_CONV, to, conv); } else return 0; @@ -1958,16 +2009,366 @@ implicit_conversion (to, from, expr, flags) tree to, from, expr; int flags; { - tree conv = standard_conversion (to, from, expr); + tree t, conv = standard_conversion (to, from, expr); + struct z_candidate *cand; if (conv || (flags & LOOKUP_NO_CONVERSION)) return conv; flags |= LOOKUP_NO_CONVERSION; - /* try constructors */; - /* try conversion ops */; + cand = build_user_type_conversion_1 (to, expr, flags); + if (! cand) + return NULL_TREE; + + conv = cand->second_conv; + + for (t = conv; TREE_CODE (TREE_OPERAND (t, 0)) != EXACT_MATCH; ) + t = TREE_OPERAND (t, 0)); + + TREE_OPERAND (t, 0) = build (USER_CONV return conv; } + +struct z_candidate * +add_method_candidate (candidates, method, instance, parms, flags) + struct z_candidate *candidates; + tree method, instance, parms; + int flags; +{ + +} + +struct z_candidate * +build_user_type_conversion_1 (totype, expr, flags) + tree totype, expr; + int flags; +{ + struct z_candidate *candidates, *cand; + tree fromtype = TREE_TYPE (expr); + tree ctors = NULL_TREE, convs = NULL_TREE, t; + + if (IS_AGGR_TYPE (totype)) + ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); + if (IS_AGGR_TYPE (fromtype)) + convs = lookup_conversions (fromtype); + + if (ctors) + ctors = TREE_VALUE (ctors); + for (; ctors; ctors = DECL_CHAIN (ctors)) + { + candidates = add_ctor_candidate (candidates, ctors, expr, flags); + } + + for (; convs; convs = TREE_CHAIN (convs)) + { + tree fn = TREE_VALUE (convs); + tree ics = standard_conversion (totype, TREE_TYPE (TREE_TYPE (fn)), 0); + if (ics) + { + candidates = add_method_candidate + (candidates, fn, expr, NULL_TREE, flags); + candidates->second_ics = ics; + } + } + + if (! any_viable (candidates)) + { + if (flags & LOOKUP_COMPLAIN) + cp_error ("no viable candidates"); + return 0; + } + + candidates = splice_viable (candidates); + cand = tourney (candidates, totype); + + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) + cp_error ("ambiguous user-defined type conversion"); + } + + return cand; +} + +/* Compare two implicit conversion sequences according to the rules set out in + [over.ics.rank]. Return values: + + 1: ics1 is better than ics2 + -1: ics2 is better than ics1 + 0: ics1 and ics2 are indistinguishable */ + +int +compare_ics (ics1, ics2) + tree ics1, ics2; +{ + tree main1, main2; + + if (ICS_RANK (ics1) > ICS_RANK (ics2)) + return 1; + else if (ICS_RANK (ics1) < ICS_RANK (ics2)) + return -1; + + /* User-defined conversion sequence U1 is a better conversion sequence + than another user-defined conversion sequence U2 if they contain the + same user-defined conversion operator or constructor and if the sec- + ond standard conversion sequence of U1 is better than the second + standard conversion sequence of U2. */ + + if (ICS_RANK (ics1) == USER_RANK) + { + tree t1, t2; + + for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0)) + ; + for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0)) + ; + + if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) + return 0; + else if (ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2)) + return 1; + else if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) + return -1; + + /* else fall through */ + } + +#if 0 /* Handled by ranking */ + /* A conversion that is not a conversion of a pointer, or pointer to + member, to bool is better than another conversion that is such a + conversion. */ + { + int bool1 = TREE_CODE (ics1) == BOOL_CONV; + int bool2 = TREE_CODE (ics2) == BOOL_CONV; + + if (bool1) + { + tree it = TREE_TYPE (TREE_OPERAND (ics1, 0)); + if (TREE_CODE (it) != POINTER_TYPE + && ! TYPE_PTRMEMFUNC_TYPE (it)) + bool1 = 0; + } + if (bool2) + { + tree it = TREE_TYPE (TREE_OPERAND (ics2, 0)); + if (TREE_CODE (it) != POINTER_TYPE + && ! TYPE_PTRMEMFUNC_TYPE (it)) + bool2 = 0; + } + if (bool1 && ! bool2) + return 1; + if (bool2 && ! bool1) + return -1; + } +#endif + + if (TREE_CODE (ics1) == QUAL_CONV) + main1 = TREE_OPERAND (ics1, 0); + else + main1 = ics1; + + if (TREE_CODE (ics2) == QUAL_CONV) + main2 = TREE_OPERAND (ics2, 0); + else + main2 = ics2; + + if (TREE_CODE (main1) != TREE_CODE (main2)) + return 0; + + if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV + || TREE_CODE (main1) == REF_BIND) + { + tree to1 = TREE_TYPE (main1); + tree from1 = TREE_TYPE (TREE_OPERAND (main1, 0)); + tree to2 = TREE_TYPE (main2); + tree from2 = TREE_TYPE (TREE_OPERAND (main2, 0)); + int distf, distt; + + /* Standard conversion sequence S1 is a better conversion sequence than + standard conversion sequence S2 if... + + S1 and S2 differ only in their qualification conversion and they + yield types identical except for cv-qualifiers and S2 adds all the + qualifiers that S1 adds (and in the same places) and S2 adds yet + more cv-qualifiers than S1, or the similar case with reference + binding15). */ + if (from1 == from2 && to1 == to2) + { + to1 = TREE_TYPE (TREE_TYPE (ics1)); + to2 = TREE_TYPE (TREE_TYPE (ics2)); + if (TYPE_READONLY (to1) >= TYPE_READONLY (to2) + && TYPE_VOLATILE (to1) > TYPE_VOLATILE (to2)) + return 1; + else if (TYPE_READONLY (to1) > TYPE_READONLY (to2) + && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2)) + return 1; + else if (TYPE_READONLY (to1) <= TYPE_READONLY (to2) + && TYPE_VOLATILE (to1) < TYPE_VOLATILE (to2)) + return -1; + else if (TYPE_READONLY (to1) < TYPE_READONLY (to2) + && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2)) + return -1; + return 0; + } + + if (TYPE_PTRMEMFUNC_P (to1)) + { + to1 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to1)); + from1 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (from1)); + } + else + { + to1 = TREE_TYPE (to1); + from1 = TREE_TYPE (from1); + + if (TREE_CODE (to1) == OFFSET_TYPE) + { + to1 = TYPE_OFFSET_BASETYPE (to1); + from1 = TYPE_OFFSET_BASETYPE (from1); + } + } + + if (TYPE_PTRMEMFUNC_P (to2)) + { + to2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2)); + from2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (from2)); + } + else + { + to2 = TREE_TYPE (to2); + from2 = TREE_TYPE (from2); + + if (TREE_CODE (to2) == OFFSET_TYPE) + { + to2 = TYPE_OFFSET_BASETYPE (to2); + from2 = TYPE_OFFSET_BASETYPE (from2); + } + } + + if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2))) + return 0; + + distf = get_base_distance (from1, from2, 0, 0); + if (distf == -1) + distf = -get_base_distance (from2, from1, 0, 0); + if (distf == -1) + return 0; + + /* If class B is derived directly or indirectly from class A, conver- + sion of B* to A* is better than conversion of B* to void*, and + conversion of A* to void* is better than conversion of B* to void*. */ + + if (TREE_CODE (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE) + { + if (distf > 0) + return 1; + else if (distf < 0) + return -1; + } + else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1) + && get_base_distance (to1, from1, 0, 0) != -1) + return 1; + else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2) + && get_base_distance (to2, from2, 0, 0) != -1) + return -1; + + if (! (IS_AGGR_TYPE (to1) && IS_AGGR_TYPE (to2))) + return 0; + + /* If class B is derived directly or indirectly from class A and class + C is derived directly or indirectly from B */ + + distt = get_base_distance (to1, to2, 0, 0); + if (distt == -1) + distt = -get_base_distance (to2, to1, 0, 0); + if (distt == -1) + return 0; + + /* --conversion of C* to B* is better than conversion of C* to A*, */ + if (distf == 0) + { + if (distt > 0) + return -1; + else if (distt < 0) + return 1; + } + /* --conversion of B* to A* is better than conversion of C* to A*, */ + else if (distt == 0) + { + if (distf > 0) + return 1; + else if (distf < 0) + return -1; + } + } + return 0; +} + +int joust (cand1, cand2) + struct z_candidate *cand1, *cand2; +{ + int winner = 0; + int i; + + for (i = 0; i < TREE_VEC_LENGTH (cand1->convs); ++i) + { + int comp = compare_ics (TREE_VEC_ELT (cand1->convs, i), + TREE_VEC_ELT (cand2->convs, i)); + + if (comp != 0) + { + if (winner && comp != winner) + return 0; + winner = comp; + } + } + + if (winner == 0 && cand1->second_ics) + winner = compare_ics (cand1->second_ics, cand2->second_ics); + + return winner; +} + +struct z_candidate * +tourney (candidates) + struct z_candidate *candidates; +{ + struct z_candidate *champ = candidates, *challenger; + int fate; + + /* This algorithm has a worst case of O(2n) (winner is last) , and a best + case of O(n/2) (no winner); much better than a sorting algorithm. */ + + for (challenger = champ->next; challenger; ) + { + fate = joust (champ, challenger); + if (fate == 1) + challenger = challenger->next; + else + { + if (fate == 0) + { + champ = challenger->next; + if (champ == 0) + return 0; + } + else + champ = challenger; + + challenger = champ->next; + } + } + + for (challenger = candidates; challenger != champ; + challenger = challenger->next) + { + fate = joust (champ, challenger); + if (fate != 1) + return 0; + } + + return champ; +} #endif diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 73b570945d2..fe1b60fb2df 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -300,6 +300,16 @@ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier; tree pfn_or_delta2_identifier, tag_identifier; tree vt_off_identifier; +struct named_label_list +{ + struct binding_level *binding_level; + tree names_in_scope; + tree label_decl; + char *filename_o_goto; + int lineno_o_goto; + struct named_label_list *next; +}; + /* A list (chain of TREE_LIST nodes) of named label uses. The TREE_PURPOSE field is the list of variables defined the the label's scope defined at the point of use. @@ -307,11 +317,17 @@ tree vt_off_identifier; The TREE_TYPE field holds `current_binding_level' at the point of the label's use. + BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken. + + Look at the pretty struct named_label_list. See the pretty struct + with the pretty named fields that describe what they do. See the + pretty lack of gratuitous casts. Notice the code got a lot cleaner. + Used only for jumps to as-yet undefined labels, since jumps to defined labels can have their validity checked by stmt.c. */ -static tree named_label_uses; +static struct named_label_list *named_label_uses = NULL; /* A list of objects which have constructors or destructors which reside in the global scope. The decl is stored in @@ -1199,12 +1215,12 @@ poplevel (keep, reverse, functionbody) level_chain = current_binding_level->level_chain; if (level_chain) { - tree labels; - for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels)) - if (TREE_TYPE (labels) == (tree)current_binding_level) + struct named_label_list *labels; + for (labels = named_label_uses; labels; labels = labels->next) + if (labels->binding_level == current_binding_level) { - TREE_TYPE (labels) = (tree)level_chain; - TREE_PURPOSE (labels) = level_chain->names; + labels->binding_level = level_chain; + labels->names_in_scope = level_chain->names; } } } @@ -1739,11 +1755,9 @@ struct saved_scope { tree old_bindings; struct saved_scope *prev; tree class_name, class_type, function_decl; - tree base_init_list, member_init_list; struct binding_level *class_bindings; tree *lang_base, *lang_stack, lang_name; int lang_stacksize; - tree named_labels; int minimal_parse_mode; tree last_function_parms; tree template_parms; @@ -1803,6 +1817,9 @@ maybe_push_to_top_level (pseudo) struct binding_level *b = inner_binding_level; tree old_bindings = NULL_TREE; + if (current_function_decl) + push_cp_function_context (NULL_TREE); + if (previous_class_type) old_bindings = store_bindings (previous_class_values, old_bindings); @@ -1832,19 +1849,17 @@ maybe_push_to_top_level (pseudo) s->class_name = current_class_name; s->class_type = current_class_type; s->function_decl = current_function_decl; - s->base_init_list = current_base_init_list; - s->member_init_list = current_member_init_list; s->class_bindings = class_binding_level; s->lang_stack = current_lang_stack; s->lang_base = current_lang_base; s->lang_stacksize = current_lang_stacksize; s->lang_name = current_lang_name; - s->named_labels = named_labels; s->minimal_parse_mode = minimal_parse_mode; s->last_function_parms = last_function_parms; s->template_parms = current_template_parms; s->previous_class_type = previous_class_type; s->previous_class_values = previous_class_values; + current_class_name = current_class_type = NULL_TREE; current_function_decl = NULL_TREE; class_binding_level = (struct binding_level *)0; @@ -1902,8 +1917,6 @@ pop_from_top_level () } current_class_name = s->class_name; current_class_type = s->class_type; - current_base_init_list = s->base_init_list; - current_member_init_list = s->member_init_list; current_function_decl = s->function_decl; class_binding_level = s->class_bindings; free (current_lang_base); @@ -1915,7 +1928,6 @@ pop_from_top_level () strict_prototype = strict_prototypes_lang_cplusplus; else if (current_lang_name == lang_name_c) strict_prototype = strict_prototypes_lang_c; - named_labels = s->named_labels; minimal_parse_mode = s->minimal_parse_mode; last_function_parms = s->last_function_parms; current_template_parms = s->template_parms; @@ -1923,6 +1935,9 @@ pop_from_top_level () previous_class_values = s->previous_class_values; free (s); + + if (current_function_decl) + pop_cp_function_context (NULL_TREE); } /* Push a definition of struct, union or enum tag "name". @@ -3717,13 +3732,20 @@ lookup_label (id) if ((decl == NULL_TREE || DECL_SOURCE_LINE (decl) == 0) - && (named_label_uses == NULL_TREE - || TREE_PURPOSE (named_label_uses) != current_binding_level->names - || TREE_VALUE (named_label_uses) != decl)) - { - named_label_uses - = tree_cons (current_binding_level->names, decl, named_label_uses); - TREE_TYPE (named_label_uses) = (tree)current_binding_level; + && (named_label_uses == NULL + || named_label_uses->names_in_scope != current_binding_level->names + || named_label_uses->label_decl != decl)) + { + struct named_label_list *new_ent; + new_ent + = (struct named_label_list*)oballoc (sizeof (struct named_label_list)); + new_ent->label_decl = decl; + new_ent->names_in_scope = current_binding_level->names; + new_ent->binding_level = current_binding_level; + new_ent->lineno_o_goto = lineno; + new_ent->filename_o_goto = input_filename; + new_ent->next = named_label_uses; + named_label_uses = new_ent; } /* Use a label already defined or ref'd with this name. */ @@ -3754,7 +3776,7 @@ lookup_label (id) SET_IDENTIFIER_LABEL_VALUE (id, decl); named_labels = tree_cons (NULL_TREE, decl, named_labels); - TREE_VALUE (named_label_uses) = decl; + named_label_uses->label_decl = decl; return decl; } @@ -3830,7 +3852,7 @@ define_label (filename, line, name) } else { - tree uses, prev; + struct named_label_list *uses, *prev; int identified = 0; /* Mark label as having been defined. */ @@ -3839,17 +3861,17 @@ define_label (filename, line, name) DECL_SOURCE_FILE (decl) = filename; DECL_SOURCE_LINE (decl) = line; - for (prev = NULL_TREE, uses = named_label_uses; - uses; - prev = uses, uses = TREE_CHAIN (uses)) - if (TREE_VALUE (uses) == decl) + prev = NULL; + uses = named_label_uses; + while (uses != NULL) + if (uses->label_decl == decl) { struct binding_level *b = current_binding_level; while (b) { tree new_decls = b->names; - tree old_decls = ((tree)b == TREE_TYPE (uses) - ? TREE_PURPOSE (uses) : NULL_TREE); + tree old_decls = (b == uses->binding_level) + ? uses->names_in_scope : NULL_TREE; while (new_decls != old_decls) { if (TREE_CODE (new_decls) == VAR_DECL @@ -3862,23 +3884,35 @@ define_label (filename, line, name) && DECL_INITIAL (new_decls) != error_mark_node) || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))) { - if (! identified) - cp_error ("jump to label `%D'", decl); - identified = 1; + if (! identified) + { + cp_error ("jump to label `%D'", decl); + error_with_file_and_line (uses->filename_o_goto, + uses->lineno_o_goto, + " from here"); + identified = 1; + } cp_error_at (" crosses initialization of `%#D'", new_decls); } new_decls = TREE_CHAIN (new_decls); } - if ((tree)b == TREE_TYPE (uses)) + if (b == uses->binding_level) break; b = b->level_chain; } - if (prev) - TREE_CHAIN (prev) = TREE_CHAIN (uses); + if (prev != NULL) + prev->next = uses->next; else - named_label_uses = TREE_CHAIN (uses); + named_label_uses = uses->next; + + uses = uses->next; + } + else + { + prev = uses; + uses = uses->next; } current_function_return_value = NULL_TREE; return decl; @@ -4665,7 +4699,7 @@ init_decl_processing () current_function_decl = NULL_TREE; named_labels = NULL_TREE; - named_label_uses = NULL_TREE; + named_label_uses = NULL; current_binding_level = NULL_BINDING_LEVEL; free_binding_level = NULL_BINDING_LEVEL; @@ -5797,8 +5831,13 @@ start_decl (declarator, declspecs, initialized, raises) tree field = lookup_field (context, DECL_NAME (decl), 0, 0); if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) cp_error ("`%#D' is not a static member of `%#T'", decl, context); - else if (duplicate_decls (decl, field)) - decl = field; + else + { + if (DECL_CONTEXT (field) != context) + cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'", DECL_CONTEXT (field), DECL_NAME (decl), context, DECL_NAME (decl)); + if (duplicate_decls (decl, field)) + decl = field; + } } else { @@ -6034,25 +6073,7 @@ grok_reference_init (decl, type, init, cleanupp) goto fail; else if (tmp != NULL_TREE) { - tree subtype = TREE_TYPE (type); init = tmp; - - /* Associate the cleanup with the reference so that we - don't get burned by "aggressive" cleanup policy. */ - if (TYPE_NEEDS_DESTRUCTOR (subtype)) - { - if (TREE_CODE (tmp) == ADDR_EXPR) - tmp = TREE_OPERAND (tmp, 0); - if (TREE_CODE (tmp) == TARGET_EXPR) - { - *cleanupp = build_delete - (build_pointer_type (subtype), - build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0), - integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); - TREE_OPERAND (tmp, 2) = error_mark_node; - } - } - DECL_INITIAL (decl) = save_expr (init); } else @@ -6620,7 +6641,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) { /* XXX: Why don't we use decl here? */ /* Ans: Because it was already expanded? */ - if (! cp_expand_decl_cleanup (NULL_TREE, cleanup)) + if (! expand_decl_cleanup (NULL_TREE, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); /* Cleanup used up here. */ @@ -6710,7 +6731,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) /* Store the cleanup, if there was one. */ if (cleanup) { - if (! cp_expand_decl_cleanup (decl, cleanup)) + if (! expand_decl_cleanup (decl, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); } @@ -7113,6 +7134,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, if (check) { tmp = check_classfn (ctype, decl); + if (tmp && DECL_ARTIFICIAL (tmp)) + cp_error ("definition of implicitly-declared `%D'", tmp); if (tmp && duplicate_decls (decl, tmp)) return tmp; } @@ -7159,6 +7182,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, revert_static_member_fn (&decl, NULL, NULL); last_function_parms = TREE_CHAIN (last_function_parms); } + if (tmp && DECL_ARTIFICIAL (tmp)) + cp_error ("definition of implicitly-declared `%D'", tmp); if (tmp && duplicate_decls (decl, tmp)) return tmp; } @@ -7224,7 +7249,7 @@ grokvardecl (type, declarator, specbits, initialized, constp) DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator); } else - decl = build_decl (VAR_DECL, declarator, type); + decl = build_decl (VAR_DECL, declarator, complete_type (type)); DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl)); @@ -9118,7 +9143,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli return NULL_TREE; } - decl = build_decl (PARM_DECL, declarator, type); + decl = build_decl (PARM_DECL, declarator, complete_type (type)); bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); @@ -11279,7 +11304,7 @@ store_parm_decls () && (cleanup = maybe_build_cleanup (parm), cleanup)) { expand_decl (parm); - if (! cp_expand_decl_cleanup (parm, cleanup)) + if (! expand_decl_cleanup (parm, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", parm); parms_have_cleanups = 1; @@ -11973,7 +11998,7 @@ finish_function (lineno, call_poplevel, nested) current_function_decl = NULL_TREE; } - named_label_uses = NULL_TREE; + named_label_uses = NULL; current_class_ptr = NULL_TREE; current_class_ref = NULL_TREE; } @@ -12200,7 +12225,7 @@ hack_incomplete_structures (type) expand_decl (decl); cleanup = maybe_build_cleanup (decl); expand_decl_init (decl); - if (! cp_expand_decl_cleanup (decl, cleanup)) + if (! expand_decl_cleanup (decl, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl); } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 1f661558869..db4f294ff86 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1285,7 +1285,8 @@ dump_expr (t, nop) break; case CAST_EXPR: - if (TREE_CHAIN (TREE_OPERAND (t, 0))) + if (TREE_OPERAND (t, 0) == NULL_TREE + || TREE_CHAIN (TREE_OPERAND (t, 0))) { dump_type (TREE_TYPE (t), 0); OB_PUTC ('('); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index b530a3ba058..adebe3b4721 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -962,7 +962,7 @@ push_eh_cleanup () cleanup = build (COMPOUND_EXPR, void_type_node, cleanup, build_modify_expr (saved_in_catch, NOP_EXPR, build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node))); - cp_expand_decl_cleanup (NULL_TREE, cleanup); + expand_decl_cleanup (NULL_TREE, cleanup); resume_momentary (yes); } diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index ccdc8aef4c1..be3d89659e3 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -9,7 +9,7 @@ @chapter Internal Architecture of the Compiler This is meant to describe the C++ front-end for gcc in detail. -Questions and comments to mrs@@cygnus.com. +Questions and comments to Mike Stump @code{<mrs@@cygnus.com>}. @menu * Limitations of g++:: @@ -310,9 +310,7 @@ vtables. See also vtable and vfield. This section describes some of the macros used on trees. The list should be alphabetical. Eventually all macros should be documented -here. There are some postscript drawings that can be used to better -understand from of the more complex data structures, contact Mike Stump -(@code{mrs@@cygnus.com}) for information about them. +here. @table @code @item BINFO_BASETYPES diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5695c980f62..bccbc29af3c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -615,9 +615,14 @@ emit_base_init (t, immediately) if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo))) { start_protect (); + + /* All cleanups must be on the function_obstack. */ + push_obstacks_nochange (); + resume_temporary_allocation (); protect_list = tree_cons (NULL_TREE, build_partial_cleanup_for (base_binfo), protect_list); + pop_obstacks (); } rbase_init_list = TREE_CHAIN (rbase_init_list); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 0b46990f60d..fffbc8a8059 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -2750,24 +2750,6 @@ identifier_typedecl_value (node) return NULL_TREE; } -struct try_type -{ - tree *node_var; - char unsigned_flag; - char long_flag; - char long_long_flag; -}; - -struct try_type type_sequence[] = -{ - { &integer_type_node, 0, 0, 0}, - { &unsigned_type_node, 1, 0, 0}, - { &long_integer_type_node, 0, 1, 0}, - { &long_unsigned_type_node, 1, 1, 0}, - { &long_long_integer_type_node, 0, 1, 1}, - { &long_long_unsigned_type_node, 1, 1, 1} -}; - int real_yylex () { @@ -3528,83 +3510,10 @@ real_yylex () yylval.ttype = build_int_2 (low, high); TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node; -#if 0 - /* Find the first allowable type that the value fits in. */ - type = 0; - for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]); - i++) - if (!(spec_long && !type_sequence[i].long_flag) - && !(spec_long_long && !type_sequence[i].long_long_flag) - && !(spec_unsigned && !type_sequence[i].unsigned_flag) - /* A hex or octal constant traditionally is unsigned. */ - && !(base != 10 && flag_traditional - && !type_sequence[i].unsigned_flag) - /* A decimal constant can't be unsigned int - unless explicitly specified. */ - && !(base == 10 && !spec_unsigned - && *type_sequence[i].node_var == unsigned_type_node)) - if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var)) - { - type = *type_sequence[i].node_var; - break; - } - if (flag_traditional && type == long_unsigned_type_node - && !spec_unsigned) - type = long_integer_type_node; - - if (type == 0) - { - type = long_long_integer_type_node; - warning ("integer constant out of range"); - } - - /* Warn about some cases where the type of a given constant - changes from traditional C to ANSI C. */ - if (warn_traditional) - { - tree other_type = 0; - - /* This computation is the same as the previous one - except that flag_traditional is used backwards. */ - for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]); - i++) - if (!(spec_long && !type_sequence[i].long_flag) - && !(spec_long_long && !type_sequence[i].long_long_flag) - && !(spec_unsigned && !type_sequence[i].unsigned_flag) - /* A hex or octal constant traditionally is unsigned. */ - && !(base != 10 && !flag_traditional - && !type_sequence[i].unsigned_flag) - /* A decimal constant can't be unsigned int - unless explicitly specified. */ - && !(base == 10 && !spec_unsigned - && *type_sequence[i].node_var == unsigned_type_node)) - if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var)) - { - other_type = *type_sequence[i].node_var; - break; - } - if (!flag_traditional && type == long_unsigned_type_node - && !spec_unsigned) - type = long_integer_type_node; - - if (other_type != 0 && other_type != type) - { - if (flag_traditional) - warning ("type of integer constant would be different without -traditional"); - else - warning ("type of integer constant would be different with -traditional"); - } - } - -#else /* 1 */ if (!spec_long && !spec_unsigned && !(flag_traditional && base != 10) && int_fits_type_p (yylval.ttype, integer_type_node)) { -#if 0 - if (warn_traditional && base != 10) - warning ("small nondecimal constant becomes signed in ANSI C++"); -#endif type = integer_type_node; } else if (!spec_long && (base != 10 || spec_unsigned) @@ -3622,10 +3531,6 @@ real_yylex () && int_fits_type_p (yylval.ttype, long_unsigned_type_node)) { -#if 0 - if (warn_traditional && !spec_unsigned) - warning ("large integer constant becomes unsigned in ANSI C++"); -#endif if (flag_traditional && !spec_unsigned) type = long_integer_type_node; else @@ -3642,11 +3547,6 @@ real_yylex () else if (int_fits_type_p (yylval.ttype, long_long_unsigned_type_node)) { -#if 0 - if (warn_traditional && !spec_unsigned) - warning ("large nondecimal constant is unsigned in ANSI C++"); -#endif - if (flag_traditional && !spec_unsigned) type = long_long_integer_type_node; else @@ -3661,7 +3561,6 @@ real_yylex () if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) warning ("decimal integer constant is so large that it is unsigned"); } -#endif TREE_TYPE (yylval.ttype) = type; *p = 0; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 321492370ea..aa607e676a7 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1751,9 +1751,11 @@ emit_thunk (thunk_fndecl) abort (); current_function_decl = thunk_fndecl; #ifdef ASM_OUTPUT_MI_THUNK + temporary_allocation (); assemble_start_function (thunk_fndecl, fnname); ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); assemble_end_function (thunk_fndecl, fnname); + permanent_allocation (1); #else save_ofp = flag_omit_frame_pointer; flag_omit_frame_pointer = 1; @@ -1995,8 +1997,12 @@ do_build_copy_constructor (fndecl) (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); - current_base_init_list = tree_cons (basetype, - p, current_base_init_list); + + if (p == error_mark_node) + cp_error ("in default copy constructor"); + else + current_base_init_list = tree_cons (basetype, + p, current_base_init_list); } for (i = 0; i < n_bases; ++i) @@ -2009,9 +2015,15 @@ do_build_copy_constructor (fndecl) p = convert_to_reference (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); - p = convert_from_reference (p); - current_base_init_list = tree_cons (basetype, - p, current_base_init_list); + + if (p == error_mark_node) + cp_error ("in default copy constructor"); + else + { + p = convert_from_reference (p); + current_base_init_list = tree_cons (basetype, + p, current_base_init_list); + } } for (; fields; fields = TREE_CHAIN (fields)) { @@ -2080,16 +2092,13 @@ do_build_assign_ref (fndecl) 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_to_reference - (build_reference_type (basetype), parm, - CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); - p = convert_from_reference (p); - p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], - build_tree_list (NULL_TREE, p)); - expand_expr_stmt (p); - } + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); + p = convert_from_reference (p); + p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], + build_tree_list (NULL_TREE, p)); + expand_expr_stmt (p); } for (; fields; fields = TREE_CHAIN (fields)) { @@ -2098,6 +2107,24 @@ do_build_assign_ref (fndecl) if (TREE_CODE (field) != FIELD_DECL) continue; + + if (TREE_READONLY (field)) + { + if (DECL_NAME (field)) + cp_error ("non-static const member `%#D', can't use default assignment operator", field); + else + cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type); + continue; + } + else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) + { + if (DECL_NAME (field)) + cp_error ("non-static reference member `%#D', can't use default assignment operator", field); + else + cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type); + continue; + } + if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 536e6c6be56..39fadec4f11 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1187,6 +1187,7 @@ instantiate_class_template (type) /* XXX handle attributes */ type = finish_struct_1 (type, NULL_TREE, 0); + CLASSTYPE_GOT_SEMICOLON (type) = 1; } else { @@ -2968,8 +2969,6 @@ instantiate_decl (d) if (! push_tinst_level (d)) return d; - if (TREE_CODE (d) == FUNCTION_DECL && nested) - push_cp_function_context (NULL_TREE); push_to_top_level (); /* Trick tsubst into giving us a new decl in case the template changed. */ @@ -3044,8 +3043,6 @@ instantiate_decl (d) } pop_from_top_level (); - if (TREE_CODE (d) == FUNCTION_DECL && nested) - pop_cp_function_context (NULL_TREE); pop_tinst_level (); return d; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 2a852cd1276..465234c63aa 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -3508,7 +3508,7 @@ add_conversions (binfo) tree tmp = TREE_VEC_ELT (method_vec, i); if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp))) break; - conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)), + conversions = tree_cons (TREE_TYPE (TREE_TYPE (tmp)), tmp, conversions); } } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d0970cd2d48..b61932f3879 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -220,7 +220,7 @@ build_cplus_new (type, init) TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); TREE_SIDE_EFFECTS (rval) = 1; TREE_ADDRESSABLE (rval) = 1; - rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE); + rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (rval) = 1; TREE_ADDRESSABLE (rval) = 1; @@ -399,7 +399,7 @@ build_cplus_method_type (basetype, rettype, argtypes) } tree -build_cplus_array_type (elt_type, index_type) +build_cplus_array_type_1 (elt_type, index_type) tree elt_type; tree index_type; { @@ -433,6 +433,24 @@ build_cplus_array_type (elt_type, index_type) saveable_obstack = ambient_saveable_obstack; return t; } + +tree +build_cplus_array_type (elt_type, index_type) + tree elt_type; + tree index_type; +{ + tree t; + int constp = TYPE_READONLY (elt_type); + int volatilep = TYPE_VOLATILE (elt_type); + elt_type = TYPE_MAIN_VARIANT (elt_type); + + t = build_cplus_array_type_1 (elt_type, index_type); + + if (constp || volatilep) + t = cp_build_type_variant (t, constp, volatilep); + + return t; +} /* Make a variant type in the proper way for C/C++, propagating qualifiers down to the element type of an array. */ @@ -451,9 +469,9 @@ cp_build_type_variant (type, constp, volatilep) 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 = build_cplus_array_type_1 (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 @@ -467,6 +485,7 @@ cp_build_type_variant (type, constp, volatilep) TYPE_MAIN_VARIANT (type) = real_main_variant; pop_obstacks (); + return type; } return build_type_variant (type, constp, volatilep); } @@ -1753,16 +1772,6 @@ break_out_target_exprs (t) return mapcar (t, bot_manip); } -/* Since cleanup may have SAVE_EXPRs in it, we protect it with an - UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups - by itself. */ -int -cp_expand_decl_cleanup (decl, cleanup) - tree decl, cleanup; -{ - return expand_decl_cleanup (decl, unsave_expr (cleanup)); -} - /* Obstack used for allocating nodes in template function and variable definitions. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e1fac0d9341..d8b26e76633 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -129,7 +129,7 @@ complete_type (type) { if (TYPE_SIZE (type) != NULL_TREE) ; - else if (TREE_CODE (type) == ARRAY_TYPE) + else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) { tree t = complete_type (TREE_TYPE (type)); if (TYPE_SIZE (t) != NULL_TREE) @@ -437,10 +437,6 @@ common_type (t1, t2) case ARRAY_TYPE: { - int constp - = TYPE_READONLY (t1) || TYPE_READONLY (t2); - int volatilep - = TYPE_VOLATILE (t1) || TYPE_VOLATILE (t2); tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) @@ -448,9 +444,8 @@ common_type (t1, t2) if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) return build_type_attribute_variant (t2, attributes); /* Merge the element types, and have a size if either arg has one. */ - t1 = build_cplus_array_type (TYPE_MAIN_VARIANT (elt), TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); - if (constp || volatilep) - t1 = cp_build_type_variant (t1, constp, volatilep); + t1 = build_cplus_array_type + (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); return build_type_attribute_variant (t1, attributes); } |