[PATCH] Ensure start_source_file and end_source_file debug hook calls in gfortran always match (PR debug/33739)

Jakub Jelinek jakub@redhat.com
Thu Dec 6 17:34:00 GMT 2007


On Thu, Dec 06, 2007 at 11:49:09AM +0000, FX wrote:
> > But, I wonder if we can't just call the start/end file hooks right away
> > during reading of the files after moving gfc_define_undef_line handling
> > into the load_file loop.  We aren't calling any debug hooks during
> > parsing other than these start_source_file/end_source_file/define/undef
> > anyway, all other debug hooks are only called when we jump into trans_*
> > code.
> 
> It tried that approach before I first added the calls to start/end
> file hooks. It didn't work because debug hooks aren't yet set up when
> we get into load_file(), IIRC.

Attached are two approaches.
The second one calls the dbg hooks immediately during load_file, but moves
the gfc_new_file call later on after debug hooks are initialized.

The first one instead records the various file change events we want to
pass to debug_hooks in a vector, with gfc_linebuf pointers showing what
events should be reported at what line.

For DWARF{2,3} the output is equivalent between both approaches, but
for -gstabs -O0 it can make a difference, e.g. if whole subroutine/function
is defined in some included file, then with the first approach there will be
BINCL/EINCL notes, while with the second approach none.  See e.g. what
f951 generates with -fpreprocessed -g3 -O0 -dA on attached include_2.f90 (and
what for -m32 -fpreprocessed -g3 -gstabs -O0 -dA).

So, for stabs' sake I think the first approach is better, though of course
the second approach is simpler.

Regtested on x86_64-linux.

	Jakub
-------------- next part --------------
2007-12-06  Jakub Jelinek  <jakub@redhat.com>

	PR debug/33739
	* gfortran.h (gfc_file): Remove sibling and down fields.
	* scanner.c (file_changes, file_changes_cur, file_changes_count,
	file_changes_allocated): New variables.
	(add_file_change, report_file_change): New functions.
	(change_file): Remove.
	(gfc_start_source_files, gfc_end_source_files): Call
	report_file_change instead of change_file.
	(gfc_advance_line): Call report_file_change instead of change_file,
	call it even if lb->file == lb->next->file.
	(get_file): Revert last changes.
	(preprocessor_line): Call add_file_change when entering or leaving
	a file.
	(load_file): Likewise.  Set file_change[...].lb for all newly added
	file changes.

	* gfortran.dg/include_1.f90: New test.
	* gfortran.dg/include_1.inc: New.
	* gfortran.dg/include_2.f90: New test.

--- gcc/fortran/gfortran.h.jj	2007-12-05 21:42:07.000000000 +0100
+++ gcc/fortran/gfortran.h	2007-12-06 17:03:02.000000000 +0100
@@ -706,7 +706,7 @@ symbol_attribute;
 
 typedef struct gfc_file
 {
-  struct gfc_file *next, *up, *sibling, *down;
+  struct gfc_file *next, *up;
   int inclusion_line, line;
   char *filename;
 } gfc_file;
--- gcc/fortran/scanner.c.jj	2007-12-05 21:42:07.000000000 +0100
+++ gcc/fortran/scanner.c	2007-12-06 17:38:50.000000000 +0100
@@ -76,6 +76,15 @@ static char *gfc_src_preprocessor_lines[
 
 extern int pedantic;
 
+static struct gfc_file_change
+{
+  const char *filename;
+  gfc_linebuf *lb;
+  int line;
+} *file_changes;
+size_t file_changes_cur, file_changes_count;
+size_t file_changes_allocated;
+
 /* Main scanner initialization.  */
 
 void
@@ -300,29 +309,38 @@ gfc_at_eol (void)
 }
 
 static void
-change_file (gfc_file *to)
+add_file_change (const char *filename, int line)
 {
-  if (current_file == NULL)
-    return;
+  if (file_changes_count == file_changes_allocated)
+    {
+      if (file_changes_allocated)
+	file_changes_allocated *= 2;
+      else
+	file_changes_allocated = 16;
+      file_changes
+	= xrealloc (file_changes,
+		    file_changes_allocated * sizeof (*file_changes));
+    }
+  file_changes[file_changes_count].filename = filename;
+  file_changes[file_changes_count].lb = NULL;
+  file_changes[file_changes_count++].line = line;
+}
 
