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 7647


This patch fixes PR C++/7647, a high-priority PR.

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

--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery dot com

2003-03-30  Mark Mitchell  <mark at codesourcery dot com>

	PR c++/7647
	* decl.c (grokdeclarator): Tidy, slightly.
	* search.c (lookup_field_1): Add want_type parameter.
	(lookup_field_r): Adjust call to lookup_field_1.

2003-03-30  Mark Mitchell  <mark at codesourcery dot com>

	PR c++/7647
	* g++.dg/lookup-class-member-2.C: New test.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1029
diff -c -5 -p -r1.1029 decl.c
*** cp/decl.c	30 Mar 2003 16:00:38 -0000	1.1029
--- cp/decl.c	30 Mar 2003 22:25:56 -0000
*************** grokdeclarator (tree declarator,
*** 11549,11570 ****
  		     declaration, to cause callers to completely
  		     ignore this declaration.  */
  		  return void_type_node;
  	      }
  
- 	    /* 9.2p13 [class.mem] */
- 	    if (constructor_name_p (declarator, current_class_type)
- 		/* The standard does not allow non-static data members
- 		   here either, but we agreed at the 10/99 meeting
- 		   to change that in TC 1 so that they are allowed in
- 		   classes with no user-defined constructors.  */
- 		&& staticp)
- 	      pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
- 			  declarator);
- 
  	    if (staticp)
  	      {
  		/* C++ allows static class members.  All other work
  		   for this is done by grokfield.  */
  		decl = build_lang_decl (VAR_DECL, declarator, type);
  		TREE_STATIC (decl) = 1;
  		/* In class context, 'static' means public access.  */
--- 11549,11567 ----
  		     declaration, to cause callers to completely
  		     ignore this declaration.  */
  		  return void_type_node;
  	      }
  
  	    if (staticp)
  	      {
+ 		/* [class.mem] forbids static data members with the
+ 		   same name as the enclosing class.  Non-static data
+ 		   members are checked in check_field_decls.  */
+ 		if (constructor_name_p (declarator, current_class_type))
+ 		  pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
+ 			   declarator);
+ 		  
  		/* C++ allows static class members.  All other work
  		   for this is done by grokfield.  */
  		decl = build_lang_decl (VAR_DECL, declarator, type);
  		TREE_STATIC (decl) = 1;
  		/* In class context, 'static' means public access.  */
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.257
diff -c -5 -p -r1.257 search.c
*** cp/search.c	13 Mar 2003 21:39:38 -0000	1.257
--- cp/search.c	30 Mar 2003 22:25:57 -0000
*************** struct vbase_info 
*** 79,89 ****
    /* A pointer to a complete object of the indicated TYPE.  */
    tree decl_ptr;
    tree inits;
  };
  
! static tree lookup_field_1 (tree, tree);
  static tree dfs_check_overlap (tree, void *);
  static tree dfs_no_overlap_yet (tree, int, void *);
  static base_kind lookup_base_r (tree, tree, base_access,
  				bool, bool, bool, tree *);
  static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
--- 79,89 ----
    /* A pointer to a complete object of the indicated TYPE.  */
    tree decl_ptr;
    tree inits;
  };
  
! static tree lookup_field_1 (tree, tree, bool);
  static tree dfs_check_overlap (tree, void *);
  static tree dfs_no_overlap_yet (tree, int, void *);
  static base_kind lookup_base_r (tree, tree, base_access,
  				bool, bool, bool, tree *);
  static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
*************** get_dynamic_cast_base_type (tree subtype
*** 418,438 ****
    offset = build_int_2 (boff, -1);
    TREE_TYPE (offset) = ssizetype;
    return offset;
  }
  
! /* Search for a member with name NAME in a multiple inheritance lattice
!    specified by TYPE.  If it does not exist, return NULL_TREE.
     If the member is ambiguously referenced, return `error_mark_node'.
!    Otherwise, return the FIELD_DECL.  */
  
  /* Do a 1-level search for NAME as a member of TYPE.  The caller must
     figure out whether it can access this field.  (Since it is only one
     level, this is reasonable.)  */
  
  static tree
! lookup_field_1 (tree type, tree name)
  {
    register tree field;
  
    if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
        || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
--- 418,439 ----
    offset = build_int_2 (boff, -1);
    TREE_TYPE (offset) = ssizetype;
    return offset;
  }
  
! /* Search for a member with name NAME in a multiple inheritance
!    lattice specified by TYPE.  If it does not exist, return NULL_TREE.
     If the member is ambiguously referenced, return `error_mark_node'.
!    Otherwise, return a DECL with the indicated name.  If WANT_TYPE is
!    true, type declarations are preferred.  */
  
  /* Do a 1-level search for NAME as a member of TYPE.  The caller must
     figure out whether it can access this field.  (Since it is only one
     level, this is reasonable.)  */
  
  static tree
