This is the mail archive of the gcc-bugs@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]

Typename Fix



Jason --

  Here's a (better) version of the fix for code like this:

    template <class T>
    struct A
    {
      typedef T A_Type;
    };


    template <class U>
    struct B : public A<U>
    {
    };


    template <class U>
    struct C : public B<U>
    {
      A_Type Func();
    };


    template <class U>
    C<U>::A_Type C<U>::Func()
    {
    }

 which egcs-971114 fails to compile.

-- 
Mark Mitchell		mmitchell@usa.net
Stanford University	http://www.stanford.edu

Sat Nov 15 17:06:55 1997  Mark Mitchell  <mmitchell@usa.net>

	* cp-tree.h (lookup_field_and_base): New function.
	* decl.c (lookup_name_real): Call lookup_field_and_base instead of
	lookup_field.
	* parse.y (nonnested_type): Lookup for inherited typedefs in
	template classes.
	* search.c (lookup_field): Call lookup_field_and_base.
	(lookup_field_and_base): New function.
	(dfs_walk): When doing pushdecls, don't recurse into template base
	classes, since they might later be specialized.

Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.1.1.2
diff -c -p -r1.1.1.2 cp-tree.h
*** cp-tree.h	1997/11/14 21:17:46	1.1.1.2
--- cp-tree.h	1997/11/15 00:01:01
*************** extern tree get_binfo				PROTO((tree, tr
*** 2378,2383 ****
--- 2378,2384 ----
  extern int get_base_distance			PROTO((tree, tree, int, tree *));
  extern tree compute_access			PROTO((tree, tree));
  extern tree lookup_field			PROTO((tree, tree, int, int));
+ extern tree lookup_field_and_base		PROTO((tree, tree, int, int, tree*));
  extern tree lookup_nested_field			PROTO((tree, int));
  extern tree lookup_fnfields			PROTO((tree, tree, int));
  extern tree lookup_nested_tag			PROTO((tree, tree));
Index: gcc/cp/decl.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl.c,v
retrieving revision 1.1.1.2
diff -c -p -r1.1.1.2 decl.c
*** decl.c	1997/11/14 21:17:46	1.1.1.2
--- decl.c	1997/11/15 20:48:15
*************** lookup_name_real (name, prefer_type, non
*** 4391,4396 ****
--- 4391,4397 ----
    int yylex = 0;
    tree from_obj = NULL_TREE;
    tree locval, classval;
+   tree scope_type = NULL_TREE;
  
    if (prefer_type == -2)
      {
*************** lookup_name_real (name, prefer_type, non
*** 4409,4414 ****
--- 4410,4417 ----
        else if (got_object != error_mark_node)
  	type = got_object;
        
+       scope_type = got_scope;
+ 
        if (type)
  	{
  	  if (type == error_mark_node)
*************** lookup_name_real (name, prefer_type, non
*** 4447,4470 ****
  		    }
  		}
  	      if (val == NULL_TREE)
! 		val = lookup_field (type, name, 0, 1);
  	    }
  	  else if (type == current_class_type)
  	    val = IDENTIFIER_CLASS_VALUE (name);
  	  else
! 	    val = lookup_field (type, name, 0, prefer_type);
  	}
        else
  	val = NULL_TREE;
  
        /* Add implicit 'typename' to scoped types from other classes.  */
!       if (got_scope && processing_template_decl
! 	  && got_scope != current_class_type
! 	  && uses_template_parms (got_scope)
  	  && val && TREE_CODE (val) == TYPE_DECL
  	  && ! DECL_ARTIFICIAL (val))
  	{
! 	  tree t = make_typename_type (got_scope, DECL_NAME (val));
  	  TREE_TYPE (t) = TREE_TYPE (val);
  	  val = TYPE_MAIN_DECL (t);
  	}
--- 4450,4475 ----
  		    }
  		}
  	      if (val == NULL_TREE)
! 		val = lookup_field_and_base (type, name, 0, 1,
! 					     &scope_type);
  	    }
  	  else if (type == current_class_type)
  	    val = IDENTIFIER_CLASS_VALUE (name);
  	  else
