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] Fix 23219


Hi,
I've installed this patch to fix 23219. The problem was we were updating an IDENTIFIER_NODE's value & type fields before determining that the template declaration was ill-formed.


I also removed some now unreachable code concerning empty stub decls.

booted & tested on i686-pc-linux-gnu, installed on mainline. I'll install just the identifier node changes on 4.0 shortly.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-08-11  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/23219
	* name-lookup.c (pushtag): Process the template type before
	altering the identifier lookup fields.  Remove unreachable code
	creating an empty stub decl.

2005-08-11  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/23219
	* g++.dg/parse/crash28.C: New.

Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.135
diff -c -3 -p -r1.135 name-lookup.c
*** cp/name-lookup.c	6 Aug 2005 05:17:57 -0000	1.135
--- cp/name-lookup.c	11 Aug 2005 07:47:05 -0000
*************** tree
*** 4626,4631 ****
--- 4626,4632 ----
  pushtag (tree name, tree type, tag_scope scope)
  {
    struct cp_binding_level *b;
+   tree decl;
  
    timevar_push (TV_NAME_LOOKUP);
    b = current_binding_level;
*************** pushtag (tree name, tree type, tag_scope
*** 4647,4760 ****
  		 || COMPLETE_TYPE_P (b->this_entity))))
      b = b->level_chain;
  
!   if (name)
      {
!       /* Do C++ gratuitous typedefing.  */
!       if (IDENTIFIER_TYPE_VALUE (name) != type)
  	{
! 	  tree d = NULL_TREE;
! 	  int in_class = 0;
! 	  tree context = TYPE_CONTEXT (type);
! 
! 	  if (! context)
! 	    {
! 	      tree cs = current_scope ();
! 
! 	      if (scope == ts_current)
! 		context = cs;
! 	      else if (cs != NULL_TREE && TYPE_P (cs))
! 		/* When declaring a friend class of a local class, we want
! 		   to inject the newly named class into the scope
! 		   containing the local class, not the namespace scope.  */
! 		context = decl_function_context (get_type_decl (cs));
! 	    }
! 	  if (!context)
! 	    context = current_namespace;
! 
! 	  if (b->kind == sk_class
! 	      || (b->kind == sk_template_parms
! 		  && b->level_chain->kind == sk_class))
! 	    in_class = 1;
! 
! 	  if (current_lang_name == lang_name_java)
! 	    TYPE_FOR_JAVA (type) = 1;
! 
! 	  d = create_implicit_typedef (name, type);
! 	  DECL_CONTEXT (d) = FROB_CONTEXT (context);
! 	  if (scope == ts_within_enclosing_non_class)
! 	    {
! 	      /* This is a friend.  Make this TYPE_DECL node hidden from
! 		 ordinary name lookup.  Its corresponding TEMPLATE_DECL
! 		 will be marked in push_template_decl_real.  */
! 	      retrofit_lang_decl (d);
! 	      DECL_ANTICIPATED (d) = 1;
! 	      DECL_FRIEND_P (d) = 1;
! 	    }
! 
! 	  if (! in_class)
! 	    set_identifier_type_value_with_scope (name, d, b);
! 
! 	  d = maybe_process_template_type_declaration
! 		(type, scope == ts_within_enclosing_non_class, b);
! 	  if (d == error_mark_node)
! 	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
! 
! 	  if (b->kind == sk_class)
! 	    {
! 	      if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
! 		/* Put this TYPE_DECL on the TYPE_FIELDS list for the
! 		   class.  But if it's a member template class, we
! 		   want the TEMPLATE_DECL, not the TYPE_DECL, so this
! 		   is done later.  */
! 		finish_member_declaration (d);
! 	      else
! 		pushdecl_class_level (d);
! 	    }
! 	  else if (b->kind != sk_template_parms)
! 	    d = pushdecl_with_scope (d, b);
! 
! 	  TYPE_CONTEXT (type) = DECL_CONTEXT (d);
! 
! 	  /* If this is a local class, keep track of it.  We need this
! 	     information for name-mangling, and so that it is possible to find
! 	     all function definitions in a translation unit in a convenient
! 	     way.  (It's otherwise tricky to find a member function definition
! 	     it's only pointed to from within a local class.)  */
! 	  if (TYPE_CONTEXT (type)
! 	      && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL)
! 	    VEC_safe_push (tree, gc, local_classes, type);
  	}
        if (b->kind == sk_class
! 	  && !COMPLETE_TYPE_P (current_class_type))
  	{
! 	  maybe_add_class_template_decl_list (current_class_type,
! 					      type, /*friend_p=*/0);
  
! 	  if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
! 	    CLASSTYPE_NESTED_UTDS (current_class_type)
! 	      = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
  
! 	  binding_table_insert
! 	    (CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
  	}
!     }
  
!   if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
!     /* Use the canonical TYPE_DECL for this node.  */
!     TYPE_STUB_DECL (type) = TYPE_NAME (type);
!   else
!     {
!       /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE
! 	 will be the tagged type we just added to the current
! 	 binding level.  This fake NULL-named TYPE_DECL node helps
! 	 dwarfout.c to know when it needs to output a
! 	 representation of a tagged type, and it also gives us a
! 	 convenient place to record the "scope start" address for
! 	 the tagged type.  */
  
!       tree d = build_decl (TYPE_DECL, NULL_TREE, type);
!       TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
      }
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
  }
  