! lookup_field_1 (tree type, tree name, bool want_type)
  {
    register tree field;
  
    if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
        || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
*************** lookup_field_1 (tree type, tree name)
*** 465,515 ****
  	    hi = i;
  	  else if (DECL_NAME (fields[i]) < name)
  	    lo = i + 1;
  	  else
  	    {
  	      /* We might have a nested class and a field with the
  		 same name; we sorted them appropriately via
  		 field_decl_cmp, so just look for the last field with
  		 this name.  */
! 	      while (i + 1 < hi
! 		     && DECL_NAME (fields[i+1]) == name)
! 		++i;
! 	      return fields[i];
  	    }
  	}
        return NULL_TREE;
      }
  
    field = TYPE_FIELDS (type);
  
  #ifdef GATHER_STATISTICS
    n_calls_lookup_field_1++;
  #endif /* GATHER_STATISTICS */
!   while (field)
      {
  #ifdef GATHER_STATISTICS
        n_fields_searched++;
  #endif /* GATHER_STATISTICS */
        my_friendly_assert (DECL_P (field), 0);
        if (DECL_NAME (field) == NULL_TREE
  	  && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
  	{
! 	  tree temp = lookup_field_1 (TREE_TYPE (field), name);
  	  if (temp)
  	    return temp;
  	}
        if (TREE_CODE (field) == USING_DECL)
  	/* For now, we're just treating member using declarations as
  	   old ARM-style access declarations.  Thus, there's no reason
  	   to return a USING_DECL, and the rest of the compiler can't
  	   handle it.  Once the class is defined, these are purged
  	   from TYPE_FIELDS anyhow; see handle_using_decl.  */
! 	;
!       else if (DECL_NAME (field) == name)
  	return field;
-       field = TREE_CHAIN (field);
      }
    /* Not found.  */
    if (name == vptr_identifier)
      {
        /* Give the user what s/he thinks s/he wants.  */
--- 466,529 ----
  	    hi = i;
  	  else if (DECL_NAME (fields[i]) < name)
  	    lo = i + 1;
  	  else
  	    {
+ 	      field = NULL_TREE;
+ 
  	      /* We might have a nested class and a field with the
  		 same name; we sorted them appropriately via
  		 field_decl_cmp, so just look for the last field with
  		 this name.  */
! 	      while (true)
! 		{
! 		  if (!want_type 
! 		      || TREE_CODE (fields[i]) == TYPE_DECL
! 		      || DECL_CLASS_TEMPLATE_P (fields[i]))
! 		    field = fields[i];
! 		  if (i + 1 == hi || DECL_NAME (fields[i+1]) != name)
! 		    break;
! 		  i++;
! 		}
! 
! 	      return field;
  	    }
  	}
        return NULL_TREE;
      }
  
    field = TYPE_FIELDS (type);
  
  #ifdef GATHER_STATISTICS
    n_calls_lookup_field_1++;
  #endif /* GATHER_STATISTICS */
!   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
      {
  #ifdef GATHER_STATISTICS
        n_fields_searched++;
  #endif /* GATHER_STATISTICS */
        my_friendly_assert (DECL_P (field), 0);
        if (DECL_NAME (field) == NULL_TREE
  	  && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
  	{
! 	  tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type);
  	  if (temp)
  	    return temp;
  	}
        if (TREE_CODE (field) == USING_DECL)
  	/* For now, we're just treating member using declarations as
  	   old ARM-style access declarations.  Thus, there's no reason
  	   to return a USING_DECL, and the rest of the compiler can't
  	   handle it.  Once the class is defined, these are purged
  	   from TYPE_FIELDS anyhow; see handle_using_decl.  */
! 	continue;
! 
!       if (DECL_NAME (field) == name
! 	  && (!want_type 
! 	      || TREE_CODE (field) == TYPE_DECL
! 	      || DECL_CLASS_TEMPLATE_P (field)))
  	return field;
      }
    /* Not found.  */
    if (name == vptr_identifier)
      {
        /* Give the user what s/he thinks s/he wants.  */
*************** lookup_field_r (tree binfo, void *data)
*** 1077,1087 ****
  	nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
      }
  
    if (!nval)
      /* Look for a data member or type.  */
!     nval = lookup_field_1 (type, lfi->name);
  
    /* If there is no declaration with the indicated name in this type,
       then there's nothing to do.  */
    if (!nval)
      return NULL_TREE;
--- 1091,1101 ----
  	nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
      }
  
    if (!nval)
      /* Look for a data member or type.  */
!     nval = lookup_field_1 (type, lfi->name, lfi->want_type);
  
    /* If there is no declaration with the indicated name in this type,
       then there's nothing to do.  */
    if (!nval)
      return NULL_TREE;
Index: testsuite/g++.dg/lookup/class-member-2.C
===================================================================
RCS file: testsuite/g++.dg/lookup/class-member-2.C
diff -N testsuite/g++.dg/lookup/class-member-2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/class-member-2.C	30 Mar 2003 22:25:57 -0000
***************
*** 0 ****
--- 1,7 ----
+ template <typename T> struct A
+ {
+   void foo () const {}
+   char A;
+ };
+ 
+ void bar() { A<void>().foo(); }


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