summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog127
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/cp/class.c48
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/cvt.c519
-rw-r--r--gcc/cp/decl.c153
-rw-r--r--gcc/cp/error.c3
-rw-r--r--gcc/cp/except.c2
-rw-r--r--gcc/cp/gxxint.texi6
-rw-r--r--gcc/cp/init.c5
-rw-r--r--gcc/cp/lex.c101
-rw-r--r--gcc/cp/method.c57
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/cp/search.c2
-rw-r--r--gcc/cp/tree.c39
-rw-r--r--gcc/cp/typeck.c11
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);
}