C++ PATCH: PR 23293

Mark Mitchell mark@codesourcery.com
Tue Oct 18 15:33:00 GMT 2005


There are several PRs about the fact that we use confusing names for
template specializations.  In particular, we tend to say "S<A>",
when the user wrote "S<B>" and "A" and "B" are different names for the
same type.

The C++ front-end uses typedef types in the internal representations
of types associated with declarations.  That allows us to report the
type of a function using the same names that the user used to declare
it, for example.  However, we only maintain one copy of each template
specialization type; if the user writes "S<int>" and "S<I>" (with "I"
a typedef for "int") we create only one "S<int/I>" type -- not two.
(Creating two, especially given our current tree structure, would be
prohibitively expensive -- and it would probably break things in our
current template processing code.)  So, if the user writes "S<I>"
first, then that becomes the name of "S<int>" forevermore -- even in
scopes where "I" is some other type, for example.

That's clearly bad.  This patch makes us the canonical type variant
(i.e., the non-typedef variant) so that we get consistent, sensible
names in all scopes.  

I'm sure that someone will now file a PR saying that we've "regressed"
on reporting errors about types like "S<MyList>", which will now be
presented as "S<std::list <int, ... > >".  I guess that's a
regression, but not an important one, and this patch clearly makes
things more consistent.  (And, in many cases, you actually need the
non-typedef form of a template type in order to figure out why
deduction failed...)

Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.0 branch.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2005-10-18  Mark Mitchell  <mark@codesourcery.com>

	PR c++/23293
	* pt.c (convert_template_argument): Use canonical type variants in
	template specializations.

2005-10-18  Mark Mitchell  <mark@codesourcery.com>

	PR c++/23293
	* g++.dg/template/error19.C: New test.

Index: gcc/testsuite/g++.dg/template/error19.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/error19.C
diff -N gcc/testsuite/g++.dg/template/error19.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/error19.C	18 Oct 2005 14:44:04 -0000
***************
*** 0 ****
--- 1,22 ----
+ // PR c++/23293
+ 
+ template < typename > struct P;
+ struct S;
+ 
+ void *unrelated_function()
+ {
+   typedef S K;
+   P < K > * p;
+   return p;
+ }
+ 
+ template < typename U >
+ void generate_warning()
+ { 
+   U::x(); // { dg-error "P<S>" }
+ }
+ 
+ int main()
+ {
+   generate_warning< P < S > >();
+ }
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.1049
diff -c -5 -p -r1.1049 pt.c
*** gcc/cp/pt.c	16 Oct 2005 23:16:28 -0000	1.1049
--- gcc/cp/pt.c	18 Oct 2005 14:44:06 -0000
*************** convert_template_argument (tree parm,
*** 3928,3937 ****
--- 3928,3944 ----
  		}
  	    }
  	}
        else
  	val = arg;
+       /* We only form one instance of each template specialization.
+ 	 Therefore, if we use a non-canonical variant (i.e., a
+ 	 typedef), any future messages referring to the type will use 
+ 	 the typedef, which is confusing if those future uses do not
+ 	 themselves also use the typedef.  */
+       if (TYPE_P (val))
+ 	val = canonical_type_variant (val);
      }
    else
      {
        tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
  



More information about the Gcc-patches mailing list