diff options
| author | giovannibajo <giovannibajo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-07-21 00:06:45 +0000 | 
|---|---|---|
| committer | giovannibajo <giovannibajo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-07-21 00:06:45 +0000 | 
| commit | 05a677c71ece39cae12ce541570b6cd3ffab0a5c (patch) | |
| tree | 1312c53d8cf381419e2804cabd75d2dfe5541a6a /gcc | |
| parent | d6f7df3a44d2d1a43b2128558157e26b8282d835 (diff) | |
| download | ppe42-gcc-05a677c71ece39cae12ce541570b6cd3ffab0a5c.tar.gz ppe42-gcc-05a677c71ece39cae12ce541570b6cd3ffab0a5c.zip | |
	PR c++/509
	* pt.c (determine_specialization): New parameter template_count.
	Disambiguate between member templates and member functions counting
	the template headers.
	(check_explicit_specialization): Update caller.
	(tsubst_friend_function): Likewise.
	PR c++/509
	* g++.dg/template/spec15.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84982 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
| -rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
| -rw-r--r-- | gcc/cp/pt.c | 54 | ||||
| -rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
| -rw-r--r-- | gcc/testsuite/g++.dg/template/spec15.C | 34 | 
4 files changed, 98 insertions, 4 deletions
| diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3038907545c..5883b7e26de 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2004-07-21  Giovanni Bajo  <giovannibajo@gcc.gnu.org> + +	PR c++/509 +	* pt.c (determine_specialization): New parameter template_count. +	Disambiguate between member templates and member functions counting +	the template headers. +	(check_explicit_specialization): Update caller. +	(tsubst_friend_function): Likewise. +  2004-07-20  Steven Bosscher  <stevenb@suse.de>  	* cp-tree.def (TINST_LEVEL): Make it an 'x' node. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 86f945e7f8f..3971b6d37d2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -155,7 +155,7 @@ static int verify_class_unification (tree, tree, tree);  static tree try_class_unification (tree, tree, tree, tree);  static int coerce_template_template_parms (tree, tree, tsubst_flags_t,  					   tree, tree); -static tree determine_specialization (tree, tree, tree *, int); +static tree determine_specialization (tree, tree, tree *, int, int);  static int template_args_equal (tree, tree);  static void tsubst_default_arguments (tree);  static tree for_each_template_parm_r (tree *, int *, void *); @@ -1205,6 +1205,10 @@ print_candidates (tree fns)     If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a     specialization of a member template. +   The TEMPLATE_COUNT is the number of references to qualifying +   template classes that appeared in the name of the function. See +   check_explicit_specialization for a more accurate description. +     The template args (those explicitly specified and those deduced)     are output in a newly created vector *TARGS_OUT. @@ -1215,13 +1219,16 @@ static tree  determine_specialization (tree template_id,                             tree decl,                             tree* targs_out,  -			  int need_member_template) +			  int need_member_template, +			  int template_count)  {    tree fns;    tree targs;    tree explicit_targs;    tree candidates = NULL_TREE;    tree templates = NULL_TREE; +  int header_count; +  struct cp_binding_level *b;    *targs_out = NULL_TREE; @@ -1244,6 +1251,14 @@ determine_specialization (tree template_id,        return error_mark_node;      } +  /* Count the number of template headers specified for this +     specialization.  */ +  header_count = 0; +  for (b = current_binding_level; +       b->kind == sk_template_parms || b->kind == sk_template_spec; +       b = b->level_chain) +    ++header_count; +    for (; fns; fns = OVL_NEXT (fns))      {        tree fn = OVL_CURRENT (fns); @@ -1280,6 +1295,35 @@ determine_specialization (tree template_id,  			       TREE_VALUE (decl_arg_types)))  	    continue; +	  /* In case of explicit specialization, we need to check if +	     the number of template headers appearing in the specialization +	     is correct. This is usually done in check_explicit_specialization, +	     but the check done there cannot be exhaustive when specializing +	     member functions. Consider the following code: + +	     template <> void A<int>::f(int); +	     template <> template <> void A<int>::f(int); + +	     Assuming that A<int> is not itself an explicit specialization +	     already, the first line specializes "f" which is a non-template +	     member function, whilst the second line specializes "f" which +	     is a template member function. So both lines are syntactically +	     correct, and check_explicit_specialization does not reject +	     them. +	      +	     Here, we can do better, as we are matching the specialization +	     against the declarations. We count the number of template +	     headers, and we check if they match TEMPLATE_COUNT + 1 +	     (TEMPLATE_COUNT is the number of qualifying template classes, +	     plus there must be another header for the member template +	     itself). +	      +	     Notice that if header_count is zero, this is not a +	     specialization but rather a template instantiation, so there +	     is no check we can perform here.  */ +	  if (header_count && header_count != template_count + 1) +	    continue; +  	  /* See whether this function might be a specialization of this  	     template.  */  	  targs = get_bindings (fn, decl, explicit_targs); @@ -1872,7 +1916,8 @@ check_explicit_specialization (tree declarator,  	 declaration.  */        tmpl = determine_specialization (declarator, decl,  				       &targs,  -				       member_specialization); +				       member_specialization, +				       template_count);        if (!tmpl || tmpl == error_mark_node)  	/* We couldn't figure out what this declaration was @@ -4980,7 +5025,8 @@ tsubst_friend_function (tree decl, tree args)        new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);        tmpl = determine_specialization (template_id, new_friend,  				       &new_args,  -				       /*need_member_template=*/0); +				       /*need_member_template=*/0, +				       TREE_VEC_LENGTH (args));        new_friend = instantiate_template (tmpl, new_args, tf_error);        goto done;      } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 39601decd15..b939e330a34 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-07-21  Giovanni Bajo  <giovannibajo@gcc.gnu.org> + +	PR c++/509 +	* g++.dg/template/spec15.C: New test. +  2004-07-21  David Billinghurst (David.Billinghurst@riotinto.com)  	Copy cases from g77.f-torture/execute and add dg-run diff --git a/gcc/testsuite/g++.dg/template/spec15.C b/gcc/testsuite/g++.dg/template/spec15.C new file mode 100644 index 00000000000..fcf4ecb904d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec15.C @@ -0,0 +1,34 @@ +// { dg-do compile } +// Contributed by Wolfgang Bangerth <bangerth at ticam dot utexas dot edu> +// PR c++/509: Make sure specializations of member templates match correctly +//  between template and non-template overloads. + +template <class T> +struct A { +  template <class U> void f (U); +  void f2 (int); + +  template <class U> void h (U); +  void h (long); +}; + +template <> +struct A<float> { +  template <class U> void g (U); +  void g2 (float); +}; + +template <> void A<int>::f (int);                    // { dg-error "" } +template <> template <> void A<int>::f (int); + +template <> void A<int>::f2 (int); +template <> template <> void A<int>::f2 (int);       // { dg-error "" } + +template <> void A<float>::g (float); +template <> template <> void A<float>::g(float);     // { dg-error "" } + +template <> void A<float>::g2 (float);               // { dg-error "" } +template <> template <> void A<float>::g2(float);    // { dg-error "" } + +template <> void A<long>::h (long); +template <> template <> void A<long>::h(long); | 

