This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 27689


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>());
+}
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]