diff options
author | Giovanni Bajo <giovannibajo@gcc.gnu.org> | 2004-05-03 10:11:19 +0000 |
---|---|---|
committer | Giovanni Bajo <giovannibajo@gcc.gnu.org> | 2004-05-03 10:11:19 +0000 |
commit | 4402147197bea00a19741bafefe7f19eb4c8467f (patch) | |
tree | d0cc887d089f42e5c3dd6d1a442b14113df99313 /gcc | |
parent | 7a8e07c7d1bc8526e0d67cb7ae0dc51ba5b90f68 (diff) | |
download | gcc-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.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 12 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 32 | ||||
-rw-r--r-- | gcc/cp/friend.c | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/member5.C | 32 |
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" } + +} |