gcc-patches@gcc.gnu.org
[Top] [All Lists]

[C++ PATCH] Fix 23219

Subject: [C++ PATCH] Fix 23219
From: Nathan Sidwell
Date: Thu, 11 Aug 2005 10:26:02 +0100
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@xxxxxxxxxxxxxxxx    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-08-11  Nathan Sidwell  <nathan@xxxxxxxxxxxxxxxx>

        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@xxxxxxxxxxxxxxxx>

        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@xxxxxxxxxxxxxxxx>
+ 
+ // PR 23219, ICE
+ // Origin:Andrew Pinski <pinskia@xxxxxxxxxxx>
+ //        Volker Reichelt <reichelt@xxxxxxxxxxx>
+ 
+ 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" }
<Prev in Thread] Current Thread [Next in Thread>
  • [C++ PATCH] Fix 23219, Nathan Sidwell <=