From a81e6834521e5e1a4e0ac2abd16d8e6ae483c7aa Mon Sep 17 00:00:00 2001 From: nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Tue, 24 Dec 2002 22:12:17 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60482 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 10 ++ gcc/cp/decl.c | 6 +- gcc/cp/decl2.c | 143 ++++++++++++++-------------- gcc/testsuite/ChangeLog | 9 +- gcc/testsuite/g++.dg/lookup/decl1.C | 32 +++++++ gcc/testsuite/g++.dg/lookup/decl2.C | 27 ++++++ 6 files changed, 155 insertions(+), 72 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/decl1.C create mode 100644 gcc/testsuite/g++.dg/lookup/decl2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5776e5c470e3..921550ed4b2f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index eef5335fb5fe..95680dd60fa1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d305ee5813e5..afb8693a6b73 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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)) + { + 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 = *methods; - if (fn_name == DECL_NAME (OVL_CURRENT (*methods))) + 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7771c26a1d51..b40420e24c3d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> diff --git a/gcc/testsuite/g++.dg/lookup/decl1.C b/gcc/testsuite/g++.dg/lookup/decl1.C new file mode 100644 index 000000000000..d9af65604cb2 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/decl1.C @@ -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; +} diff --git a/gcc/testsuite/g++.dg/lookup/decl2.C b/gcc/testsuite/g++.dg/lookup/decl2.C new file mode 100644 index 000000000000..75ce0967a4b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/decl2.C @@ -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); +} -- GitLab