From 4402147197bea00a19741bafefe7f19eb4c8467f Mon Sep 17 00:00:00 2001 From: Giovanni Bajo Date: Mon, 3 May 2004 10:11:19 +0000 Subject: [PATCH] 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 --- gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 12 ++++++---- gcc/cp/decl2.c | 32 +++++++++++++++++++------ gcc/cp/friend.c | 5 +++- gcc/cp/pt.c | 4 ++-- gcc/testsuite/ChangeLog | 7 +++++- gcc/testsuite/g++.dg/template/member5.C | 32 +++++++++++++++++++++++++ 7 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/member5.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c3c7c868e25..37170e2ca71 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 1b788310ca3..17b625f668c 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 e094493f988..5730d369efc 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 c81bd934e0a..e55adaa8bc0 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 5d2c95ac155..96ee6875a56 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 5735a6c5548..df01d26d23e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ +2004-05-03 Giovanni Bajo + + PR c++/14389 + * g++.dg/template/member5.C: New test. + 2004-05-03 Uros Bizjak - * gcc.dg/builtins-34.c: Also check expm1*. + * gcc.dg/builtins-34.c: Also check expm1*. 2004-05-01 Kaveh R. Ghazi diff --git a/gcc/testsuite/g++.dg/template/member5.C b/gcc/testsuite/g++.dg/template/member5.C new file mode 100644 index 00000000000..45dcd6c6c66 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/member5.C @@ -0,0 +1,32 @@ +// { dg-do compile } +// Contributed by: +// 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 (); +template void S::foo (); + +} + +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" } + +} -- 2.30.2