cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Aug 2005 09:23:57 +0000 (09:23 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Aug 2005 09:23:57 +0000 (09:23 +0000)
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.
testsuite:
PR c++/23219
* g++.dg/parse/crash28.C: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102982 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/crash28.C [new file with mode: 0644]

index 0aa5d7b..e904821 100644 (file)
@@ -1,3 +1,10 @@
+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-10  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/20646
index a03b648..79a6552 100644 (file)
@@ -4626,6 +4626,7 @@ tree
 pushtag (tree name, tree type, tag_scope scope)
 {
   struct cp_binding_level *b;
+  tree decl;
 
   timevar_push (TV_NAME_LOOKUP);
   b = current_binding_level;
@@ -4647,114 +4648,103 @@ pushtag (tree name, tree type, tag_scope scope)
                 || COMPLETE_TYPE_P (b->this_entity))))
     b = b->level_chain;
 
-  if (name)
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+  
+  /* Do C++ gratuitous typedefing.  */
+  if (IDENTIFIER_TYPE_VALUE (name) != type)
     {
-      /* 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;
+      tree tdef;
+      int in_class = 0;
+      tree context = TYPE_CONTEXT (type);
 
-         if (current_lang_name == lang_name_java)
-           TYPE_FOR_JAVA (type) = 1;
+      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;
 
-         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 (b->kind == sk_class
+         || (b->kind == sk_template_parms
+             && b->level_chain->kind == sk_class))
+       in_class = 1;
 
-         if (! in_class)
-           set_identifier_type_value_with_scope (name, d, b);
+      if (current_lang_name == lang_name_java)
+       TYPE_FOR_JAVA (type) = 1;
 
-         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))
+      tdef = create_implicit_typedef (name, type);
+      DECL_CONTEXT (tdef) = FROB_CONTEXT (context);
+      if (scope == ts_within_enclosing_non_class)
        {
-         maybe_add_class_template_decl_list (current_class_type,
-                                             type, /*friend_p=*/0);
+         /* 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;
+       }
 
-         if (CLASSTYPE_NESTED_UTDS (current_class_type) == NULL)
-           CLASSTYPE_NESTED_UTDS (current_class_type)
-             = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+      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);
 
-         binding_table_insert
-           (CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
+      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 (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
-    /* Use the canonical TYPE_DECL for this node.  */
-    TYPE_STUB_DECL (type) = TYPE_NAME (type);
-  else
+  if (b->kind == sk_class
+      && !COMPLETE_TYPE_P (current_class_type))
     {
-      /* 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);
+      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);
 }
 \f
index 8a29628..558456d 100644 (file)
@@ -1,3 +1,8 @@
+2005-08-11  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/23219
+       * g++.dg/parse/crash28.C: New.
+
 2005-08-11  Richard Guenther  <rguenther@suse.de>
 
        PR target/23289
diff --git a/gcc/testsuite/g++.dg/parse/crash28.C b/gcc/testsuite/g++.dg/parse/crash28.C
new file mode 100644 (file)
index 0000000..9c38f89
--- /dev/null
@@ -0,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" }