call.c (joust): Only prefer a non-builtin candidate to a builtin one if...

* 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.

From-SVN: r44358
This commit is contained in:
Jason Merrill 2001-07-25 11:04:32 -04:00 committed by Jason Merrill
parent ea0eceb165
commit 08ac397c04
11 changed files with 133 additions and 84 deletions

View file

@ -1,3 +1,19 @@
2001-07-25 Jason Merrill <jason_merrill@redhat.com>
* 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 <nathan@codesourcery.com>
PR c++/3416

View file

@ -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);

View file

@ -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));

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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. */

View file

@ -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.

View file

@ -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" }
}