C++ PATCH: PR 27689
Mark Mitchell
mark@codesourcery.com
Fri Jun 16 07:12:00 GMT 2006
This patch fixes a problem with template template parameters: we were
matching specializations of non-primary templates. While looking at
the code, I also realized that we would fail to match specializations
of template unions, so I fixed that too. (I don't imagine there are
many uses of templates unions, but...)
Tested on x86_64-unknown-linux-gnu, applied on the mainline. I will
apply to 4.1 when testing completes.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2006-06-15 Mark Mitchell <mark@codesourcery.com>
PR c++/27689
* cp-tree.h (CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P): New
macro.
* pt.c (unify): Use it.
2006-06-15 Mark Mitchell <mark@codesourcery.com>
PR c++/27689
* g++.dg/template/ttp18.C: New test.
* g++.dg/template/ttp19.C: Likewise.
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h (revision 114635)
+++ gcc/cp/cp-tree.h (working copy)
@@ -1117,14 +1117,6 @@ struct lang_type GTY(())
#endif /* ENABLE_TREE_CHECKING */
-/* Indicates whether or not (and how) a template was expanded for this class.
- 0=no information yet/non-template class
- 1=implicit template instantiation
- 2=explicit template specialization
- 3=explicit template instantiation */
-#define CLASSTYPE_USE_TEMPLATE(NODE) \
- (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
-
/* Fields used for storing information before the class is defined.
After the class is defined, these fields hold other information. */
@@ -2096,15 +2088,15 @@ extern void decl_shadowed_for_var_insert
(DECL_LANG_SPECIFIC (DECL)->decl_flags.deferred)
/* If non-NULL for a VAR_DECL, FUNCTION_DECL, TYPE_DECL or
- TEMPLATE_DECL, the entity is a template specialization. In that
- case, DECL_TEMPLATE_INFO is a TREE_LIST, whose TREE_PURPOSE is the
- TEMPLATE_DECL of which this entity is a specialization. The TREE_
- TREE_VALUE is the template arguments used to specialize the
- template.
-
- In general, DECL_TEMPLATE_INFO is non-NULL only if
- DECL_USE_TEMPLATE is nonzero. However, for friends, we sometimes
- have DECL_TEMPLATE_INFO even when DECL_USE_TEMPLATE is zero.
+ TEMPLATE_DECL, the entity is either a template specialization (if
+ DECL_USE_TEMPLATE is non-zero) or the abstract instance of the
+ template itself.
+
+ In either case, DECL_TEMPLATE_INFO is a TREE_LIST, whose
+ TREE_PURPOSE is the TEMPLATE_DECL of which this entity is a
+ specialization or abstract instance. The TREE_VALUE is the
+ template arguments used to specialize the template.
+
Consider:
template <typename T> struct S { friend void f(T) {} };
@@ -2112,7 +2104,8 @@ extern void decl_shadowed_for_var_insert
In this case, S<int>::f is, from the point of view of the compiler,
an instantiation of a template -- but, from the point of view of
the language, each instantiation of S results in a wholly unrelated
- global function f. */
+ global function f. In this case, DECL_TEMPLATE_INFO for S<int>::f
+ will be non-NULL, but DECL_USE_TEMPLATE will be zero. */
#define DECL_TEMPLATE_INFO(NODE) \
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
->decl_flags.u.template_info)
@@ -2240,6 +2233,16 @@ extern void decl_shadowed_for_var_insert
are always the full set of arguments required to instantiate this
declaration from the most general template specialized here. */
#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE))
+
+/* The TEMPLATE_DECL associated with NODE, a class type. Even if NODE
+ will be generated from a partial specialization, the TEMPLATE_DECL
+ referred to here will be the original template. For example,
+ given:
+
+ template <typename T> struct S {};
+ template <typename T> struct S<T*> {};
+
+ the CLASSTPYE_TI_TEMPLATE for S<int*> will be S, not the S<T*>. */
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
@@ -2252,7 +2255,7 @@ extern void decl_shadowed_for_var_insert
(CLASSTYPE_TI_TEMPLATE ((TYPE))))) \
: (TYPE))
-/* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+/* Like CLASS_TI_TEMPLATE, but also works for ENUMERAL_TYPEs. */
#define TYPE_TI_TEMPLATE(NODE) \
(TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE)))
@@ -2845,17 +2848,38 @@ extern void decl_shadowed_for_var_insert
/* Returns nonzero if NODE is a primary template. */
#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))
-/* Indicates whether or not (and how) a template was expanded for this
- FUNCTION_DECL or VAR_DECL.
- 0=normal declaration, e.g. int min (int, int);
- 1=implicit template instantiation
- 2=explicit template specialization, e.g. int min<int> (int, int);
- 3=explicit template instantiation, e.g. template int min<int> (int, int);
+/* Non-zero iff NODE is a specialization of a template. The value
+ indicates the type of specializations:
+
+ 1=implicit instantiation
+ 2=explicit specialization, e.g. int min<int> (int, int);
+ 3=explicit instantiation, e.g. template int min<int> (int, int);
+
+ Note that NODE will be marked as a specialization even if the
+ template it is instantiating is not a primary template. For
+ example, given:
+
+ template <typename T> struct O {
+ void f();
+ struct I {};
+ };
+
+ both O<int>::f and O<int>::I will be marked as instantiations.
- If DECL_USE_TEMPLATE is nonzero, then DECL_TEMPLATE_INFO will also
+ If DECL_USE_TEMPLATE is non-zero, then DECL_TEMPLATE_INFO will also
be non-NULL. */
#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.use_template)
+/* Like DECL_USE_TEMPLATE, but for class types. */
+#define CLASSTYPE_USE_TEMPLATE(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
+
+/* True if NODE is a specialization of a primary template. */
+#define CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P(NODE) \
+ (CLASS_TYPE_P (NODE) \
+ && CLASSTYPE_USE_TEMPLATE (NODE) \
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
+
#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) & 1)
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 114701)
+++ gcc/cp/pt.c (working copy)
@@ -10166,7 +10166,7 @@ unify (tree tparms, tree targs, tree par
/* ARG must be constructed from a template class or a template
template parameter. */
if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
- && (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg)))
+ && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
return 1;
{
Index: gcc/testsuite/g++.dg/template/ttp19.C
===================================================================
--- gcc/testsuite/g++.dg/template/ttp19.C (revision 0)
+++ gcc/testsuite/g++.dg/template/ttp19.C (revision 0)
@@ -0,0 +1,7 @@
+// PR c++/27689
+
+void f (...);
+template <template <typename> class F, typename T> void f (F<T>);
+template <typename> struct foo { struct bar {}; };
+void g (foo<int>::bar x) { f(x); }
+
Index: gcc/testsuite/g++.dg/template/ttp18.C
===================================================================
--- gcc/testsuite/g++.dg/template/ttp18.C (revision 0)
+++ gcc/testsuite/g++.dg/template/ttp18.C (revision 0)
@@ -0,0 +1,10 @@
+template <template <typename> class T>
+void f(T<int>) {}
+
+template <typename T>
+union U {};
+
+void g() {
+ f(U<int>());
+}
+
More information about the Gcc-patches
mailing list