--- 4648,4750 ----
  		 || COMPLETE_TYPE_P (b->this_entity))))
      b = b->level_chain;
  
!   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
!   
!   /* Do C++ gratuitous typedefing.  */
!   if (IDENTIFIER_TYPE_VALUE (name) != type)
      {
!       tree tdef;
!       int in_class = 0;
!       tree context = TYPE_CONTEXT (type);
! 
!       if (! context)
  	{
! 	  tree cs = current_scope ();
! 	  
! 	  if (scope == ts_current)
! 	    context = cs;
! 	  else if (cs != NULL_TREE && TYPE_P (cs))
! 	    /* When declaring a friend class of a local class, we want
! 	       to inject the newly named class into the scope
! 	       containing the local class, not the namespace
! 	       scope.  */
! 	    context = decl_function_context (get_type_decl (cs));
  	}
+       if (!context)
+ 	context = current_namespace;
+ 
        if (b->kind == sk_class
! 	  || (b->kind == sk_template_parms
! 	      && b->level_chain->kind == sk_class))
! 	in_class = 1;
! 
!       if (current_lang_name == lang_name_java)
! 	TYPE_FOR_JAVA (type) = 1;
! 
!       tdef = create_implicit_typedef (name, type);
!       DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
!       if (scope == ts_within_enclosing_non_class)
  	{
! 	  /* This is a friend.  Make this TYPE_DECL node hidden from
! 	     ordinary name lookup.  Its corresponding TEMPLATE_DECL
! 	     will be marked in push_template_decl_real.  */
! 	  retrofit_lang_decl (tdef);
! 	  DECL_ANTICIPATED (tdef) = 1;
! 	  DECL_FRIEND_P (tdef) = 1;
! 	}
  
!       decl = maybe_process_template_type_declaration
! 	(type, scope == ts_within_enclosing_non_class, b);
!       if (decl == error_mark_node)
! 	POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
! 	  
!       if (! in_class)
! 	set_identifier_type_value_with_scope (name, tdef, b);
  
!       if (b->kind == sk_class)
! 	{
! 	  if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
! 	    /* Put this TYPE_DECL on the TYPE_FIELDS list for the
! 	       class.  But if it's a member template class, we want
! 	       the TEMPLATE_DECL, not the TYPE_DECL, so this is done
! 	       later.  */
! 	    finish_member_declaration (decl);
! 	  else
! 	    pushdecl_class_level (decl);
  	}
!       else if (b->kind != sk_template_parms)
! 	decl = pushdecl_with_scope (decl, b);
  
!       TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
  
!       /* If this is a local class, keep track of it.  We need this
! 	 information for name-mangling, and so that it is possible to
! 	 find all function definitions in a translation unit in a
! 	 convenient way.  (It's otherwise tricky to find a member
! 	 function definition it's only pointed to from within a local
! 	 class.)  */
!       if (TYPE_CONTEXT (type)
! 	  && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL)
! 	VEC_safe_push (tree, gc, local_classes, type);
!     }
!   if (b->kind == sk_class
!       && !COMPLETE_TYPE_P (current_class_type))
!     {
!       maybe_add_class_template_decl_list (current_class_type,
! 					  type, /*friend_p=*/0);
!       
!       if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
! 	CLASSTYPE_NESTED_UTDS (current_class_type)
! 	  = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
!       
!       binding_table_insert
! 	(CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
      }
+ 
+   decl = TYPE_NAME (type);
+   gcc_assert (TREE_CODE (decl) == TYPE_DECL);
+   TYPE_STUB_DECL (type) = decl;
+ 
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
  }
  
Index: testsuite/g++.dg/parse/crash28.C
===================================================================
RCS file: testsuite/g++.dg/parse/crash28.C
diff -N testsuite/g++.dg/parse/crash28.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/crash28.C	11 Aug 2005 09:22:41 -0000
***************
*** 0 ****
--- 1,14 ----
+ // Copyright (C) 2005 Free Software Foundation, Inc.
+ // Contributed by Nathan Sidwell 10 Aug 2005 <nathan@codesourcery.com>
+ 
+ // PR 23219, ICE
+ // Origin:Andrew Pinski <pinskia@gcc.gnu.org>
+ //        Volker Reichelt <reichelt@gcc.gnu.org>
+ 
+ template <class _Tp> class insert_iterator<slist<_Tp> > {}; // { dg-error "not a template|not declared in this scope|expected unqualified-id|extra" }
+ template <class _Value> class insert_iterator<int > { // { dg-error "template parameters not used|_Value" }
+   hash_set<_Value>; // { dg-error "no type|expected" }
+ };
+ 
+ template<int> struct A<X<> > {}; // { dg-error "not a template|not declared in this scope|expected unqualified-id|extra" }
+ struct A {}; // { dg-error "template argument required" }

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