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
This commit is contained in:
Nathan Sidwell 2002-12-24 22:12:17 +00:00
parent 40aa9d95e2
commit b9201622ae
6 changed files with 155 additions and 72 deletions

View File

@ -1,3 +1,13 @@
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>
* call.c (tourney, build_field_call, equal_functions, joust)

View File

@ -3212,7 +3212,11 @@ duplicate_decls (newdecl, olddecl)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (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);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);

View File

@ -676,11 +676,7 @@ tree
check_classfn (ctype, function)
tree ctype, function;
{
tree fn_name = DECL_NAME (function);
tree fndecl, fndecls;
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
int ix;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
@ -697,81 +693,90 @@ check_classfn (ctype, function)
reason we should, either. We let our callers know we didn't
find the method, but we don't complain. */
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);
end = TREE_VEC_END (method_vec);
/* First suss out ctors and dtors. */
if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
&& DECL_CONSTRUCTOR_P (function))
goto got_it;
if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
&& DECL_DESTRUCTOR_P (function))
goto got_it;
while (++methods != end && *methods)
tree methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl;
bool is_conv_op;
const char *format = NULL;
for (fndecls = TREE_VEC_ELT (methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
fndecl = *methods;
if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
tree p1, p2;
fndecl = OVL_CURRENT (fndecls);
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 = OVL_CURRENT (fndecls);
fndecls = OVL_NEXT (fndecls);
if (!fndecls && is_conv_op)
{
got_it:
for (fndecls = *methods; fndecls != NULL_TREE;
fndecls = OVL_NEXT (fndecls))
if (TREE_VEC_LENGTH (methods) > ix)
{
fndecl = OVL_CURRENT (fndecls);
/* 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"). */
if (DECL_NAME (function) == DECL_NAME (fndecl))
ix++;
fndecls = TREE_VEC_ELT (methods, ix);
if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
{
tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
/* 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;
fndecls = NULL_TREE;
is_conv_op = false;
}
}
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);
}
}
if (methods != end && *methods)
{
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 if (!COMPLETE_TYPE_P (ctype))
cxx_incomplete_type_error (function, ctype);
else
{
methods = 0;
if (!COMPLETE_TYPE_P (ctype))
cxx_incomplete_type_error (function, ctype);
else
error ("no `%#D' member function declared in class `%T'",
function, ctype);
}
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
spurious errors (unless the CTYPE is not yet defined, in which

View File

@ -1,3 +1,8 @@
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>
* g++.dg/init/new1.C, g++.dg/template/alignof1.C,
@ -12,9 +17,9 @@
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>

View File

@ -0,0 +1,32 @@
// { 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;
}

View File

@ -0,0 +1,27 @@
// { 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);
}