aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-05-03 10:11:19 +0000
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-05-03 10:11:19 +0000
commit4402147197bea00a19741bafefe7f19eb4c8467f (patch)
treed0cc887d089f42e5c3dd6d1a442b14113df99313 /gcc
parent7a8e07c7d1bc8526e0d67cb7ae0dc51ba5b90f68 (diff)
downloadgcc-4402147197bea00a19741bafefe7f19eb4c8467f.zip
gcc-4402147197bea00a19741bafefe7f19eb4c8467f.tar.gz
gcc-4402147197bea00a19741bafefe7f19eb4c8467f.tar.bz2
re PR c++/14389 (Out-of-line of overloaded template rejected)
PR c++/14389 * decl2.c (check_classfn): For member templates, compare also the template parameters to match the declaration. * cp-tree.h: Adjust declaration of check_classfn. * decl.c (start_decl, grokfndecl): Adjust callers of check_classfn. * friend.c (do_friend): Likewise. * pt.c (tsubst_friend_function): Likewise. PR c++/14389 * g++.dg/template/member5.C: New test. From-SVN: r81426
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/decl2.c32
-rw-r--r--gcc/cp/friend.c5
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/template/member5.C32
7 files changed, 78 insertions, 16 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c3c7c86..37170e2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3721,7 +3721,7 @@ extern void maybe_make_one_only (tree);
extern void grokclassfn (tree, tree, enum overload_flags, tree);
extern tree grok_array_decl (tree, tree);
extern tree delete_sanity (tree, tree, bool, int);
-extern tree check_classfn (tree, tree, bool);
+extern tree check_classfn (tree, tree, tree);
extern void check_member_template (tree);
extern tree grokfield (tree, tree, tree, tree, tree);
extern tree grokbitfield (tree, tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1b78831..17b625f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3727,8 +3727,10 @@ start_decl (tree declarator,
else
{
tree field = check_classfn (context, decl,
- processing_template_decl
- > template_class_depth (context));
+ (processing_template_decl
+ > template_class_depth (context))
+ ? current_template_parms
+ : NULL_TREE);
if (field && duplicate_decls (decl, field))
decl = field;
}
@@ -5691,8 +5693,10 @@ grokfndecl (tree ctype,
tree old_decl;
old_decl = check_classfn (ctype, decl,
- processing_template_decl
- > template_class_depth (ctype));
+ (processing_template_decl
+ > template_class_depth (ctype))
+ ? current_template_parms
+ : NULL_TREE);
if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
/* Because grokfndecl is always supposed to return a
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index e094493..5730d36 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -612,15 +612,19 @@ check_java_method (tree method)
/* Sanity check: report error if this function FUNCTION is not
really a member of the class (CTYPE) it is supposed to belong to.
- CNAME is the same here as it is for grokclassfn above.
- TEMPLATE_HEADER_P is true when this declaration comes with a
- template header. */
+ TEMPLATE_PARMS is used to specifiy the template parameters of a member
+ template passed as FUNCTION_DECL. If the member template is passed as a
+ TEMPLATE_DECL, it can be NULL since the parameters can be extracted
+ from the declaration. If the function is not a function template, it
+ must be NULL.
+ It returns the original declaration for the function, or NULL_TREE
+ if no declaration was found (and an error was emitted). */
tree
-check_classfn (tree ctype, tree function, bool template_header_p)
+check_classfn (tree ctype, tree function, tree template_parms)
{
int ix;
- int is_template;
+ bool is_template;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
@@ -638,9 +642,20 @@ check_classfn (tree ctype, tree function, bool template_header_p)
find the method, but we don't complain. */
return NULL_TREE;
+ /* Basic sanity check: for a template function, the template parameters
+ either were not passed, or they are the same of DECL_TEMPLATE_PARMS. */
+ if (TREE_CODE (function) == TEMPLATE_DECL)
+ {
+ my_friendly_assert (!template_parms
+ || comp_template_parms
+ (template_parms,
+ DECL_TEMPLATE_PARMS (function)),
+ 20040303);
+ template_parms = DECL_TEMPLATE_PARMS (function);
+ }
+
/* OK, is this a definition of a member template? */
- is_template = (TREE_CODE (function) == TEMPLATE_DECL
- || template_header_p);
+ is_template = (template_parms != NULL_TREE);
ix = lookup_fnfields_1 (complete_type (ctype),
DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
@@ -684,6 +699,9 @@ check_classfn (tree ctype, tree function, bool template_header_p)
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)))
&& compparms (p1, p2)
+ && (!is_template
+ || comp_template_parms (template_parms,
+ DECL_TEMPLATE_PARMS (fndecl)))
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index c81bd93..e55adaa 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -397,7 +397,10 @@ do_friend (tree ctype, tree declarator, tree decl,
validity of the declaration later. */
decl = push_template_decl_real (decl, /*is_friend=*/1);
else
- decl = check_classfn (ctype, decl, template_member_p);
+ decl = check_classfn (ctype, decl,
+ template_member_p
+ ? current_template_parms
+ : NULL_TREE);
if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL)
decl = DECL_TI_TEMPLATE (decl);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5d2c95a..96ee687 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5142,8 +5142,8 @@ tsubst_friend_function (tree decl, tree args)
{
/* Check to see that the declaration is really present, and,
possibly obtain an improved declaration. */
- tree fn = check_classfn (DECL_CONTEXT (new_friend),
- new_friend, false);
+ tree fn = check_classfn (DECL_CONTEXT (new_friend),
+ new_friend, NULL_TREE);
if (fn)
new_friend = fn;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5735a6c..df01d26 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,11 @@
+2004-05-03 Giovanni Bajo <giovannibajo@gcc.gnu.org>
+
+ PR c++/14389
+ * g++.dg/template/member5.C: New test.
+
2004-05-03 Uros Bizjak <uros@kss-loka.si>
- * gcc.dg/builtins-34.c: Also check expm1*.
+ * gcc.dg/builtins-34.c: Also check expm1*.
2004-05-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
diff --git a/gcc/testsuite/g++.dg/template/member5.C b/gcc/testsuite/g++.dg/template/member5.C
new file mode 100644
index 0000000..45dcd6c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/member5.C
@@ -0,0 +1,32 @@
+// { dg-do compile }
+// Contributed by: <fasbjx at free dot fr>
+// PR c++/14389: Disambiguate overloaded member templates which differ only
+// in the template argument list.
+
+namespace N1 {
+
+struct S {
+ template< typename B, typename A > void foo();
+ template< typename A > void foo();
+};
+
+template< typename A > void S::foo() {}
+template< typename B, typename A > void S::foo() {}
+
+template void S::foo<void> ();
+template void S::foo<void,void> ();
+
+}
+
+namespace N2 {
+
+struct S {
+ template< typename _A > void foo();
+ template< int _i > void foo();
+};
+
+template< typename _A > void S::foo() {}
+
+template void S::foo< 0 >(); // { dg-error "no definition available|instantiated from here" }
+
+}