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]

C++ PATCH for infinite recursion with implicit typename



The infamous :-) implicit typename extension struck again, causing an
infinite recursion on this code:

  template <class T>
  struct B {
    typedef T X;
  };

  template <class T>
  struct S : public B<T>
  {
    struct I {
      void f(X x);
    };
  };

When looking for `X' we called make_typename_type for S<T>::X, which
called lookup_field, which called make_typename_type...

If lookup_field can't find the type, there's no need to go through
make_typename_type since we already know we can't find the type
itself.

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1998-10-15  Mark Mitchell  <mark@markmitchell.com>

	* cp-tree.def (TYPENAME_TYPE): Add to documentation.
	* cp-tree.h (TYPENAME_TYPE_FULLNAME): Document.
	(build_typename_type): New function.
	* decl.c (build_typename_type): Broken out from ...
	(make_typename_type): Use it.
	* search.c (lookup_field): Likewise.

Index: typename14.C
===================================================================
RCS file: typename14.C
diff -N typename14.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- typename14.C	Thu Oct 15 11:01:48 1998
***************
*** 0 ****
--- 1,15 ----
+ // Build don't link:
+ // Special g++ Options:
+ 
+ template <class T>
+ struct B {
+   typedef T X;
+ };
+ 
+ template <class T>
+ struct S : public B<T>
+ {
+   struct I {
+     void f(X x);
+   };
+ };
Index: cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.20
diff -c -p -r1.20 cp-tree.def
*** cp-tree.def	1998/10/06 14:19:46	1.20
--- cp-tree.def	1998/10/15 17:47:34
*************** DEFTREECODE (TEMPLATE_TYPE_PARM, "templa
*** 143,149 ****
     The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX.  */
  DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
  
! /* A type designated by 'typename T::t'. */
  DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
  
  /* A thunk is a stub function.
--- 143,152 ----
     The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX.  */
  DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
  
! /* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
!    TYPE_NAME is a TYPE_DECL for `t'.  If TREE_TYPE is present, this
!    type was generated by the implicit typename extension, and the
!    TREE_TYPE is a _TYPE from a baseclass of `T'.  */
  DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
  
  /* A thunk is a stub function.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.152
diff -c -p -r1.152 cp-tree.h
*** cp-tree.h	1998/10/13 14:34:21	1.152
--- cp-tree.h	1998/10/15 17:47:46
*************** struct lang_decl
*** 1337,1342 ****
--- 1337,1346 ----
     && !CLASSTYPE_USE_TEMPLATE (NODE) \
     && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
  
+ /* The name used by the user to name the typename type.  Typically,
+    this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
+    corresponding TYPE_DECL.  However, this may also be a
+    TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'.  */
  #define TYPENAME_TYPE_FULLNAME(NODE)	CLASSTYPE_SIZE (NODE)
  
  /* Nonzero in INTEGER_CST means that this int is negative by dint of
*************** extern tree binding_for_name            
*** 2543,2548 ****
--- 2547,2553 ----
  extern tree namespace_binding                   PROTO((tree, tree));
  extern void set_namespace_binding               PROTO((tree, tree, tree));
  extern tree lookup_namespace_name		PROTO((tree, tree));
+ extern tree build_typename_type                 PROTO((tree, tree, tree, tree));
  extern tree make_typename_type			PROTO((tree, tree));
  extern tree lookup_name_nonclass		PROTO((tree));
  extern tree lookup_function_nonclass            PROTO((tree, tree));
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.230
diff -c -p -r1.230 decl.c
*** decl.c	1998/10/14 21:16:37	1.230
--- decl.c	1998/10/15 17:48:29
*************** lookup_namespace_name (namespace, name)
*** 4776,4786 ****
    return error_mark_node;
  }
  
  tree
  make_typename_type (context, name)
       tree context, name;
  {
!   tree t, d;
    tree fullname;
  
    if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
--- 4776,4826 ----
    return error_mark_node;
  }
  
+ /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
+    the type of `T', NAME is the IDENTIFIER_NODE for `t'.  If BASE_TYPE
+    is non-NULL, this type is being created by the implicit typename
+    extension, and BASE_TYPE is a type named `t' in some base class of
+    `T' which depends on template parameters.  
+ 
+    Returns the new TYPENAME_TYPE.  */
+ 
  tree
