diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index eb000083a11b..050f437f6d7d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2001-07-25 Jason Merrill + + * call.c (joust): Only prefer a non-builtin candidate to a builtin + one if they have the same signature. + + * cvt.c (build_up_reference): Take DECL parm. Check TREE_STATIC on + it rather than toplevel_bindings_p. Give it a mangled name if static. + (convert_to_reference): Adjust. + * decl2.c (get_temp_name): Lose. + * mangle.c (mangle_ref_init_variable): New fn. + (mangle_guard_variable): Strip the ref-init header. + * cp-tree.h: Adjust. + * decl.c (cp_finish_decl): Add the DECL_STMT after processing the + initializer. + (grok_reference_init): Always use DECL_INITIAL. + 2001-07-25 Nathan Sidwell PR c++/3416 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4be0920f2caf..268cc273a561 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5353,22 +5353,6 @@ joust (cand1, cand2, warn) return winner; } - /* a non-template user function is better than a builtin. (Pedantically - the builtin which matched the user function should not be added to - the overload set, but we spot it here. - - [over.match.oper] - ... the builtin candidates include ... - - do not have the same parameter type list as any non-template - non-member candidate. */ - - if (TREE_CODE (cand1->fn) != IDENTIFIER_NODE - && TREE_CODE (cand2->fn) == IDENTIFIER_NODE) - return 1; - else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE - && TREE_CODE (cand2->fn) != IDENTIFIER_NODE) - return -1; - /* or, if not that, the context is an initialization by user-defined conversion (see _dcl.init_ and _over.match.user_) and the standard conversion @@ -5384,21 +5368,42 @@ joust (cand1, cand2, warn) return winner; } - /* If the built-in candidates are the same, arbitrarily pick one. */ - if (cand1->fn == cand2->fn - && TREE_CODE (cand1->fn) == IDENTIFIER_NODE) + /* Check whether we can discard a builtin candidate, either because we + have two identical ones or matching builtin and non-builtin candidates. + + (Pedantically in the latter case the builtin which matched the user + function should not be added to the overload set, but we spot it here. + + [over.match.oper] + ... the builtin candidates include ... + - do not have the same parameter type list as any non-template + non-member candidate. */ + + if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE + || TREE_CODE (cand2->fn) == IDENTIFIER_NODE) { for (i = 0; i < len; ++i) if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)), TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)))) break; if (i == TREE_VEC_LENGTH (cand1->convs)) - return 1; + { + if (cand1->fn == cand2->fn) + /* Two built-in candidates; arbitrarily pick one. */ + return 1; + else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE) + /* cand1 is built-in; prefer cand2. */ + return -1; + else + /* cand2 is built-in; prefer cand1. */ + return 1; + } /* Kludge around broken overloading rules whereby Integer a, b; test ? a : b; is ambiguous, since there's a builtin that takes references and another that takes values. */ - if (cand1->fn == ansi_opname (COND_EXPR)) + if (cand1->fn == cand2->fn + && cand1->fn == ansi_opname (COND_EXPR)) { tree c1 = TREE_VEC_ELT (cand1->convs, 1); tree c2 = TREE_VEC_ELT (cand2->convs, 1); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8a6b0ae90d94..d5f10e4397d3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3784,7 +3784,6 @@ extern void cplus_decl_attributes PARAMS ((tree *, tree, tree, int)); extern tree constructor_name_full PARAMS ((tree)); extern tree constructor_name PARAMS ((tree)); extern void defer_fn PARAMS ((tree)); -extern tree get_temp_name PARAMS ((tree)); extern void finish_anon_union PARAMS ((tree)); extern tree finish_table PARAMS ((tree, tree, tree, int)); extern void finish_builtin_type PARAMS ((tree, const char *, @@ -4384,6 +4383,7 @@ extern tree mangle_ctor_vtbl_for_type PARAMS ((tree, tree)); extern tree mangle_thunk PARAMS ((tree, tree, tree)); extern tree mangle_conv_op_name_for_type PARAMS ((tree)); extern tree mangle_guard_variable PARAMS ((tree)); +extern tree mangle_ref_init_variable PARAMS ((tree)); /* in dump.c */ extern int cp_dump_tree PARAMS ((dump_info_p, tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 385ad2e5f9b3..3637cc0535a5 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA. */ static tree cp_convert_to_pointer PARAMS ((tree, tree, int)); static tree convert_to_pointer_force PARAMS ((tree, tree)); -static tree build_up_reference PARAMS ((tree, tree, int)); +static tree build_up_reference PARAMS ((tree, tree, int, tree)); static void warn_ref_binding PARAMS ((tree, tree, tree)); /* Change of width--truncation and extension of integers or reals-- @@ -358,11 +358,12 @@ convert_to_pointer_force (type, expr) value we have to begin with is in ARG. FLAGS controls how we manage access checking. - DIRECT_BIND in FLAGS controls how any temporaries are generated. */ + DIRECT_BIND in FLAGS controls how any temporaries are generated. + If DIRECT_BIND is set, DECL is the reference we're binding to. */ static tree -build_up_reference (type, arg, flags) - tree type, arg; +build_up_reference (type, arg, flags, decl) + tree type, arg, decl; int flags; { tree rval; @@ -374,15 +375,28 @@ build_up_reference (type, arg, flags) if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg)) { - /* Create a new temporary variable. */ + /* Create a new temporary variable. We can't just use a TARGET_EXPR + here because it needs to live as long as DECL. */ tree targ = arg; - if (toplevel_bindings_p ()) - arg = get_temp_name (argtype); + + arg = build_decl (VAR_DECL, NULL_TREE, argtype); + DECL_ARTIFICIAL (arg) = 1; + TREE_USED (arg) = 1; + TREE_STATIC (arg) = TREE_STATIC (decl); + + if (TREE_STATIC (decl)) + { + /* Namespace-scope or local static; give it a mangled name. */ + tree name = mangle_ref_init_variable (decl); + DECL_NAME (arg) = name; + SET_DECL_ASSEMBLER_NAME (arg, name); + arg = pushdecl_top_level (arg); + } else { + /* automatic; make sure we handle the cleanup properly. */ maybe_push_cleanup_level (argtype); - arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype)); - DECL_ARTIFICIAL (arg) = 1; + arg = pushdecl (arg); } /* Process the initializer for the declaration. */ @@ -393,7 +407,7 @@ build_up_reference (type, arg, flags) else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg)) return get_target_expr (arg); - /* If we had a way to wrap this up, and say, if we ever needed it's + /* If we had a way to wrap this up, and say, if we ever needed its address, transform all occurrences of the register, into a memory reference we could win better. */ rval = build_unary_op (ADDR_EXPR, arg, 1); @@ -531,7 +545,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ttr, reftype); } - return build_up_reference (reftype, expr, flags); + return build_up_reference (reftype, expr, flags, decl); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { @@ -562,7 +576,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl) if (rval == NULL_TREE || rval == error_mark_node) return rval; warn_ref_binding (reftype, intype, decl); - rval = build_up_reference (reftype, rval, flags); + rval = build_up_reference (reftype, rval, flags, decl); } if (rval) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c140af427c85..4bbf2e0f5d48 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7386,14 +7386,7 @@ grok_reference_init (decl, type, init) if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp)) return tmp; - if (building_stmt_tree ()) - { - /* Initialize the declaration. */ - tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp); - finish_expr_stmt (tmp); - } - else - DECL_INITIAL (decl) = tmp; + DECL_INITIAL (decl) = tmp; return NULL_TREE; } @@ -8010,17 +8003,16 @@ cp_finish_decl (decl, init, asmspec_tree, flags) if (type == error_mark_node) return; - /* Add this declaration to the statement-tree. */ - if (building_stmt_tree () - && at_function_scope_p () - && TREE_CODE (decl) != RESULT_DECL) - add_decl_stmt (decl); - if (TYPE_HAS_MUTABLE_P (type)) TREE_READONLY (decl) = 0; if (processing_template_decl) { + /* Add this declaration to the statement-tree. */ + if (at_function_scope_p () + && TREE_CODE (decl) != RESULT_DECL) + add_decl_stmt (decl); + if (init && DECL_INITIAL (decl)) DECL_INITIAL (decl) = init; goto finish_end0; @@ -8089,6 +8081,12 @@ cp_finish_decl (decl, init, asmspec_tree, flags) GNU_xref_decl (current_function_decl, decl); + /* Add this declaration to the statement-tree. */ + if (building_stmt_tree () + && at_function_scope_p () + && TREE_CODE (decl) != RESULT_DECL) + add_decl_stmt (decl); + if (TREE_CODE (decl) == VAR_DECL) layout_var_decl (decl); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d0f8c438d640..ef419bd47419 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1946,41 +1946,6 @@ defer_fn (fn) VARRAY_PUSH_TREE (deferred_fns, fn); } -/* Hand off a unique name which can be used for variable we don't really - want to know about anyway, for example, the anonymous variables which - are needed to make references work. Declare this thing so we can use it. - The variable created will be of type TYPE, and will have internal - linkage. */ - -tree -get_temp_name (type) - tree type; -{ - char buf[sizeof (AUTO_TEMP_FORMAT) + 20]; - tree decl; - int toplev = toplevel_bindings_p (); - - sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++); - decl = build_decl (VAR_DECL, get_identifier (buf), type); - DECL_ARTIFICIAL (decl) = 1; - TREE_USED (decl) = 1; - TREE_STATIC (decl) = 1; - - decl = pushdecl_top_level (decl); - - /* If this is a local variable, then lay out its rtl now. - Otherwise, callers of this function are responsible for dealing - with this variable's rtl. */ - if (! toplev) - { - expand_decl (decl); - my_friendly_assert (DECL_INITIAL (decl) == NULL_TREE, - 19990826); - } - - return decl; -} - /* Hunts through the global anonymous union ANON_DECL, building appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and returns a VAR_DECL whose size is the same as the size of the diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 2b1b00952909..6e94681e51ea 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2420,10 +2420,28 @@ mangle_guard_variable (variable) { start_mangling (); write_string ("_ZGV"); - write_name (variable, /*ignore_local_scope=*/0); + if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) + /* The name of a guard variable for a reference temporary should refer + to the reference, not the temporary. */ + write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); + else + write_name (variable, /*ignore_local_scope=*/0); return get_identifier (finish_mangling ()); } +/* Return an identifier for the name of a temporary variable used to + initialize a static reference. This isn't part of the ABI, but we might + as well call them something readable. */ + +tree +mangle_ref_init_variable (variable) + tree variable; +{ + start_mangling (); + write_string ("_ZGR"); + write_name (variable, /*ignore_local_scope=*/0); + return get_identifier (finish_mangling ()); +} /* Foreign language type mangling section. */ diff --git a/gcc/testsuite/g++.dg/README b/gcc/testsuite/g++.dg/README new file mode 100644 index 000000000000..318b819834da --- /dev/null +++ b/gcc/testsuite/g++.dg/README @@ -0,0 +1,17 @@ +Subdirectories: + +abi Tests for ABI compatibility -- mangling, object layout, etc. +eh Tests for exception handling. +ext Tests for GNU language extensions. +inherit Tests for inheritance -- virtual functions, multiple inheritance, etc. +init Tests for initialization semantics, constructors/destructors, etc. +lookup Tests for lookup semantics, namespaces, etc. +overload Tests for overload resolution and conversions. +rtti Tests for run-time type identification (typeid, dynamic_cast, etc.) +template Tests for templates. +warn Tests for compiler warnings. + +other Tests that don't fit into one of the other categories. + +special Tests that need custom expect code to run them; see special/ecos.exp + for an example. diff --git a/gcc/testsuite/g++.dg/other/init-ref1.C b/gcc/testsuite/g++.dg/init/init-ref1.C similarity index 100% rename from gcc/testsuite/g++.dg/other/init-ref1.C rename to gcc/testsuite/g++.dg/init/init-ref1.C diff --git a/gcc/testsuite/g++.dg/other/init-ref2.C b/gcc/testsuite/g++.dg/init/init-ref2.C similarity index 100% rename from gcc/testsuite/g++.dg/other/init-ref2.C rename to gcc/testsuite/g++.dg/init/init-ref2.C diff --git a/gcc/testsuite/g++.dg/overload/builtin1.C b/gcc/testsuite/g++.dg/overload/builtin1.C new file mode 100644 index 000000000000..9f66e3360651 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/builtin1.C @@ -0,0 +1,16 @@ +// Test that we don't discard builtin candidates inappropriately. + +struct B { }; + +struct A { + operator int (); + operator B (); +}; + +void operator+ (B, B); // { dg-error "" "candidate" } + +int main () +{ + A a; + a + a; // { dg-error "" "ambiguous" } +}