Commit 44021471 by Giovanni Bajo

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
parent 7a8e07c7
......@@ -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);
......
......@@ -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
......
......@@ -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)
......
......@@ -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);
......
......@@ -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;
......
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>
......
// { 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" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment