aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@gcc.gnu.org>2002-12-24 22:12:17 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2002-12-24 22:12:17 +0000
commitb9201622aed326ee95c8023c8bc697d8adf443ff (patch)
tree77d6b2efb9525308ac4a4185821f8c3a21401842 /gcc
parent40aa9d95e2f81b94d4eccf64d870dea3fe9e4083 (diff)
downloadgcc-b9201622aed326ee95c8023c8bc697d8adf443ff.zip
gcc-b9201622aed326ee95c8023c8bc697d8adf443ff.tar.gz
gcc-b9201622aed326ee95c8023c8bc697d8adf443ff.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/decl2.c143
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/g++.dg/lookup/decl1.C32
-rw-r--r--gcc/testsuite/g++.dg/lookup/decl2.C27
6 files changed, 155 insertions, 72 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5776e5c..921550e 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 eef5335..95680dd6 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 d305ee5..afb8693 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 7771c26..b40420e 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 0000000..d9af656
--- /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 0000000..75ce096
--- /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);
+}