Commit b9201622 by Nathan Sidwell

re PR c++/9053 (g++ confused about ambiguity of overloaded function templates)

cp:
        PR c++/9053
        * decl.c (duplicate_decls): Templates may be disambiguated by
        return type.

        PR c++/8702
        * decl2.c (check_classfn): Use lookup_fnfield_1. List all
        conversion operators on failure.
testsuite
        * g++.dg/lookup/decl1.C: New test.
        * g++.dg/lookup/decl2.C: New test.

From-SVN: r60482
parent 40aa9d95
2002-12-24 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9053
* decl.c (duplicate_decls): Templates may be disambiguated by
return type.
PR c++/8702
* decl2.c (check_classfn): Use lookup_fnfield_1. List all
conversion operators on failure.
2002-12-23 Gabriel Dos Reis <gdr@integrable-solutions.net> 2002-12-23 Gabriel Dos Reis <gdr@integrable-solutions.net>
* call.c (tourney, build_field_call, equal_functions, joust) * call.c (tourney, build_field_call, equal_functions, joust)
......
...@@ -3212,7 +3212,11 @@ duplicate_decls (newdecl, olddecl) ...@@ -3212,7 +3212,11 @@ duplicate_decls (newdecl, olddecl)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))), && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)))) TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl), && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl))) DECL_TEMPLATE_PARMS (olddecl))
/* Template functions can be disambiguated by
return type. */
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl))))
{ {
error ("new declaration `%#D'", newdecl); error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl); cp_error_at ("ambiguates old declaration `%#D'", olddecl);
......
...@@ -676,11 +676,7 @@ tree ...@@ -676,11 +676,7 @@ tree
check_classfn (ctype, function) check_classfn (ctype, function)
tree ctype, function; tree ctype, function;
{ {
tree fn_name = DECL_NAME (function); int ix;
tree fndecl, fndecls;
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
if (DECL_USE_TEMPLATE (function) if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL && !(TREE_CODE (function) == TEMPLATE_DECL
...@@ -697,81 +693,90 @@ check_classfn (ctype, function) ...@@ -697,81 +693,90 @@ check_classfn (ctype, function)
reason we should, either. We let our callers know we didn't reason we should, either. We let our callers know we didn't
find the method, but we don't complain. */ find the method, but we don't complain. */
return NULL_TREE; return NULL_TREE;
if (method_vec != 0) ix = lookup_fnfields_1 (complete_type (ctype),
DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
DECL_DESTRUCTOR_P (function) ? dtor_identifier :
DECL_NAME (function));
if (ix >= 0)
{ {
methods = &TREE_VEC_ELT (method_vec, 0); tree methods = CLASSTYPE_METHOD_VEC (ctype);
end = TREE_VEC_END (method_vec); tree fndecls, fndecl;
bool is_conv_op;
/* First suss out ctors and dtors. */ const char *format = NULL;
if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
&& DECL_CONSTRUCTOR_P (function)) for (fndecls = TREE_VEC_ELT (methods, ix);
goto got_it; fndecls; fndecls = OVL_NEXT (fndecls))
if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) {
&& DECL_DESTRUCTOR_P (function)) tree p1, p2;
goto got_it;
fndecl = OVL_CURRENT (fndecls);
while (++methods != end && *methods) p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
/* We cannot simply call decls_match because this doesn't
work for static member functions that are pretending to
be methods, and because the name may have been changed by
asm("new_name"). */
/* Get rid of the this parameter on functions that become
static. */
if (DECL_STATIC_FUNCTION_P (fndecl)
&& TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
p1 = TREE_CHAIN (p1);
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)))
&& compparms (p1, p2)
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
|| (DECL_TI_TEMPLATE (function)
== DECL_TI_TEMPLATE (fndecl))))
return fndecl;
}
error ("prototype for `%#D' does not match any in class `%T'",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
if (is_conv_op)
ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
fndecls = TREE_VEC_ELT (methods, ix);
while (fndecls)
{ {
fndecl = *methods; fndecl = OVL_CURRENT (fndecls);
if (fn_name == DECL_NAME (OVL_CURRENT (*methods))) fndecls = OVL_NEXT (fndecls);
if (!fndecls && is_conv_op)
{ {
got_it: if (TREE_VEC_LENGTH (methods) > ix)
for (fndecls = *methods; fndecls != NULL_TREE;
fndecls = OVL_NEXT (fndecls))
{ {
fndecl = OVL_CURRENT (fndecls); ix++;
fndecls = TREE_VEC_ELT (methods, ix);
/* We cannot simply call decls_match because this if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
doesn't work for static member functions that are
pretending to be methods, and because the name
may have been changed by asm("new_name"). */
if (DECL_NAME (function) == DECL_NAME (fndecl))
{ {
tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); fndecls = NULL_TREE;
tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); is_conv_op = false;
/* Get rid of the this parameter on functions that become
static. */
if (DECL_STATIC_FUNCTION_P (fndecl)
&& TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
p1 = TREE_CHAIN (p1);
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)))
&& compparms (p1, p2)
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
|| (DECL_TI_TEMPLATE (function)
== DECL_TI_TEMPLATE (fndecl))))
return fndecl;
} }
} }
break; /* loser */ else
is_conv_op = false;
} }
if (format)
format = " %#D";
else if (fndecls)
format = "candidates are: %#D";
else
format = "candidate is: %#D";
cp_error_at (format, fndecl);
} }
} }
else if (!COMPLETE_TYPE_P (ctype))
if (methods != end && *methods) cxx_incomplete_type_error (function, ctype);
{
tree fndecl = *methods;
error ("prototype for `%#D' does not match any in class `%T'",
function, ctype);
cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is",
OVL_CURRENT (fndecl));
while (fndecl = OVL_NEXT (fndecl), fndecl)
cp_error_at (" %#D", OVL_CURRENT(fndecl));
}
else else
{ error ("no `%#D' member function declared in class `%T'",
methods = 0; function, ctype);
if (!COMPLETE_TYPE_P (ctype))
cxx_incomplete_type_error (function, ctype);
else
error ("no `%#D' member function declared in class `%T'",
function, ctype);
}
/* If we did not find the method in the class, add it to avoid /* If we did not find the method in the class, add it to avoid
spurious errors (unless the CTYPE is not yet defined, in which spurious errors (unless the CTYPE is not yet defined, in which
......
2002-12-24 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/lookup/decl1.C: New test.
* g++.dg/lookup/decl2.C: New test.
2002-12-24 Joseph S. Myers <jsm@polyomino.org.uk> 2002-12-24 Joseph S. Myers <jsm@polyomino.org.uk>
* g++.dg/init/new1.C, g++.dg/template/alignof1.C, * g++.dg/init/new1.C, g++.dg/template/alignof1.C,
...@@ -12,9 +17,9 @@ ...@@ -12,9 +17,9 @@
2002-12-23 Mark Mitchell <mark@codesourcery.com> 2002-12-23 Mark Mitchell <mark@codesourcery.com>
* testsuite/gcc.dg/i386-bitfield3.c: New test. * gcc.dg/i386-bitfield3.c: New test.
* testsuite/gcc.dg/i386-bitfield2.c: New test. * gcc.dg/i386-bitfield2.c: New test.
2002-12-22 Nathan Sidwell <nathan@codesourcery.com> 2002-12-22 Nathan Sidwell <nathan@codesourcery.com>
......
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 24 Dec 2002 <nathan@codesourcery.com>
// PR 8702. Failure to match templates.
template <typename X> struct C1{};
template <typename X>
struct C2 {
template<typename Y> operator C1<Y>();
template<typename Y> operator C2<Y>();
};
template<typename X> template<typename Y>
C2<X>::operator C1<Y>()
{
return C1<Y>();
}
struct A
{
operator int (); // { dg-error "operator" "" }
operator float (); // { dg-error "operator" "" }
operator float () const; // { dg-error "operator" "" }
template <typename T> operator T * (); // { dg-error "candidates" "" }
};
A::operator short () { // { dg-error "prototype for" "" }
return 0;
}
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 24 Dec 2002 <nathan@codesourcery.com>
// Source Martin Buchholz martin@xemacs.org
// PR 9053. Failed to consider templates that are disambiguated by
// return type.
template <typename T> class bar;
template <> struct bar<const char*> { typedef void type; };
template <typename T> class qux;
template <> struct qux<int> { typedef void type; };
template <typename T>
typename bar<T>::type foo (T t) { }
template <typename T>
typename qux<T>::type foo (T t) { }
int
main (int argc, char *argv[])
{
foo ("foo");
foo (7);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment