+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
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
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);
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 *,
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));
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--
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;
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. */
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);
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))
{
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)
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;
}
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;
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);
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
{
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 ());
+}
\f
/* Foreign language type mangling section. */
--- /dev/null
+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.
--- /dev/null
+// 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" }
+}