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 c++/17132


This patch fixes a rejects-valid regression in G++.  When substituting
into a class template, if there was a member template class, we have
to substitute into the arguments to that member template class.  The
resulting arguments may still be dependent, on the template parameters
to the member template, but -- because processing_template_decl was
zero -- dependent_type_p didn't realize that.

(The test case in the PR was actually invalid; it used "Type::operator
*" to form a pointer-to-member, failing to include the "&".  That was
not the point of the PR however; I fixed this before checking in the
test case.)

Tested on i686-pc-linux-gnu, applied on the mainline and on the 3.4
branch.

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


2004-10-28  Mark Mitchell  <mark@codesourcery.com>

	PR c++/17132
	* pt.c (instantiate_class_template): Increment
	processing_template_decl when substituting into a member class
	template.

2004-10-28  Mark Mitchell  <mark@codesourcery.com>

	PR c++/17132
	* g++.dg/template/memclass3.C: New test.

Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.938
diff -c -5 -p -r1.938 pt.c
*** cp/pt.c	27 Oct 2004 02:23:13 -0000	1.938
--- cp/pt.c	28 Oct 2004 20:38:30 -0000
*************** instantiate_class_template (tree type)
*** 5619,5636 ****
  	      /* Build new CLASSTYPE_NESTED_UTDS.  */
  
  	      tree tag = t;
  	      tree name = TYPE_IDENTIFIER (tag);
  	      tree newtag;
  
  	      newtag = tsubst (tag, args, tf_error, NULL_TREE);
  	      if (newtag == error_mark_node)
  		continue;
  
  	      if (TREE_CODE (newtag) != ENUMERAL_TYPE)
  		{
! 		  if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
  		    /* Unfortunately, lookup_template_class sets
  		       CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
  		       instantiation (i.e., for the type of a member
  		       template class nested within a template class.)
  		       This behavior is required for
--- 5619,5650 ----
  	      /* Build new CLASSTYPE_NESTED_UTDS.  */
  
  	      tree tag = t;
  	      tree name = TYPE_IDENTIFIER (tag);
  	      tree newtag;
+ 	      bool class_template_p;
  
+ 	      class_template_p = (TREE_CODE (tag) != ENUMERAL_TYPE
+ 				  && TYPE_LANG_SPECIFIC (tag)
+ 				  && CLASSTYPE_IS_TEMPLATE (tag));
+ 	      /* If the member is a class template, then -- even after
+ 		 substituition -- there may be dependent types in the
+ 		 template argument list for the class.  We increment
+ 		 PROCESSING_TEMPLATE_DECL so that dependent_type_p, as
+ 		 that function will assume that no types are dependent
+ 		 when outside of a template.  */
+ 	      if (class_template_p)
+ 		++processing_template_decl;
  	      newtag = tsubst (tag, args, tf_error, NULL_TREE);
+ 	      if (class_template_p)
+ 		--processing_template_decl;
  	      if (newtag == error_mark_node)
  		continue;
  
  	      if (TREE_CODE (newtag) != ENUMERAL_TYPE)
  		{
! 		  if (class_template_p)
  		    /* Unfortunately, lookup_template_class sets
  		       CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
  		       instantiation (i.e., for the type of a member
  		       template class nested within a template class.)
  		       This behavior is required for
Index: testsuite/g++.dg/template/memclass3.C
===================================================================
RCS file: testsuite/g++.dg/template/memclass3.C
diff -N testsuite/g++.dg/template/memclass3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/memclass3.C	28 Oct 2004 20:38:30 -0000
***************
*** 0 ****
--- 1,39 ----
+ // PR c++/17132
+ 
+ template <typename T>
+ struct has_deref
+ {
+     struct impl
+     {
+         template <
+             typename Type,
+             typename Type::reference (Type::*Func)(void) const>
+         struct func_tag;
+ 
+         template <typename Type>
+         static char (& test(
+             Type *,
+             func_tag<Type, &Type::operator*> * = 0
+         ))[2];
+         static char test(void *);
+     };
+ 
+     static const bool value = (sizeof(impl::test((T *) 0)) == 2);
+ };
+ 
+ template <typename T>
+ struct container
+ {
+     struct iterator
+     {
+         typedef T & reference;
+         reference operator*() const;
+     };
+ };
+ 
+ int main()
+ {
+     typedef container<int>::iterator iter;
+     int result = has_deref<iter>::value;
+     return result;
+ }


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