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:
parent
ea0eceb165
commit
08ac397c04
11 changed files with 133 additions and 84 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
38
gcc/cp/cvt.c
38
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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
17
gcc/testsuite/g++.dg/README
Normal file
17
gcc/testsuite/g++.dg/README
Normal 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.
|
16
gcc/testsuite/g++.dg/overload/builtin1.C
Normal file
16
gcc/testsuite/g++.dg/overload/builtin1.C
Normal 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" }
|
||||
}
|
Loading…
Add table
Reference in a new issue