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]

[PATCH] Fix PR c++/33207: ICE redeclaring namespace as struct


Hi all.

The following code snippet triggers an ICE with the mainline:

=== cut here ===
namespace N { }
struct N;
struct N* p;
=== cut here ===

The problem is that the type for 'struct N', when processed by
'pushtag', is not completely setup: we leave the function earlier
because we end up with error_mark_node after 'pushdecl_with_scope' since
N is already the name of a namespace. In particular, the type's
TYPE_STUB_DECL is not set, so it (and TYPE_MAIN_DECL) remains NULL_TREE.

When processing the declaration for 'p', in 'no_linkage_check', the
type's TYPE_MAIN_DECL is used to call 'decl_function_context', which
does not check if its argument is NULL_TREE or not before dereferencing
it, hence the ICE.

The attached patch fixes this by making sure that 'pushtag' properly
sets up TYPE even in case of error.

I have successfully regtested it on i386-apple-darwin8.10.1. Is it OK
for mainline?

Thanks in advance,
Simon

:ADDPATCH c++:





2007-09-08  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/33207
	* name-lookup.c (pushtag_finish_type): New helper function to pushtag
	to finish to setup TYPE.
	(pushtag): Use it, even in case of error.



Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 128174)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -4853,6 +4853,20 @@ maybe_process_template_type_declaration 
   return decl;
 }
 
+/* Helper function to pushtag. Finish to setup TYPE.  */
+
+static void
+pushtag_finish_type (tree type)
+{
+  tree decl = TYPE_NAME (type);
+  gcc_assert (TREE_CODE (decl) == TYPE_DECL);
+  TYPE_STUB_DECL (type) = decl;
+
+  /* Set type visibility now if this is a forward declaration.  */
+  TREE_PUBLIC (decl) = 1;
+  determine_visibility (decl);
+}
+
 /* Push a tag name NAME for struct/class/union/enum type TYPE.  In case
    that the NAME is a class template, the tag is processed but not pushed.
 
@@ -4942,7 +4956,10 @@ pushtag (tree name, tree type, tag_scope
       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);
+	{
+	  pushtag_finish_type (type);
+	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+	}
 
       if (! in_class)
 	set_identifier_type_value_with_scope (name, tdef, b);
@@ -4962,7 +4979,10 @@ pushtag (tree name, tree type, tag_scope
 	{
 	  decl = pushdecl_with_scope (decl, b, /*is_friend=*/false);
 	  if (decl == error_mark_node)
-	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
+	    {
+	      pushtag_finish_type (type);
+	      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+	    }
 	}
 
       TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
@@ -4991,13 +5011,7 @@ pushtag (tree name, tree type, tag_scope
 	(CLASSTYPE_NESTED_UTDS (current_class_type), name, type);
     }
 
-  decl = TYPE_NAME (type);
-  gcc_assert (TREE_CODE (decl) == TYPE_DECL);
-  TYPE_STUB_DECL (type) = decl;
-
-  /* Set type visibility now if this is a forward declaration.  */
-  TREE_PUBLIC (decl) = 1;
-  determine_visibility (decl);
+  pushtag_finish_type (type);
 
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
 }



2007-09-08  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/33207
	* g++.dg/parse/crash38.C: New test.



/* PR c++/33207  */
/* This used to ICE.  */

namespace N { } /* { dg-error "previous declaration" } */
struct N; /* { dg-error "redeclared as different kind of symbol" } */
struct N* p;




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