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