-  while (current_file != to)
-    if (current_file->down)
-      {
-	gfc_file *f = current_file->down;
-	/* Ensure we don't enter it ever again.  */
-	current_file->down = NULL;
-	current_file = f;
-	(*debug_hooks->start_source_file) (current_file->inclusion_line,
-					   current_file->filename);
-      }
-    else if (current_file->sibling)
-      current_file = current_file->sibling;
-    else
-      {
-	gcc_assert (current_file->up);
-	(*debug_hooks->end_source_file) (current_file->inclusion_line + 1);
-	current_file = current_file->up;
-      }
+static void
+report_file_change (gfc_linebuf *lb)
+{
+  size_t c = file_changes_cur;
+  while (c < file_changes_count
+	 && file_changes[c].lb == lb)
+    {
+      if (file_changes[c].filename)
+	(*debug_hooks->start_source_file) (file_changes[c].line,
+					   file_changes[c].filename);
+      else
+	(*debug_hooks->end_source_file) (file_changes[c].line);
+      ++c;
+    }
+  file_changes_cur = c;
 }
 
 void
@@ -333,27 +351,14 @@ gfc_start_source_files (void)
   if (debug_hooks->start_end_main_source_file)
     (*debug_hooks->start_source_file) (0, gfc_source_file);
 
-  if (gfc_current_locus.lb && gfc_current_locus.lb->file)
-    {
-      current_file = gfc_current_locus.lb->file;
-      while (current_file->up)
-	current_file = current_file->up;
-      change_file (gfc_current_locus.lb->file);
-    }
-  else
-    current_file = NULL;
+  file_changes_cur = 0;
+  report_file_change (gfc_current_locus.lb);
 }
 
 void
 gfc_end_source_files (void)
 {
-  if (current_file != NULL)
-    {
-      gfc_file *to = current_file;
-      while (to->up)
-	to = to->up;
-      change_file (to);
-    }
+  report_file_change (NULL);
 
   if (debug_hooks->start_end_main_source_file)
     (*debug_hooks->end_source_file) (0);
@@ -374,10 +379,9 @@ gfc_advance_line (void)
     } 
 
   if (gfc_current_locus.lb->next
-      && gfc_current_locus.lb->next->file != gfc_current_locus.lb->file
       && !gfc_current_locus.lb->next->dbg_emitted)
     {
-      change_file (gfc_current_locus.lb->next->file);
+      report_file_change (gfc_current_locus.lb->next);
       gfc_current_locus.lb->next->dbg_emitted = true;
     }
 
@@ -1264,23 +1268,8 @@ get_file (const char *name, enum lc_reas
   file_head = f;
 
   f->up = current_file;
-  /* Already cleared by gfc_getmem.
-     f->down = NULL;
-     f->sibling = NULL;  */
   if (current_file != NULL)
-    {
-      f->inclusion_line = current_file->line;
-      if (current_file->down == NULL)
-	current_file->down = f;
-      else
-	{
-	  gfc_file *s;
-
-	  for (s = current_file->down; s->sibling; s = s->sibling)
-	    ;
-	  s->sibling = f;
-	}
-    }
+    f->inclusion_line = current_file->line;
 
 #ifdef USE_MAPPED_LOCATION
   linemap_add (line_table, reason, false, f->filename, 1);
@@ -1390,6 +1379,7 @@ preprocessor_line (char *c)
   if (flag[1]) /* Starting new file.  */
     {
       f = get_file (filename, LC_RENAME);
+      add_file_change (f->filename, f->inclusion_line);
       current_file = f;
     }
 
@@ -1406,6 +1396,7 @@ preprocessor_line (char *c)
 	  return;
 	}
 
+      add_file_change (NULL, line);
       current_file = current_file->up;
 #ifdef USE_MAPPED_LOCATION
       linemap_add (line_table, LC_RENAME, false, current_file->filename,
@@ -1557,6 +1548,8 @@ load_file (const char *filename, bool in
   /* Load the file.  */
 
   f = get_file (filename, initial ? LC_RENAME : LC_ENTER);
+  if (!initial)
+    add_file_change (f->filename, f->inclusion_line);
   current_file = f;
   current_file->line = 1;
   line = NULL;
@@ -1654,6 +1647,9 @@ load_file (const char *filename, bool in
 	line_tail->next = b;
 
       line_tail = b;
+
+      while (file_changes_cur < file_changes_count)
+	file_changes[file_changes_cur++].lb = b;
     }
 
   /* Release the line buffer allocated in load_line.  */
@@ -1661,6 +1657,8 @@ load_file (const char *filename, bool in
 
   fclose (input);
 
+  if (!initial)
+    add_file_change (NULL, current_file->inclusion_line + 1);
   current_file = current_file->up;
 #ifdef USE_MAPPED_LOCATION
   linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
--- gcc/testsuite/gfortran.dg/include_1.inc.jj	2007-12-06 17:59:53.000000000 +0100
+++ gcc/testsuite/gfortran.dg/include_1.inc	2007-12-06 12:06:35.000000000 +0100
@@ -0,0 +1 @@
+integer :: i
--- gcc/testsuite/gfortran.dg/include_1.f90.jj	2007-12-06 17:59:47.000000000 +0100
+++ gcc/testsuite/gfortran.dg/include_1.f90	2007-12-06 18:00:56.000000000 +0100
@@ -0,0 +1,9 @@
+! PR debug/33739
+! { dg-do compile }
+! { dg-options "-g3" }
+subroutine a
+include 'include_1.inc'
+end subroutine a
+subroutine b
+include 'include_1.inc'
+end subroutine b
--- gcc/testsuite/gfortran.dg/include_2.f90.jj	2007-12-06 18:01:19.000000000 +0100
+++ gcc/testsuite/gfortran.dg/include_2.f90	2007-12-06 18:03:14.000000000 +0100
@@ -0,0 +1,29 @@
+# 1 "include_2.F90"
+# 1 "/tmp/"
+# 1 "<built-in>"
+# 1 "<command line>"
+# 1 "include_2.F90"
+#define S1 1
+#define B a
+# 1 "include_2.inc" 1
+subroutine a
+#undef S2
+#define S2 1
+integer :: i
+end subroutine a
+# 4 "include_2.F90" 2
+#undef B
+#define B b
+# 1 "include_2.inc" 1
+subroutine b
+#undef S2
+#define S2 1
+integer :: i
+end subroutine b
+# 6 "include_2.F90" 2
+! PR debug/33739
+! { dg-do link }
+! { dg-options "-fpreprocessed -g3" }
+    call a
+    call b
+end
-------------- next part --------------
--- gcc/fortran/scanner.c.jj	2007-12-05 21:42:07.000000000 +0100
+++ gcc/fortran/scanner.c	2007-12-06 16:36:58.000000000 +0100
@@ -299,66 +299,6 @@ gfc_at_eol (void)
   return (*gfc_current_locus.nextc == '\0');
 }
 
-static void
-change_file (gfc_file *to)
-{
-  if (current_file == NULL)
-    return;
-
-  while (current_file != to)
-    if (current_file->down)
-      {
-	gfc_file *f = current_file->down;
-	/* Ensure we don't enter it ever again.  */
-	current_file->down = NULL;
-	current_file = f;
-	(*debug_hooks->start_source_file) (current_file->inclusion_line,
-					   current_file->filename);
-      }
-    else if (current_file->sibling)
-      current_file = current_file->sibling;
-    else
-      {
-	gcc_assert (current_file->up);
-	(*debug_hooks->end_source_file) (current_file->inclusion_line + 1);
-	current_file = current_file->up;
-      }
-}
-
-void
-gfc_start_source_files (void)
-{
-  /* If the debugger wants the name of the main source file,
-     we give it.  */
-  if (debug_hooks->start_end_main_source_file)
-    (*debug_hooks->start_source_file) (0, gfc_source_file);
-
-  if (gfc_current_locus.lb && gfc_current_locus.lb->file)
-    {
-      current_file = gfc_current_locus.lb->file;
-      while (current_file->up)
-	current_file = current_file->up;
-      change_file (gfc_current_locus.lb->file);
-    }
-  else
-    current_file = NULL;
-}
-
-void
-gfc_end_source_files (void)
-{
-  if (current_file != NULL)
-    {
-      gfc_file *to = current_file;
-      while (to->up)
-	to = to->up;
-      change_file (to);
-    }
-
-  if (debug_hooks->start_end_main_source_file)
-    (*debug_hooks->end_source_file) (0);
-}
-
 /* Advance the current line pointer to the next line.  */
 
 void
@@ -373,14 +313,6 @@ gfc_advance_line (void)
       return;
     } 
 
-  if (gfc_current_locus.lb->next
-      && gfc_current_locus.lb->next->file != gfc_current_locus.lb->file
-      && !gfc_current_locus.lb->next->dbg_emitted)
-    {
-      change_file (gfc_current_locus.lb->next->file);
-      gfc_current_locus.lb->next->dbg_emitted = true;
-    }
-
   gfc_current_locus.lb = gfc_current_locus.lb->next;
 
   if (gfc_current_locus.lb != NULL)	 
@@ -441,28 +373,6 @@ skip_comment_line (void)
 }
 
 
-int
-gfc_define_undef_line (void)
-{
-  /* All lines beginning with '#' are either #define or #undef.  */
-  if (debug_info_level != DINFO_LEVEL_VERBOSE || gfc_peek_char () != '#')
-    return 0;
-
-  if (strncmp (gfc_current_locus.nextc, "#define ", 8) == 0)
-    (*debug_hooks->define) (gfc_linebuf_linenum (gfc_current_locus.lb),
-			    &(gfc_current_locus.nextc[8]));
-
-  if (strncmp (gfc_current_locus.nextc, "#undef ", 7) == 0)
-    (*debug_hooks->undef) (gfc_linebuf_linenum (gfc_current_locus.lb),
-			   &(gfc_current_locus.nextc[7]));
-
-  /* Skip the rest of the line.  */
-  skip_comment_line ();
-
-  return 1;
-}
-
-
 /* Comment lines are null lines, lines containing only blanks or lines
    on which the first nonblank line is a '!'.
    Return true if !$ openmp conditional compilation sentinel was
@@ -1264,23 +1174,8 @@ get_file (const char *name, enum lc_reas
   file_head = f;
 
   f->up = current_file;
-  /* Already cleared by gfc_getmem.
-     f->down = NULL;
-     f->sibling = NULL;  */
   if (current_file != NULL)
-    {
-      f->inclusion_line = current_file->line;
-      if (current_file->down == NULL)
-	current_file->down = f;
-      else
-	{
-	  gfc_file *s;
-
-	  for (s = current_file->down; s->sibling; s = s->sibling)
-	    ;
-	  s->sibling = f;
-	}
-    }
+    f->inclusion_line = current_file->line;
 
 #ifdef USE_MAPPED_LOCATION
   linemap_add (line_table, reason, false, f->filename, 1);
@@ -1390,6 +1285,7 @@ preprocessor_line (char *c)
   if (flag[1]) /* Starting new file.  */
     {
       f = get_file (filename, LC_RENAME);
+      (*debug_hooks->start_source_file) (f->inclusion_line, f->filename);
       current_file = f;
     }
 
@@ -1406,6 +1302,7 @@ preprocessor_line (char *c)
 	  return;
 	}
 