! 	    val = lookup_field_and_base (type, name, 0, prefer_type,
! 					 &scope_type); 
  	}
        else
  	val = NULL_TREE;
  
        /* Add implicit 'typename' to scoped types from other classes.  */
!       if (scope_type && processing_template_decl
! 	  && scope_type != current_class_type
! 	  && uses_template_parms (scope_type)
  	  && val && TREE_CODE (val) == TYPE_DECL
  	  && ! DECL_ARTIFICIAL (val))
  	{
! 	  tree t = make_typename_type (scope_type, DECL_NAME (val));
  	  TREE_TYPE (t) = TREE_TYPE (val);
  	  val = TYPE_MAIN_DECL (t);
  	}
*************** lookup_name_real (name, prefer_type, non
*** 4486,4511 ****
    if (current_class_type && ! nonclass)
      {
        classval = IDENTIFIER_CLASS_VALUE (name);
!       if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
  	/* Try to find values from base classes if we are presently
  	   defining a type.  We are presently only interested in
  	   TYPE_DECLs.  */
! 	classval = lookup_field (current_class_type, name, 0, 1);
  
        /* yylex() calls this with -2, since we should never start digging for
  	 the nested name at the point where we haven't even, for example,
  	 created the COMPONENT_REF or anything like that.  */
!       if (classval == NULL_TREE)
! 	classval = lookup_nested_field (name, ! yylex);
  
        /* Add implicit 'typename' to types from base classes.  */
        if (processing_template_decl
  	  && classval && TREE_CODE (classval) == TYPE_DECL
! 	  && DECL_CONTEXT (classval) != current_class_type
! 	  && uses_template_parms (DECL_CONTEXT (classval))
  	  && ! DECL_ARTIFICIAL (classval))
  	{
! 	  tree t = make_typename_type (DECL_CONTEXT (classval),
  				       DECL_NAME (classval));
  	  TREE_TYPE (t) = TREE_TYPE (classval);
  	  classval = TYPE_MAIN_DECL (t);
--- 4491,4523 ----
    if (current_class_type && ! nonclass)
      {
        classval = IDENTIFIER_CLASS_VALUE (name);
!       if (classval == NULL_TREE 
! 	  && (TYPE_BEING_DEFINED (current_class_type) 
! 	      || uses_template_parms (current_class_type)))
  	/* Try to find values from base classes if we are presently
  	   defining a type.  We are presently only interested in
  	   TYPE_DECLs.  */
! 	classval = lookup_field_and_base (current_class_type, name, 0,
! 					  1, &scope_type);
  
        /* yylex() calls this with -2, since we should never start digging for
  	 the nested name at the point where we haven't even, for example,
  	 created the COMPONENT_REF or anything like that.  */
!       if (classval == NULL_TREE) 
! 	{
! 	  classval = lookup_nested_field (name, ! yylex);
! 	  if (classval != NULL_TREE)
! 	    scope_type = DECL_CONTEXT (classval);
! 	}
  
        /* Add implicit 'typename' to types from base classes.  */
        if (processing_template_decl
  	  && classval && TREE_CODE (classval) == TYPE_DECL
! 	  && scope_type != current_class_type
! 	  && uses_template_parms (scope_type)
  	  && ! DECL_ARTIFICIAL (classval))
  	{
! 	  tree t = make_typename_type (scope_type,
  				       DECL_NAME (classval));
  	  TREE_TYPE (t) = TREE_TYPE (classval);
  	  classval = TYPE_MAIN_DECL (t);
Index: gcc/cp/parse.y
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/parse.y,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 parse.y
*** parse.y	1997/11/08 17:53:59	1.1.1.1
--- parse.y	1997/11/15 21:05:04
*************** nonnested_type:
*** 3018,3024 ****
  		  if (TREE_CODE ($1) == IDENTIFIER_NODE)
  		    {
  		      if (current_class_type
! 			  && TYPE_BEING_DEFINED (current_class_type)
  			  && ! IDENTIFIER_CLASS_VALUE ($1))
  			{
  			  /* Be sure to get an inherited typedef.  */
--- 3018,3025 ----
  		  if (TREE_CODE ($1) == IDENTIFIER_NODE)
  		    {
  		      if (current_class_type
! 			  && (TYPE_BEING_DEFINED (current_class_type)
! 			      || uses_template_parms (current_class_type))
  			  && ! IDENTIFIER_CLASS_VALUE ($1))
  			{
  			  /* Be sure to get an inherited typedef.  */
Index: gcc/cp/search.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/search.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 search.c
*** search.c	1997/11/08 17:53:59	1.1.1.1
--- search.c	1997/11/15 20:40:52
*************** lookup_fnfields_here (type, name)
*** 1139,1144 ****
--- 1139,1145 ----
    return -1;
  }
  
+ 
  /* Look for a field named NAME in an inheritance lattice dominated by
     XBASETYPE.  PROTECT is zero if we can avoid computing access
     information, otherwise it is 1.  WANT_TYPE is 1 when we should only
*************** lookup_fnfields_here (type, name)
*** 1146,1157 ****
  
     It was not clear what should happen if WANT_TYPE is set, and an
     ambiguity is found.  At least one use (lookup_name) to not see
!    the error.  */
  
! tree
! lookup_field (xbasetype, name, protect, want_type)
       register tree xbasetype, name;
       int protect, want_type;
  {
    int head = 0, tail = 0;
    tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
--- 1147,1163 ----
  
     It was not clear what should happen if WANT_TYPE is set, and an
     ambiguity is found.  At least one use (lookup_name) to not see
!    the error.  
  
!    If RIMMEDIATE_BASE is non-zero, store the immediate base of
!    xbasetype in which the field was found there.  */
! 
! tree 
! lookup_field_and_base (xbasetype, name, protect, want_type,
! 		       rimmediate_base)
       register tree xbasetype, name;
       int protect, want_type;
+      tree* rimmediate_base;
  {
    int head = 0, tail = 0;
    tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
*************** lookup_field (xbasetype, name, protect, 
*** 1160,1165 ****
--- 1166,1173 ----
    tree entry, binfo, binfo_h;
    tree own_access = access_default_node;
    int vbase_name_p = VBASE_NAME_P (name);
+   tree immediate_base;
+   int depth = 0;
  
    /* rval_binfo is the binfo associated with the found member, note,
       this can be set with useful information, even when rval is not
*************** lookup_field (xbasetype, name, protect, 
*** 1338,1349 ****
        for (i = 0; i < n_baselinks; i++)
  	{
  	  tree base_binfo = TREE_VEC_ELT (binfos, i);
  	  if (BINFO_FIELDS_MARKED (base_binfo) == 0)
  	    {
  	      tree btypes;
  
  	      SET_BINFO_FIELDS_MARKED (base_binfo);
! 	      btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
  	      TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
  	      TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
  	      TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
--- 1346,1362 ----
        for (i = 0; i < n_baselinks; i++)
  	{
  	  tree base_binfo = TREE_VEC_ELT (binfos, i);
+ 
+ 	  if (depth == 0)
+ 	    immediate_base = TREE_TYPE (base_binfo);
+ 
  	  if (BINFO_FIELDS_MARKED (base_binfo) == 0)
  	    {
  	      tree btypes;
  
  	      SET_BINFO_FIELDS_MARKED (base_binfo);
! 	      btypes = my_tree_cons (immediate_base, base_binfo,
! 				     basetype_chain); 
  	      TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
  	      TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
  	      TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
*************** lookup_field (xbasetype, name, protect, 
*** 1369,1374 ****
--- 1382,1388 ----
        basetype_chain = search_stack->first[head++];
        binfo_h = TREE_VALUE (basetype_chain);
        basetype_chain = TREE_CHAIN (basetype_chain);
+       immediate_base = TREE_PURPOSE (basetype_chain);
        basetype_path = TREE_VALUE (basetype_chain);
        if (TREE_CHAIN (basetype_chain))
  	BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
*************** lookup_field (xbasetype, name, protect, 
*** 1402,1407 ****
--- 1416,1423 ----
  	      if (nval)
  		{
  		  rval = nval;
+ 		  if (rimmediate_base)
+ 		    *rimmediate_base = immediate_base;
  		  if (entry || protect)
  		    this_v = compute_access (basetype_path, rval);
  		  /* These may look ambiguous, but they really are not.  */
*************** lookup_field (xbasetype, name, protect, 
*** 1424,1429 ****
--- 1440,1447 ----
  	      break;
  	    }
  	}
+ 
+       ++depth;
      }
    {
      tree *tp = search_stack->first;
*************** lookup_field (xbasetype, name, protect, 
*** 1542,1547 ****
--- 1560,1575 ----
    return rval;
  }
  
+ 
+ tree
+ lookup_field (xbasetype, name, protect, want_type)
+      register tree xbasetype, name;
+      int protect, want_type;
+ {
+   return lookup_field_and_base (xbasetype, name, protect, want_type, 0);
+ }
+ 
+ 
  /* Try to find NAME inside a nested class.  */
  
  tree
*************** dfs_walk (binfo, fn, qfn)
*** 2510,2515 ****
--- 2538,2551 ----
  	      dfs_walk (base_binfo, fn, qfn);
  
  	      vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
+ 	    }
+ 	  else if (fn == dfs_pushdecls)
+ 	    {
+ 	      /* We don't want to enter template base classes of template
+ 		 classes because we will then give bindings to some names
+ 		 that may not exist if the base class is specialized.  */
+ 	      if (!uses_template_parms (TREE_TYPE (base_binfo)))
+ 		dfs_walk (base_binfo, fn, qfn);
  	    }
  	  else
  	    dfs_walk (base_binfo, fn, qfn);
cvs diff: Diffing gcc/cp/inc
cvs diff: Diffing gcc/ginclude
cvs diff: Diffing gcc/testsuite
cvs diff: Diffing gcc/testsuite/config
cvs diff: Diffing gcc/testsuite/g++.old-deja
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.benjamin
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.bob
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.brendan
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.bugs
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.ext
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.gb
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.jason
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.law
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.mike
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.niklas
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.other
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.pt
Index: gcc/testsuite/g++.old-deja/g++.pt/typename3.C
===================================================================
RCS file: typename3.C
diff -N typename3.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- typename3.C	Sat Nov 15 16:45:35 1997
***************
*** 0 ****
--- 1,20 ----
+ // Build don't link:
+ 
+ template <class T>
+ struct A
+ {
+   typedef T A_Type;
+ };
+ 
+ 
+ template <class U>
+ struct B : public A<U>
+ {
+   A_Type Func();
+ };
+ 
+ 
+ template <class U>
+ A<U>::A_Type B<U>::Func()
+ {
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/typename4.C
===================================================================
RCS file: typename4.C
diff -N typename4.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- typename4.C	Sat Nov 15 16:45:44 1997
***************
*** 0 ****
--- 1,26 ----
+ // Build don't link:
+ 
+ template <class T>
+ struct A
+ {
+   typedef T A_Type;
+ };
+ 
+ 
+ template <class U>
+ struct B : public A<U>
+ {
+ };
+ 
+ 
+ template <class U>
+ struct C : public B<U>
+ {
+   A_Type Func();
+ };
+ 
+ 
+ template <class U>
+ C<U>::A_Type C<U>::Func()
+ {
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/typename5.C
===================================================================
RCS file: typename5.C
diff -N typename5.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- typename5.C	Sat Nov 15 16:45:50 1997
***************
*** 0 ****
--- 1,26 ----
+ // Build don't link:
+ 
+ template <class T>
+ struct A
+ {
+   typedef T A_Type;
+ };
+ 
+ 
+ template <class U>
+ struct B : public A<U>
+ {
+ };
+ 
+ 
+ template <class U>
+ struct C : public B<U>
+ {
+   void Func(A_Type);
+ };
+ 
+ 
+ template <class U>
+ void C<U>::Func(A_Type)
+ {
+ }


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