The problem:  Statement labels within a type declaration are put in the 
statement label tree belonging to the type declaration's namespace's (instead 
of the current namespace).  When the line is otherwise empty and an error is 
issued, gfc_free_st_label tries to delete the label from the label tree 
belonging to the current namespace and then frees the label structure, leaving 
an invalid statement label pointer in the type declaration's namespace's label 
tree.  When that namespace is cleaned up, bad things can happen.

The attached patch stores a namespace pointer in the statement label structure 
so that if a label is deleted early for some reason, it will be deleted from 
the proper namespace.

Louis



Attachment: empty_label_typedecl.f90
Description: Binary data

Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h      (revision 229302)
+++ gcc/fortran/gfortran.h      (working copy)
@@ -1291,6 +1291,8 @@ typedef struct gfc_st_label
   tree backend_decl;
 
   locus where;
+
+  gfc_namespace *ns;
 }
 gfc_st_label;
 
Index: gcc/fortran/io.c
===================================================================
--- gcc/fortran/io.c    (revision 229302)
+++ gcc/fortran/io.c    (working copy)
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 
 gfc_st_label
 format_asterisk = {0, NULL, NULL, -1, ST_LABEL_FORMAT, ST_LABEL_FORMAT, NULL,
-                  0, {NULL, NULL}};
+                  0, {NULL, NULL}, NULL};
 
 typedef struct
 {
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c        (revision 229302)
+++ gcc/fortran/symbol.c        (working copy)
@@ -2195,7 +2195,7 @@ gfc_free_st_label (gfc_st_label *label)
   if (label == NULL)
     return;
 
-  gfc_delete_bbt (&gfc_current_ns->st_labels, label, compare_st_labels);
+  gfc_delete_bbt (&label->ns->st_labels, label, compare_st_labels);
 
   if (label->format != NULL)
     gfc_free_expr (label->format);
@@ -2260,6 +2260,7 @@ gfc_get_st_label (int labelno)
   lp->value = labelno;
   lp->defined = ST_LABEL_UNKNOWN;
   lp->referenced = ST_LABEL_UNKNOWN;
+  lp->ns = ns;
 
   gfc_insert_bbt (&ns->st_labels, lp, compare_st_labels);
 

Reply via email to