+      (*debug_hooks->end_source_file) (line);
       current_file = current_file->up;
 #ifdef USE_MAPPED_LOCATION
       linemap_add (line_table, LC_RENAME, false, current_file->filename,
@@ -1557,6 +1454,8 @@ load_file (const char *filename, bool in
   /* Load the file.  */
 
   f = get_file (filename, initial ? LC_RENAME : LC_ENTER);
+  if (!initial)
+    (*debug_hooks->start_source_file) (f->inclusion_line, f->filename);
   current_file = f;
   current_file->line = 1;
   line = NULL;
@@ -1610,12 +1509,21 @@ load_file (const char *filename, bool in
       if (line[0] == '#')
 	{
 	  /* When -g3 is specified, it's possible that we emit #define
-	     and #undef lines, which we need to pass to the middle-end
+	     and #undef lines, which we need to pass to a debug hook
 	     so that it can emit correct debug info.  */
-	  if (debug_info_level == DINFO_LEVEL_VERBOSE
-	      && (strncmp (line, "#define ", 8) == 0
-		  || strncmp (line, "#undef ", 7) == 0))
-	    ;
+	  if (strncmp (line + 1, "define ", 7) == 0
+	      || strncmp (line + 1, "undef ", 6) == 0)
+	    {
+	      if (debug_info_level == DINFO_LEVEL_VERBOSE)
+		{
+		  if (line[1] == 'd')
+		    (*debug_hooks->define) (current_file->line, line + 8);
+		  else
+		    (*debug_hooks->undef) (current_file->line, line + 7);
+		}
+	      current_file->line++;
+	      continue;
+	    }
 	  else
 	    {
 	      preprocessor_line (line);
@@ -1661,6 +1569,8 @@ load_file (const char *filename, bool in
 
   fclose (input);
 
+  if (!initial)
+    (*debug_hooks->end_source_file) (current_file->inclusion_line + 1);
   current_file = current_file->up;
 #ifdef USE_MAPPED_LOCATION
   linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
--- gcc/fortran/Make-lang.in.jj	2007-12-06 11:58:25.000000000 +0100
+++ gcc/fortran/Make-lang.in	2007-12-06 15:51:34.000000000 +0100
@@ -306,6 +306,7 @@ fortran/f95-lang.o: $(GFORTRAN_TRANS_DEP
   gt-fortran-f95-lang.h gtype-fortran.h $(CGRAPH_H) $(TARGET_H) \
   $(BUILTINS_DEF) fortran/types.def
 fortran/scanner.o: toplev.h
+fortran/parse.o: toplev.h
 fortran/convert.o: $(GFORTRAN_TRANS_DEPS)
 fortran/trans.o: $(GFORTRAN_TRANS_DEPS)
 fortran/trans-decl.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-decl.h \
--- gcc/fortran/parse.c.jj	2007-12-05 21:42:07.000000000 +0100
+++ gcc/fortran/parse.c	2007-12-06 15:50:30.000000000 +0100
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.  
 #include "match.h"
 #include "parse.h"
 #include "debug.h"
+#include "toplev.h"
 
 /* Current statement label.  Zero means no statement label.  Because new_st
    can get wiped during statement matching, we have to keep it separate.  */
@@ -674,9 +675,6 @@ next_statement (void)
 	  break;
 	}
 
-      if (gfc_define_undef_line ())
-	continue;
-
       st = (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free ();
 
       if (st != ST_NONE)
@@ -3289,7 +3287,13 @@ gfc_parse_file (void)
   gfc_statement st;
   locus prog_locus;
 
-  gfc_start_source_files ();
+  /* If the debugger wants the name of the main source file,
+     we give it.  */
+  if (debug_hooks->start_end_main_source_file)
+    (*debug_hooks->start_source_file) (0, gfc_source_file);
+
+  if (gfc_new_file () != SUCCESS)
+    fatal_error ("can't open input file: %s", gfc_source_file);
 
   top.state = COMP_NONE;
   top.sym = NULL;
@@ -3401,7 +3405,9 @@ loop:
   goto loop;
 
 done:
-  gfc_end_source_files ();
+  if (debug_hooks->start_end_main_source_file)
+    (*debug_hooks->end_source_file) (0);
+
   return SUCCESS;
 
 duplicate_main:
--- gcc/fortran/gfortran.h.jj	2007-12-05 21:42:07.000000000 +0100
+++ gcc/fortran/gfortran.h	2007-12-06 15:17:38.000000000 +0100
@@ -706,7 +706,7 @@ symbol_attribute;
 
 typedef struct gfc_file
 {
-  struct gfc_file *next, *up, *sibling, *down;
+  struct gfc_file *next, *up;
   int inclusion_line, line;
   char *filename;
 } gfc_file;
@@ -722,7 +722,6 @@ typedef struct gfc_linebuf
   struct gfc_linebuf *next;
 
   int truncated;
-  bool dbg_emitted;
 
   char line[1];
 } gfc_linebuf;
@@ -1923,7 +1922,6 @@ int gfc_at_bol (void);
 int gfc_at_eol (void);
 void gfc_advance_line (void);
 int gfc_check_include (void);
-int gfc_define_undef_line (void);
 
 void gfc_skip_comments (void);
 int gfc_next_char_literal (int);
@@ -1938,9 +1936,6 @@ extern gfc_source_form gfc_current_form;
 extern const char *gfc_source_file;
 extern locus gfc_current_locus;
 
-void gfc_start_source_files (void);
-void gfc_end_source_files (void);
-
 /* misc.c */
 void *gfc_getmem (size_t) ATTRIBUTE_MALLOC;
 void gfc_free (void *);
--- gcc/fortran/f95-lang.c.jj	2007-12-06 11:58:25.000000000 +0100
+++ gcc/fortran/f95-lang.c	2007-12-06 15:48:25.000000000 +0100
@@ -287,8 +287,6 @@ gfc_init (void)
   /* Then the frontend.  */
   gfc_init_1 ();
 
-  if (gfc_new_file () != SUCCESS)
-    fatal_error ("can't open input file: %s", gfc_source_file);
   return true;
 }
 


More information about the Gcc-patches mailing list