+ build_typename_type (context, name, fullname, base_type)
+      tree context;
+      tree name;
+      tree fullname;
+      tree base_type;
+ {
+   tree t;
+   tree d;
+ 
+   if (processing_template_decl)
+     push_obstacks (&permanent_obstack, &permanent_obstack);
+ 
+   /* Build the TYPENAME_TYPE.  */
+   t = make_lang_type (TYPENAME_TYPE);
+   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+   TYPENAME_TYPE_FULLNAME (t) = fullname;
+   TREE_TYPE (t) = base_type;
+   CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ 
+   /* Build the corresponding TYPE_DECL.  */
+   d = build_decl (TYPE_DECL, name, t);
+   TYPE_NAME (TREE_TYPE (d)) = d;
+   TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+   DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ 
+   if (processing_template_decl)
+     pop_obstacks ();
+ 
+   return t;
+ }
+ 
+ tree
  make_typename_type (context, name)
       tree context, name;
  {
!   tree t;
    tree fullname;
  
    if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
*************** make_typename_type (context, name)
*** 4846,4867 ****
  	  return TREE_TYPE (t);
  	}
      }
! 
!   if (processing_template_decl)
!     push_obstacks (&permanent_obstack, &permanent_obstack);
!   t = make_lang_type (TYPENAME_TYPE);
!   TYPENAME_TYPE_FULLNAME (t) = fullname;
!   d = build_decl (TYPE_DECL, name, t);
!   if (processing_template_decl)
!     pop_obstacks ();
! 
!   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
!   TYPE_NAME (TREE_TYPE (d)) = d;
!   TYPE_STUB_DECL (TREE_TYPE (d)) = d;
!   DECL_CONTEXT (d) = FROB_CONTEXT (context);
!   CLASSTYPE_GOT_SEMICOLON (t) = 1;
! 
!   return t;
  }
  
  /* Select the right _DECL from multiple choices. */
--- 4886,4893 ----
  	  return TREE_TYPE (t);
  	}
      }
!   
!   return build_typename_type (context, name, fullname,  NULL_TREE);
  }
  
  /* Select the right _DECL from multiple choices. */
Index: search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.59
diff -c -p -r1.59 search.c
*** search.c	1998/10/13 14:34:24	1.59
--- search.c	1998/10/15 18:24:44
*************** lookup_field (xbasetype, name, protect, 
*** 1178,1184 ****
        rval = error_mark_node;
      }
  
!   /* Do implicit typename stuff.  */
    if (rval && TREE_CODE (rval) == TYPE_DECL
        && processing_template_decl
        && ! currently_open_class (BINFO_TYPE (rval_binfo))
--- 1178,1191 ----
        rval = error_mark_node;
      }
  
!   /* Do implicit typename stuff.  This code also handles out-of-class
!      definitions of nested classes whose enclosing class is a
!      template.  For example:
!     
!        template <class T> struct S { struct I { void f(); }; };
!        template <class T> void S<T>::I::f() {}
! 
!      will come through here to handle `S<T>::I'.  */
    if (rval && TREE_CODE (rval) == TYPE_DECL
        && processing_template_decl
        && ! currently_open_class (BINFO_TYPE (rval_binfo))
*************** lookup_field (xbasetype, name, protect, 
*** 1191,1199 ****
  		== current_class_type))
  	  break;
  
!       entry = make_typename_type (BINFO_TYPE (binfo), name);
!       TREE_TYPE (entry) = TREE_TYPE (rval);
!       rval = TYPE_MAIN_DECL (entry);
      }
  
    return rval;
--- 1198,1206 ----
  		== current_class_type))
  	  break;
  
!       entry = build_typename_type (BINFO_TYPE (binfo), name,  name, 
! 				   TREE_TYPE (rval));
!       return TYPE_STUB_DECL (entry);
      }
  
    return rval;


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