aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/call.c358
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb43.C2
4 files changed, 160 insertions, 215 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 58a57e0..5c8ff3a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2010-05-12 Jason Merrill <jason@redhat.com>
+
+ * call.c (add_candidates): Add first_arg and return_type parms.
+ Add special constructor/conversion op handling.
+ (convert_class_to_reference): Use it.
+ (build_user_type_conversion_1): Likewise.
+ (build_op_call): Likewise.
+ (build_new_method_call): Likewise.
+ (build_new_op): Adjust.
+ (perform_overload_resolution): Adjust.
+
2010-05-11 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/34272
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d74eb19..17ad99e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -197,8 +197,8 @@ static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
static tree prep_operand (tree);
-static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
- int, struct z_candidate **);
+static void add_candidates (tree, tree, const VEC(tree,gc) *, tree, tree, bool,
+ tree, tree, int, struct z_candidate **);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
static tree build_temp (tree, tree, int, diagnostic_t *);
@@ -1056,57 +1056,28 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags)
for (; conversions; conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
+ tree binfo = TREE_PURPOSE (conversions);
+ struct z_candidate *old_candidates = candidates;;
- for (; fns; fns = OVL_NEXT (fns))
+ add_candidates (fns, first_arg, NULL, reference_type,
+ NULL_TREE, false,
+ binfo, TYPE_BINFO (s),
+ flags, &candidates);
+
+ for (cand = candidates; cand != old_candidates; cand = cand->next)
{
- tree f = OVL_CURRENT (fns);
+ /* Now, see if the conversion function really returns
+ an lvalue of the appropriate type. From the
+ point of view of unification, simply returning an
+ rvalue of the right type is good enough. */
+ tree f = cand->fn;
tree t2 = TREE_TYPE (TREE_TYPE (f));
-
- if (DECL_NONCONVERTING_P (f)
- && (flags & LOOKUP_ONLYCONVERTING))
- continue;
-
- cand = NULL;
-
- /* If this is a template function, try to get an exact
- match. */
- if (TREE_CODE (f) == TEMPLATE_DECL)
+ if (TREE_CODE (t2) != REFERENCE_TYPE
+ || !reference_compatible_p (t, TREE_TYPE (t2)))
{
- cand = add_template_candidate (&candidates,
- f, s,
- NULL_TREE,
- first_arg,
- NULL,
- reference_type,
- TYPE_BINFO (s),
- TREE_PURPOSE (conversions),
- LOOKUP_NORMAL,
- DEDUCE_CONV);
-
- if (cand)
- {
- /* Now, see if the conversion function really returns
- an lvalue of the appropriate type. From the
- point of view of unification, simply returning an
- rvalue of the right type is good enough. */
- f = cand->fn;
- t2 = TREE_TYPE (TREE_TYPE (f));
- if (TREE_CODE (t2) != REFERENCE_TYPE
- || !reference_compatible_p (t, TREE_TYPE (t2)))
- {
- candidates = candidates->next;
- cand = NULL;
- }
- }
+ cand->viable = 0;
}
- else if (TREE_CODE (t2) == REFERENCE_TYPE
- && reference_compatible_p (t, TREE_TYPE (t2)))
- cand = add_function_candidate (&candidates, f, s, first_arg,
- NULL, TYPE_BINFO (s),
- TREE_PURPOSE (conversions),
- LOOKUP_NORMAL);
-
- if (cand)
+ else
{
conversion *identity_conv;
/* Build a standard conversion sequence indicating the
@@ -2874,6 +2845,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
candidates = 0;
flags |= LOOKUP_NO_CONVERSION;
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ flags |= LOOKUP_NO_NARROWING;
/* It's OK to bind a temporary for converting constructor arguments, but
not in converting the return value of a conversion operator. */
@@ -2882,18 +2855,25 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (ctors)
{
+ int ctorflags = flags;
ctors = BASELINK_FUNCTIONS (ctors);
first_arg = build_int_cst (build_pointer_type (totype), 0);
- if (BRACE_ENCLOSED_INITIALIZER_P (expr)
- && !TYPE_HAS_LIST_CTOR (totype))
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
- args = ctor_to_vec (expr);
- /* We still allow more conversions within an init-list. */
- flags = ((flags & ~LOOKUP_NO_CONVERSION)
- /* But not for the copy ctor. */
- |LOOKUP_NO_COPY_CTOR_CONVERSION
- |LOOKUP_NO_NARROWING);
+ /* For list-initialization we consider explicit constructors, but
+ give an error if one is selected. */
+ ctorflags &= ~LOOKUP_ONLYCONVERTING;
+ if (TYPE_HAS_LIST_CTOR (totype))
+ args = make_tree_vector_single (expr);
+ else
+ {
+ args = ctor_to_vec (expr);
+ /* We still allow more conversions within an init-list. */
+ ctorflags &= ~LOOKUP_NO_CONVERSION;
+ /* But not for the copy ctor. */
+ ctorflags |= LOOKUP_NO_COPY_CTOR_CONVERSION;
+ }
}
else
args = make_tree_vector_single (expr);
@@ -2902,28 +2882,12 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
from here. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
- }
- for (; ctors; ctors = OVL_NEXT (ctors))
- {
- tree ctor = OVL_CURRENT (ctors);
- if (DECL_NONCONVERTING_P (ctor)
- && !BRACE_ENCLOSED_INITIALIZER_P (expr))
- continue;
- if (TREE_CODE (ctor) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, ctor, totype,
- NULL_TREE, first_arg, args, NULL_TREE,
- TYPE_BINFO (totype),
- TYPE_BINFO (totype),
- flags,
- DEDUCE_CALL);
- else
- cand = add_function_candidate (&candidates, ctor, totype,
- first_arg, args, TYPE_BINFO (totype),
- TYPE_BINFO (totype),
- flags);
+ add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
+ TYPE_BINFO (totype), TYPE_BINFO (totype),
+ ctorflags, &candidates);
- if (cand)
+ for (cand = candidates; cand; cand = cand->next)
{
cand->second_conv = build_identity_conv (totype, NULL_TREE);
@@ -2947,8 +2911,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
{
- tree fns;
tree conversion_path = TREE_PURPOSE (conv_fns);
+ struct z_candidate *old_candidates;
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
@@ -2957,65 +2921,40 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
- for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns))
+ old_candidates = candidates;
+ add_candidates (TREE_VALUE (conv_fns), first_arg, NULL, totype,
+ NULL_TREE, false,
+ conversion_path, TYPE_BINFO (fromtype),
+ flags, &candidates);
+
+ for (cand = candidates; cand != old_candidates; cand = cand->next)
{
- tree fn = OVL_CURRENT (fns);
-
- if (DECL_NONCONVERTING_P (fn)
- && (flags & LOOKUP_ONLYCONVERTING))
- continue;
-
- /* [over.match.funcs] For conversion functions, the function
- is considered to be a member of the class of the implicit
- object argument for the purpose of defining the type of
- the implicit object parameter.
-
- So we pass fromtype as CTYPE to add_*_candidate. */
-
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, fn, fromtype,
- NULL_TREE,
- first_arg, NULL, totype,
- TYPE_BINFO (fromtype),
- conversion_path,
- flags,
- DEDUCE_CONV);
- else
- cand = add_function_candidate (&candidates, fn, fromtype,
- first_arg, NULL,
- TYPE_BINFO (fromtype),
- conversion_path,
- flags);
+ conversion *ics
+ = implicit_conversion (totype,
+ TREE_TYPE (TREE_TYPE (cand->fn)),
+ 0,
+ /*c_cast_p=*/false, convflags);
- if (cand)
- {
- conversion *ics
- = implicit_conversion (totype,
- TREE_TYPE (TREE_TYPE (cand->fn)),
- 0,
- /*c_cast_p=*/false, convflags);
-
- /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
- copy-initialization. In that case, "The result of the
- call is then used to direct-initialize the object that is
- the destination of the copy-initialization." [dcl.init]
-
- We represent this in the conversion sequence with an
- rvalue conversion, which means a constructor call. But
- don't add a second rvalue conversion if there's already
- one there. Which there really shouldn't be, but it's
- harmless since we'd add it here anyway. */
- if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
- && !(convflags & LOOKUP_NO_TEMP_BIND))
- ics = build_conv (ck_rvalue, totype, ics);
-
- cand->second_conv = ics;
-
- if (!ics)
- cand->viable = 0;
- else if (candidates->viable == 1 && ics->bad_p)
- cand->viable = -1;
- }
+ /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
+ copy-initialization. In that case, "The result of the
+ call is then used to direct-initialize the object that is
+ the destination of the copy-initialization." [dcl.init]
+
+ We represent this in the conversion sequence with an
+ rvalue conversion, which means a constructor call. But
+ don't add a second rvalue conversion if there's already
+ one there. Which there really shouldn't be, but it's
+ harmless since we'd add it here anyway. */
+ if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
+ && !(convflags & LOOKUP_NO_TEMP_BIND))
+ ics = build_conv (ck_rvalue, totype, ics);
+
+ cand->second_conv = ics;
+
+ if (!ics)
+ cand->viable = 0;
+ else if (cand->viable == 1 && ics->bad_p)
+ cand->viable = -1;
}
}
@@ -3145,7 +3084,8 @@ perform_overload_resolution (tree fn,
}
/* Add the various candidate functions. */
- add_candidates (fn, args, explicit_targs, template_only,
+ add_candidates (fn, NULL_TREE, args, NULL_TREE,
+ explicit_targs, template_only,
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE,
LOOKUP_NORMAL,
@@ -3383,24 +3323,13 @@ build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
if (fns)
{
- tree base = BINFO_TYPE (BASELINK_BINFO (fns));
first_mem_arg = build_this (obj);
- for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
-
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- add_template_candidate (&candidates, fn, base, NULL_TREE,
- first_mem_arg, *args, NULL_TREE,
- TYPE_BINFO (type),
- TYPE_BINFO (type),
- LOOKUP_NORMAL, DEDUCE_CALL);
- else
- add_function_candidate
- (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
- TYPE_BINFO (type), LOOKUP_NORMAL);
- }
+ add_candidates (BASELINK_FUNCTIONS (fns),
+ first_mem_arg, *args, NULL_TREE,
+ NULL_TREE, false,
+ BASELINK_BINFO (fns), BASELINK_ACCESS_BINFO (fns),
+ LOOKUP_NORMAL, &candidates);
}
convs = lookup_conversions (type, /*lookup_template_convs_p=*/true);
@@ -4058,53 +3987,86 @@ prep_operand (tree operand)
/* Add each of the viable functions in FNS (a FUNCTION_DECL or
OVERLOAD) to the CANDIDATES, returning an updated list of
- CANDIDATES. The ARGS are the arguments provided to the call,
- without any implicit object parameter. This may change ARGS. The
+ CANDIDATES. The ARGS are the arguments provided to the call;
+ if FIRST_ARG is non-null it is the implicit object argument,
+ otherwise the first element of ARGS is used if needed. The
EXPLICIT_TARGS are explicit template arguments provided.
TEMPLATE_ONLY is true if only template functions should be
considered. CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for
add_function_candidate. */
static void
-add_candidates (tree fns, const VEC(tree,gc) *args,
+add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
+ tree return_type,
tree explicit_targs, bool template_only,
tree conversion_path, tree access_path,
int flags,
struct z_candidate **candidates)
{
tree ctype;
- VEC(tree,gc) *non_static_args;
- tree first_arg;
+ const VEC(tree,gc) *non_static_args;
+ bool check_converting;
+ unification_kind_t strict;
+ tree fn;
+
+ if (!fns)
+ return;
+
+ /* Precalculate special handling of constructors and conversion ops. */
+ fn = OVL_CURRENT (fns);
+ if (DECL_CONV_FN_P (fn))
+ {
+ check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ strict = DEDUCE_CONV;
+ /* [over.match.funcs] For conversion functions, the function
+ is considered to be a member of the class of the implicit
+ object argument for the purpose of defining the type of
+ the implicit object parameter. */
+ ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (first_arg)));
+ }
+ else
+ {
+ if (DECL_CONSTRUCTOR_P (fn))
+ check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ else
+ check_converting = false;
+ strict = DEDUCE_CALL;
+ ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
+ }
- ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
- /* Delay creating the implicit this parameter until it is needed. */
- non_static_args = NULL;
- first_arg = NULL_TREE;
+ if (first_arg)
+ non_static_args = args;
+ else
+ /* Delay creating the implicit this parameter until it is needed. */
+ non_static_args = NULL;
- while (fns)
+ for (; fns; fns = OVL_NEXT (fns))
{
- tree fn;
tree fn_first_arg;
const VEC(tree,gc) *fn_args;
fn = OVL_CURRENT (fns);
+
+ if (check_converting && DECL_NONCONVERTING_P (fn))
+ continue;
+
/* Figure out which set of arguments to use. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
{
- /* If this function is a non-static member, prepend the implicit
- object parameter. */
- if (non_static_args == NULL)
+ /* If this function is a non-static member and we didn't get an
+ implicit object argument, move it out of args. */
+ if (first_arg == NULL_TREE)
{
unsigned int ix;
tree arg;
-
- non_static_args = VEC_alloc (tree, gc,
- VEC_length (tree, args) - 1);
+ VEC(tree,gc) *tempvec
+ = VEC_alloc (tree, gc, VEC_length (tree, args) - 1);
for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix)
- VEC_quick_push (tree, non_static_args, arg);
+ VEC_quick_push (tree, tempvec, arg);
+ non_static_args = tempvec;
+ first_arg = build_this (VEC_index (tree, args, 0));
}
- if (first_arg == NULL_TREE)
- first_arg = build_this (VEC_index (tree, args, 0));
+
fn_first_arg = first_arg;
fn_args = non_static_args;
}
@@ -4122,11 +4084,11 @@ add_candidates (tree fns, const VEC(tree,gc) *args,
explicit_targs,
fn_first_arg,
fn_args,
- NULL_TREE,
+ return_type,
access_path,
conversion_path,
flags,
- DEDUCE_CALL);
+ strict);
else if (!template_only)
add_function_candidate (candidates,
fn,
@@ -4136,7 +4098,6 @@ add_candidates (tree fns, const VEC(tree,gc) *args,
access_path,
conversion_path,
flags);
- fns = OVL_NEXT (fns);
}
}
@@ -4247,7 +4208,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
/* Add namespace-scope operators to the list of functions to
consider. */
add_candidates (lookup_function_nonclass (fnname, arglist, /*block_p=*/true),
- arglist, NULL_TREE, false, NULL_TREE, NULL_TREE,
+ NULL_TREE, arglist, NULL_TREE,
+ NULL_TREE, false, NULL_TREE, NULL_TREE,
flags, &candidates);
/* Add class-member operators to the candidate set. */
if (CLASS_TYPE_P (TREE_TYPE (arg1)))
@@ -4261,10 +4223,11 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
goto user_defined_result_ready;
}
if (fns)
- add_candidates (BASELINK_FUNCTIONS (fns), arglist,
+ add_candidates (BASELINK_FUNCTIONS (fns),
+ NULL_TREE, arglist, NULL_TREE,
NULL_TREE, false,
BASELINK_BINFO (fns),
- TYPE_BINFO (TREE_TYPE (arg1)),
+ BASELINK_ACCESS_BINFO (fns),
flags, &candidates);
}
@@ -6210,7 +6173,6 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
VEC(tree,gc) *user_args;
tree call;
tree fn;
- tree class_type;
int template_only = 0;
bool any_viable_p;
tree orig_instance;
@@ -6340,48 +6302,14 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
*args = ctor_to_vec (VEC_index (tree, *args, 0));
}
- class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
first_mem_arg = instance_ptr;
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
- for (fn = fns; fn; fn = OVL_NEXT (fn))
- {
- tree t = OVL_CURRENT (fn);
- tree this_first_arg;
-
- /* We can end up here for copy-init of same or base class. */
- if ((flags & LOOKUP_ONLYCONVERTING)
- && DECL_NONCONVERTING_P (t))
- continue;
-
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
- this_first_arg = first_mem_arg;
- else
- this_first_arg = NULL_TREE;
-
- if (TREE_CODE (t) == TEMPLATE_DECL)
- /* A member template. */
- add_template_candidate (&candidates, t,
- class_type,
- explicit_targs,
- this_first_arg,
- args == NULL ? NULL : *args,
- optype,
- access_binfo,
- conversion_path,
- flags,
- DEDUCE_CALL);
- else if (! template_only)
- add_function_candidate (&candidates, t,
- class_type,
- this_first_arg,
- args == NULL ? NULL : *args,
- access_binfo,
- conversion_path,
- flags);
- }
+ add_candidates (fns, first_mem_arg, args ? *args : NULL, optype,
+ explicit_targs, template_only, conversion_path,
+ access_binfo, flags, &candidates);
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e5f3a50..6425c9e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-05-12 Jason Merrill <jason@redhat.com>
+
+ * g++.old-deja/g++.robertl/eb43.C: Prune "candidates" messages.
+
2010-05-12 H.J. Lu <hongjiu.lu@intel.com>
PR target/44088
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C
index 5355afe..1dc4328 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C
@@ -4,6 +4,8 @@
// The first one should still fail because it requires an implicit conversion
// to pointer_to_binary_function, which has an `explicit' constructor.
+// { dg-prune-output "note" }
+
#include <vector>
#include <algorithm>
#include <functional>