diff mbox

gengtype improvements for plugins, thirdround! patch 3/7 [inputfile]

Message ID 20100921211217.df1ef337.basile@starynkevitch.net
State New
Headers show

Commit Message

Basile Starynkevitch Sept. 21, 2010, 7:12 p.m. UTC
Hello All,

[join work by Basile Starynkevitch & Jeremie Salvucci]

References: 
  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02060.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00616.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00663.html
  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02063.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00887.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01702.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01706.html

As I told in http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00808.html I
am continuing to send the complete patch series of our gengtype
work. This does not mean I am ignoring the recieved feedback.  I intend
to send a third round of patches once this "complete!" round is ended.

I am taking into account most of Laurynas comments in
http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00212.html with the
important exception of INPUT_FILE_MAGIC, discussed below.

Laurynas latter gave more feedback in
http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00887.html that we did
take into account.

The gengtype-lex.l & gengtype-parse.c files need to include fatal.h
because it is used from gengtype.h

Laurynas thinks that adding a magic number don't bring anything and is
just a temporary trick we (Jeremie & me Basile) used to code this
patch.  This is indeed true, but I (Basile) believe that this trick is
really useful to future gengtype hackers, since input files are
painfully reachable from types in a non-trivial way (and that very
fact is an occasion for bugs).  I would like opinion of other people,
in particular of reviewers, on that issue.  As I told before sending
our patch serie, gengtype is difficult to understand, and we insist on
defensive programming.  And this INPUT_FILE_MAGIC used in macro
CHECK_INPUT_FILE_MAGIC is exactly a case of defensive programming
(disabled unless ENABLE_CHECKING is configured).  It will be very
probably useful to future gengtype hackers, so I pray the allmighty
reviewers to consider accepting it.

The http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00842.html previous
version of this patch contained two variants, one with the
INPUT_FILE_MAGIC trick and one without.  I would prefer the magic
trick to be included, since it will definitely help any brave or
foolish :-) enough gengtype hacker.  If you really want me to remove
the trick before committing this patch, please ask.  Notice that since
I added the CHECK_INPUT_FILE_MAGIC macro, the trick don't need much
lines in the patch.


Since struct location_s is no longer used inside GCC, the hack in
new_structure to handle it is removed.
 
The attached patch is relative to the previous patch 2 [verbosity] sent

This relative patch was obtained with
 diff -u -p  -N $(svn stat | awk '/[AM]/{print $2}') \
     --from-file ../thirdround_02_verbosity/ > \
        $HOME/Gengtype_Thirdround/patch3_inputfile-relto02.diff

########## gcc/ChangeLog entry is
2010-09-20  Jeremie Salvucci  <jeremie.salvucci@free.fr>
	    Basile Starynkevitch  <basile@starynkevitch.net>

	* gengtype.c (get_output_file_name, plugin_files)
	(get_file_srcdir_relative_path, nb_plugin_files): moved to gengtype.h.
	(get_file_basename, get_file_realbasename, get_file_langdir): Use
	an input_file as argument.
	(error_at_line): Use input_file-s.
	(gt_files, num_gt_files, this_file, system_h_file): Declared as
	input_file-s.
	(lang_dir_names, num_lang_dirs): No static.
	(get_lang_bitmap, set_lang_bitmap): Moved to gengtype.h.
	(read_input_list): Use input_file-s.
	(new_structure): Remove location_s hack.
	(creat_field_all, get_file_realbasename)
	(get_file_srcdir_relative_path, get_file_basename)
	(get_file_langdir, get_file_gtfilename)
	(get_output_file_with_visibility, get_output_file_name)
	(put_mangled_filename): Use input_file-s.
	(struct flist): Removed name and added file field.
	(output_type_enum): Use input_file-s.
	(finish_root_table, write_roots): Use file not name field of
	struct flist.
	(dump_fileloc, parse_program_options): Use input_file-s.

	* gengtype.h (struct input_file_st, input_file): New structure and
	type.
	(INPUT_FILE_MAGIC, CHECK_INPUT_FILE_MAGIC): New macros.
	(gt_files, num_gt_files): New variables moved from gengtype.c.
	(this_file, system_h_file): New variables.
	(input_file_by_name): Declared new function.
	(get_input_file_name): New inline function.
	(get_lang_bitmap, set_lang_bitmap): Moved from gengtype.c and
	updated.
	(struct fileloc): field file changed type.
	(lang_dir_names, num_lang_dirs): moved from gengtype.c.
	(get_output_file_with_visibility, get_output_file_name): Use
	input_file-s.

	* gengtype-lex.l:  Updated copyright year. Included errors.h.
	(yybegin): use input_file-s.

	* gengtype-parse.c:   Updated copyright year. Included errors.h.
	(parse_error): Use input_file-s.
	(type): Generate anonymous names differently for GCC source input
	and other input.

##########


Regards.

Comments

Laurynas Biveinis Sept. 22, 2010, 2:23 a.m. UTC | #1
2010/9/21 Basile Starynkevitch <basile@starynkevitch.net>:
> The gengtype-lex.l & gengtype-parse.c files need to include fatal.h
> because it is used from gengtype.h

OK. In that case bonus points for a follow-up patch that includes
fatal.h from gengtype.h and updates Makefile accordingly :)

> Since struct location_s is no longer used inside GCC, the hack in
> new_structure to handle it is removed.

This is excellent, but it really should be a separate patch.

-/* The plugin input files and their number; in that case only
-   a single file is produced.  */
-static char** plugin_files;
+/* The plugin input files and their number; in plugin mode only a
+   single file is produced.  */
+static input_file** plugin_files;

Please remove the comment part after semicolon (the comment should
explain plugin_files definition, the numer of output files is
irrelevant to that definition)

-/* The gt- output file name for F.  */
+/* The gt- output file name for INPF.  */

 static const char *
-get_file_gtfilename (const char *f)
+get_file_gtfilename (const input_file *inpf)

Drop the empty line between the comment and the definition.

@@ -4424,89 +4384,142 @@ print_version (void)
 static void
 parse_program_options (int argc, char**argv)
 {
-    int opt = -1;
+  int opt = -1;
[...two hundred lines or so of indentation changes follow...]

These parse_program_options changes only fix indentation in the first
patch, so please fix the first patch and this will disappear. If there
were any real code changes here, I couldn't tell through all those
formatting changes.

-      for (i = 0; i < num_gt_files; i++) {
-	parse_file (gt_files[i]);
-	DBGPRINTF ("parsed file #%d %s", (int) i, gt_files[i]);
-      }
+      for (i = 0; i < num_gt_files; i++)
+	{
+	  parse_file (get_input_file_name (gt_files[i]));
+	  DBGPRINTF ("parsed file #%d %s", (int) i, get_input_file_name
(gt_files[i]));
+	}

Same here. (Here at least I can see the non-formatting code change)

+	    if (relp)
+	      /* The input file is a GCC source file, we use a double
+		 colon after anonymous.  To be sure s is truly unique,
+		 we also use anonymous_count.  */
+	      s = xasprintf ("anonymous::%s:%d::%d",
+			     relp, lexer_line.line, anonymous_count);
+	    else
+	      /* The input file is outside of GCC source tree, we use
+		 a single colon after anonymous.  To be sure s is
+		 truly unique, we also use anonymous_count.  */
+	      s = xasprintf ("anonymous:%s:%d::%d",
+			     get_input_file_name (lexer_line.file),
+			     lexer_line.line, anonymous_count);

Here and in similar following fragments, please add { } on if and else
clauses (too many visual lines).

As far as I'm concerned, the non-magic patch would be OK with these changes.

> ########## gcc/ChangeLog entry is
> 2010-09-20  Jeremie Salvucci  <jeremie.salvucci@free.fr>
>            Basile Starynkevitch  <basile@starynkevitch.net>
>
>        * gengtype.c (get_output_file_name, plugin_files)
>        (get_file_srcdir_relative_path, nb_plugin_files): moved to gengtype.h.
>        (get_file_basename, get_file_realbasename, get_file_langdir): Use
>        an input_file as argument.
>        (error_at_line): Use input_file-s.
>        (gt_files, num_gt_files, this_file, system_h_file): Declared as
>        input_file-s.
>        (lang_dir_names, num_lang_dirs): No static.
>        (get_lang_bitmap, set_lang_bitmap): Moved to gengtype.h.
>        (read_input_list): Use input_file-s.
>        (new_structure): Remove location_s hack.
>        (creat_field_all, get_file_realbasename)
>        (get_file_srcdir_relative_path, get_file_basename)
>        (get_file_langdir, get_file_gtfilename)
>        (get_output_file_with_visibility, get_output_file_name)
>        (put_mangled_filename): Use input_file-s.
>        (struct flist): Removed name and added file field.
>        (output_type_enum): Use input_file-s.
>        (finish_root_table, write_roots): Use file not name field of
>        struct flist.
>        (dump_fileloc, parse_program_options): Use input_file-s.
>
>        * gengtype.h (struct input_file_st, input_file): New structure and
>        type.
>        (INPUT_FILE_MAGIC, CHECK_INPUT_FILE_MAGIC): New macros.
>        (gt_files, num_gt_files): New variables moved from gengtype.c.
>        (this_file, system_h_file): New variables.
>        (input_file_by_name): Declared new function.
>        (get_input_file_name): New inline function.
>        (get_lang_bitmap, set_lang_bitmap): Moved from gengtype.c and
>        updated.
>        (struct fileloc): field file changed type.
>        (lang_dir_names, num_lang_dirs): moved from gengtype.c.
>        (get_output_file_with_visibility, get_output_file_name): Use
>        input_file-s.
>
>        * gengtype-lex.l:  Updated copyright year. Included errors.h.
>        (yybegin): use input_file-s.
>
>        * gengtype-parse.c:   Updated copyright year. Included errors.h.
>        (parse_error): Use input_file-s.
>        (type): Generate anonymous names differently for GCC source input
>        and other input.
diff mbox

Patch

--- ../thirdround_02_verbosity//gengtype.c	2010-09-20 22:35:07.000000000 +0200
+++ gcc/gengtype.c	2010-09-21 11:02:01.000000000 +0200
@@ -123,7 +123,6 @@  struct type
 
 
 
-const char *get_output_file_name (const char *);
 
 
 /* The list of output files.  */
@@ -137,12 +136,12 @@  outf_p header_file;
 /* The name of the file containing the list of input files.  */
 static char* inputlist;
 
-/* The plugin input files and their number; in that case only
-   a single file is produced.  */
-static char** plugin_files;
+/* The plugin input files and their number; in plugin mode only a
+   single file is produced.  */
+static input_file** plugin_files;
 static size_t nb_plugin_files;
 
-/* the generated plugin output file and name.  */
+/* the generated plugin output file and name in plugin mode.  */
 static outf_p plugin_output;
 static char* plugin_output_filename;
 
@@ -169,12 +168,11 @@  static const char* backup_dir;
 
 static outf_p create_file (const char *, const char *);
 
-static const char * get_file_basename (const char *);
-static const char * get_file_realbasename (const char *);
-static const char * get_file_srcdir_relative_path (const char *);
+static const char * get_file_basename (const input_file *);
+static const char * get_file_realbasename (const input_file *);
 
 static int get_prefix_langdir_index (const char *);
-static const char * get_file_langdir (const char *);
+static const char * get_file_langdir (const input_file *);
 
 
 /* Nonzero iff an error has occurred.  */
@@ -194,7 +192,8 @@  error_at_line (const struct fileloc *pos
 
   va_start (ap, msg);
 
-  fprintf (stderr, "%s:%d: ", pos->file, pos->line);
+  gcc_assert (pos != NULL && pos->file != NULL);
+  fprintf (stderr, "%s:%d: ", get_input_file_name (pos->file), pos->line);
   vfprintf (stderr, msg, ap);
   fputc ('\n', stderr);
   hit_error = true;
@@ -222,68 +221,24 @@  xasprintf (const char *format, ...)
 /* Input file handling. */
 
 /* Table of all input files.  */
-static const char **gt_files;
-static size_t num_gt_files;
+input_file** gt_files;
+size_t num_gt_files;
 
-/* A number of places use the name of this "gengtype.h" file for a
+/* A number of places use the name of this "gengtype.c" file for a
    location for things that we can't rely on the source to define.
-   Make sure we can still use pointer comparison on filenames.  */
-const char this_file[] = __FILE__;
+   Initialized early in main.  */
+input_file* this_file;
 /* The "system.h" file is likewise specially useful.  */
-const char system_h_file[] = "system.h";
+input_file* system_h_file;
 
 /* Vector of per-language directories.  */
-static const char **lang_dir_names;
-static size_t num_lang_dirs;
+const char **lang_dir_names;
+size_t num_lang_dirs;
 
 /* An array of output files suitable for definitions.  There is one
    BASE_FILES entry for each language.  */
 static outf_p *base_files;
 
-/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
-   INPUT_FILE is used by <lang>.
-
-   This function should be written to assume that a file _is_ used
-   if the situation is unclear.  If it wrongly assumes a file _is_ used,
-   a linker error will result.  If it wrongly assumes a file _is not_ used,
-   some GC roots may be missed, which is a much harder-to-debug problem.
-
-   The relevant bitmap is stored immediately before the file's name in the
-   buffer set up by read_input_list.  It may be unaligned, so we have to
-   read it byte-by-byte.  */
-
-static lang_bitmap
-get_lang_bitmap (const char *gtfile)
-{
-
-  if (gtfile == this_file || gtfile == system_h_file)
-    /* Things defined in this "gengtype.c" file or in "system.h" are
-       universal (and there is no space for their lang_bitmap before
-       their file names).  */
-    return (((lang_bitmap)1) << num_lang_dirs) - 1;
-  else
-    {
-      lang_bitmap n = 0;
-      int i;
-      for (i = -(int) sizeof (lang_bitmap); i < 0; i++)
-	n = (n << CHAR_BIT) + (unsigned char)gtfile[i];
-      return n;
-    }
-}
-
-/* Set the bitmap returned by get_lang_bitmap.  The only legitimate
-   caller of this function is read_input_list.  */
-static void
-set_lang_bitmap (char *gtfile, lang_bitmap n)
-{
-  int i;
-  for (i = -1; i >= -(int) sizeof (lang_bitmap); i--)
-    {
-      gtfile[i] = n & ((1U << CHAR_BIT)-1);
-      n >>= CHAR_BIT;
-    }
-}
-
 
 #if ENABLE_CHECKING
 /* Utility debugging function, printing the various type counts within
@@ -477,11 +432,11 @@  read_input_list (const char *listname)
       size_t nfiles = 0;
       lang_bitmap curlangs = (1 << num_lang_dirs) - 1;
 
-      epos.file = listname;
+      epos.file = input_file_by_name (listname);
       epos.line = 0;
 
       lang_dir_names = XNEWVEC (const char *, num_lang_dirs);
-      gt_files = XNEWVEC (const char *, num_gt_files);
+      gt_files = XNEWVEC (input_file *, num_gt_files);
 
       for (;;)
 	{
@@ -511,13 +466,16 @@  read_input_list (const char *listname)
 	  else
 	    {
 	      size_t i;
+	      input_file *inpf = input_file_by_name (line);
 	      gcc_assert (nfiles <= num_gt_files);
 	      for (i = 0; i < nfiles; i++)
-		if (strcmp (gt_files[i], line) == 0)
+		/* Since the input_file-s are uniquely hash-consed, we
+		   can just compare pointers! */
+		if (gt_files[i] == inpf)
 		  {
 		    /* Throw away the string we just read, and add the
 		       current language to the existing string's bitmap.  */
-		    lang_bitmap bmap = get_lang_bitmap (gt_files[i]);
+		    lang_bitmap bmap = get_lang_bitmap (inpf);
 		    if (bmap & curlangs)
 		      error_at_line (&epos, "file %s specified more than once "
 				     "for language %s", line, langno == 0
@@ -525,13 +483,13 @@  read_input_list (const char *listname)
 				     : lang_dir_names[langno - 1]);
 
 		    bmap |= curlangs;
-		    set_lang_bitmap (CONST_CAST(char *, gt_files[i]), bmap);
+		    set_lang_bitmap (inpf, bmap);
 		    here = committed;
 		    goto next_line;
 		  }
 
-	      set_lang_bitmap (line, curlangs);
-	      gt_files[nfiles++] = line;
+	      set_lang_bitmap (inpf, curlangs);
+	      gt_files[nfiles++] = inpf;
 	    }
 	}
       /* Update the global counts now that we know accurately how many
@@ -750,21 +708,6 @@  new_structure (const char *name, int isu
   if (s->u.s.lang_struct)
     s->u.s.lang_struct->u.s.bitmap |= bitmap;
 
-  /* Reset location_s's location to input.h so that we know where to
-     write out its mark routine.  */
-  if (!strcmp (name, "location_s") && !isunion
-      && pos->file == this_file)
-    {
-      size_t n;
-      for (n = 0; n < num_gt_files; n++)
-	if (!strcmp (gt_files[n] + strlen (gt_files[n]) - strlen ("input.h"),
-		     "input.h"))
-	  {
-	    s->u.s.line.file = gt_files[n];
-	    break;
-	  }
-    }
-
     return s;
 }
 
@@ -902,7 +845,7 @@  note_variable (const char *s, type_p t,
 /* Most-general structure field creator.  */
 static pair_p
 create_field_all (pair_p next, type_p type, const char *name, options_p opt,
-		  const char *file, int line)
+		  const input_file* inpf, int line)
 {
   pair_p field;
 
@@ -911,7 +854,7 @@  create_field_all (pair_p next, type_p ty
   field->type = type;
   field->name = name;
   field->opt = opt;
-  field->line.file = file;
+  field->line.file = inpf;
   field->line.line = line;
   return field;
 }
@@ -1667,8 +1610,9 @@  open_base_files (void)
    components skipped.  */
 
 static const char *
-get_file_realbasename (const char *f)
+get_file_realbasename (const input_file *inpf)
 {
+  const char* f = get_input_file_name (inpf);
   const char * lastslash = strrchr (f, '/');
 
   return (lastslash != NULL) ? lastslash + 1 : f;
@@ -1677,26 +1621,28 @@  get_file_realbasename (const char *f)
 /* For F a filename, return the relative path to F from $(srcdir) if the
    latter is a prefix in F, NULL otherwise.  */
 
-static const char *
-get_file_srcdir_relative_path (const char *f)
+const char *
+get_file_srcdir_relative_path (const input_file *inpf)
 {
-  if (strlen (f) > srcdir_len
-      && IS_DIR_SEPARATOR (f[srcdir_len])
-      && memcmp (f, srcdir, srcdir_len) == 0)
-    return f + srcdir_len + 1;
+  const char* fname = get_input_file_name (inpf);
+  if (strlen (fname) > srcdir_len
+      && IS_DIR_SEPARATOR (fname[srcdir_len])
+      && memcmp (fname, srcdir, srcdir_len) == 0)
+    return fname + srcdir_len + 1;
   else
     return NULL;
 }
 
-/* For F a filename, return the relative path to F from $(srcdir) if the
-   latter is a prefix in F, or the real basename of F otherwise.  */
+/* For INPF an input_file, return the relative path to INPF from
+   $(srcdir) if the latter is a prefix in INPF, or the real basename
+   of INPF otherwise.  */
 
 static const char *
-get_file_basename (const char *f)
+get_file_basename (const input_file *inpf)
 {
-  const char * srcdir_path = get_file_srcdir_relative_path (f);
+  const char * srcdir_path = get_file_srcdir_relative_path (inpf);
 
-  return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (f);
+  return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (inpf);
 }
 
 /* For F a filename, return the lang_dir_names relative index of the language
@@ -1722,19 +1668,19 @@  get_prefix_langdir_index (const char *f)
   return -1;
 }
 
-/* For F a filename, return the name of language directory where F is located,
-   if any, NULL otherwise.  */
 
+/* For INPF an input_file, return the name of language directory where
+   INPF is located, if any, NULL otherwise.  */
 static const char *
-get_file_langdir (const char *f)
+get_file_langdir (const input_file *inpf)
 {
   /* Get the relative path to F from $(srcdir) and find the language by
      comparing the prefix with language directory names.  If F is not even
      srcdir relative, no point in looking further.  */
 
   int lang_index;
-  const char * srcdir_relative_path = get_file_srcdir_relative_path (f);
-  const char * r;
+  const char *srcdir_relative_path = get_file_srcdir_relative_path (inpf);
+  const char *r;
 
   if (!srcdir_relative_path)
     return NULL;
@@ -1751,16 +1697,16 @@  get_file_langdir (const char *f)
   return r;
 }
 
-/* The gt- output file name for F.  */
+/* The gt- output file name for INPF.  */
 
 static const char *
-get_file_gtfilename (const char *f)
+get_file_gtfilename (const input_file *inpf)
 {
   /* Cook up an initial version of the gt- file name from the file real
      basename and the language name, if any.  */
 
-  const char *basename = get_file_realbasename (f);
-  const char *langdir = get_file_langdir (f);
+  const char *basename = get_file_realbasename (inpf);
+  const char *langdir = get_file_langdir (inpf);
 
   char * result =
     (langdir ? xasprintf ("gt-%s-%s", langdir, basename)
@@ -1786,7 +1732,7 @@  get_file_gtfilename (const char *f)
    INPUT_FILE.  */
 
 outf_p
-get_output_file_with_visibility (const char *input_file)
+get_output_file_with_visibility (input_file* inpf)
 {
   outf_p r;
   size_t len;
@@ -1797,30 +1743,30 @@  get_output_file_with_visibility (const c
   /* This can happen when we need a file with visibility on a
      structure that we've never seen.  We have to just hope that it's
      globally visible.  */
-  if (input_file == NULL)
-    input_file = "system.h";
+  if (inpf == NULL)
+    inpf = system_h_file;
 
-  /* In plugin mode, return NULL unless the input_file is one of the
-     plugin_files.  */
+  /* In plugin mode, return NULL unless the INPF is one of the
+     plugin_files.  We can compare input_file-s by pointer equality.  */
   if (plugin_files)
     {
       size_t i;
       for (i = 0; i < nb_plugin_files; i++)
-	if (strcmp (input_file, plugin_files[i]) == 0)
+	if (inpf == plugin_files[i])
 	  return plugin_output;
 
       return NULL;
     }
 
   /* Determine the output file name.  */
-  basename = get_file_basename (input_file);
+  basename = get_file_basename (inpf);
 
   len = strlen (basename);
   if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
       || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
       || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
     {
-      output_name = get_file_gtfilename (input_file);
+      output_name = get_file_gtfilename (inpf);
       for_name = basename;
     }
   /* Some headers get used by more than one front-end; hence, it
@@ -1872,13 +1818,13 @@  get_output_file_with_visibility (const c
 }
 
 /* The name of an output file, suitable for definitions, that can see
-   declarations made in INPUT_FILE and is linked into every language
-   that uses INPUT_FILE.  */
+   declarations made in INPF and is linked into every language
+   that uses INPF.  */
 
 const char *
-get_output_file_name (const char *input_file)
+get_output_file_name (input_file *inpf)
 {
-  outf_p o =  get_output_file_with_visibility (input_file);
+  outf_p o =  get_output_file_with_visibility (inpf);
   if (o)
     return o->name;
   return NULL;
@@ -1970,7 +1916,7 @@  close_output_files (void)
 struct flist {
   struct flist *next;
   int started_p;
-  const char *name;
+  const input_file *file;
   outf_p f;
 };
 
@@ -2019,7 +1965,7 @@  static void write_local (outf_p output_h
 			 type_p param_structs);
 static void write_enum_defn (type_p structures, type_p param_structs);
 static int contains_scalar_p (type_p t);
-static void put_mangled_filename (outf_p , const char *);
+static void put_mangled_filename (outf_p, const input_file *);
 static void finish_root_table (struct flist *flp, const char *pfx,
 			       const char *tname, const char *lastname,
 			       const char *name);
@@ -2490,7 +2436,7 @@  walk_type (type_p t, struct walk_type_da
 	      {
 		fprintf (stderr,
 	"%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
-			 d->line->file, d->line->line, f->name);
+			 get_input_file_name (d->line->file), d->line->line, f->name);
 		continue;
 	      }
 	    else if (union_p && ! (default_p || tagid))
@@ -2658,16 +2604,27 @@  output_type_enum (outf_p of, type_p s)
 static outf_p
 get_output_file_for_structure (const_type_p s, type_p *param)
 {
-  const char * fn = s->u.s.line.file;
+  const input_file* fn = NULL;
   int i;
 
+  if (UNION_OR_STRUCT_P (s))
+    fn = s->u.s.line.file;
+  else if (s->kind == TYPE_PARAM_STRUCT)
+    fn = s->u.param_struct.line.file;
+
+  CHECK_INPUT_FILE_MAGIC (fn);
+
   /* This is a hack, and not the good kind either.  */
   for (i = NUM_PARAM - 1; i >= 0; i--)
     if (param && param[i] && param[i]->kind == TYPE_POINTER
 	&& UNION_OR_STRUCT_P (param[i]->u.p))
       fn = param[i]->u.p->u.s.line.file;
 
-  return get_output_file_with_visibility (fn);
+  CHECK_INPUT_FILE_MAGIC (fn);
+
+  /* The call to get_output_file_with_visibility may update fn by
+     caching its result inside, so we need the CONST_CAST.  */
+  return get_output_file_with_visibility (CONST_CAST (input_file*, fn));
 }
 
 /* For S, a structure that's part of ORIG_S, and using parameters
@@ -3248,9 +3205,12 @@  contains_scalar_p (type_p t)
 /* Mangle FN and print it to F.  */
 
 static void
-put_mangled_filename (outf_p f, const char *fn)
+put_mangled_filename (outf_p f, const input_file *inpf)
 {
-  const char *name = get_output_file_name (fn);
+  /* The call to get_output_file_name may indirectly update fn since
+     get_output_file_with_visibility caches its result inside, so we
+     need the CONST_CAST.  */
+  const char *name = get_output_file_name (CONST_CAST (input_file*, inpf));
   if (!f || !name)
     return;
   for (; *name != 0; name++)
@@ -3280,7 +3240,7 @@  finish_root_table (struct flist *flp, co
   for (fli2 = flp; fli2 && base_files; fli2 = fli2->next)
     if (fli2->started_p)
       {
-	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
+	lang_bitmap bitmap = get_lang_bitmap (fli2->file);
 	int fnum;
 
 	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
@@ -3289,7 +3249,7 @@  finish_root_table (struct flist *flp, co
 	      oprintf (base_files[fnum],
 		       "extern const struct %s gt_%s_",
 		       tname, pfx);
-	      put_mangled_filename (base_files[fnum], fli2->name);
+	      put_mangled_filename (base_files[fnum], fli2->file);
 	      oprintf (base_files[fnum], "[];\n");
 	    }
       }
@@ -3306,7 +3266,7 @@  finish_root_table (struct flist *flp, co
   for (fli2 = flp; fli2; fli2 = fli2->next)
     if (fli2->started_p)
       {
-	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
+	lang_bitmap bitmap = get_lang_bitmap (fli2->file);
 	int fnum;
 
 	fli2->started_p = 0;
@@ -3315,7 +3275,7 @@  finish_root_table (struct flist *flp, co
 	  if (bitmap & 1)
 	    {
 	      oprintf (base_files[fnum], "  gt_%s_", pfx);
-	      put_mangled_filename (base_files[fnum], fli2->name);
+	      put_mangled_filename (base_files[fnum], fli2->file);
 	      oprintf (base_files[fnum], ",\n");
 	    }
       }
@@ -3651,8 +3611,8 @@  write_roots (pair_p variables, bool emit
 	  fli->f = f;
 	  fli->next = flp;
 	  fli->started_p = 0;
-	  fli->name = v->line.file;
-	  gcc_assert(fli->name);
+	  fli->file = v->line.file;
+	  gcc_assert (fli->file);
 	  flp = fli;
 
 	  oprintf (f, "\n/* GC roots.  */\n\n");
@@ -4190,8 +4150,8 @@  dump_options (int indent, options_p opt)
 static void
 dump_fileloc (int indent, struct fileloc line)
 {
-  printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', line.file,
-	  line.line);
+  printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ',
+	  get_input_file_name (line.file), line.line);
 }
 
 /* Recursively dumps the struct, union, or a language-specific
@@ -4424,89 +4384,142 @@  print_version (void)
 static void
 parse_program_options (int argc, char**argv)
 {
-    int opt = -1;
+  int opt = -1;
   while ((opt = getopt_long (argc, argv, "hvVdP:S:B:I:w:r:D",
-			       gengtype_long_options, NULL)) >= 0)
+			     gengtype_long_options, NULL)) >= 0)
     {
-	switch (opt)
+      switch (opt)
 	{
 	case 'h': /* --help */
-	    print_usage ();
-	    break;
+	  print_usage ();
+	  break;
 	case 'v': /* --verbose */
 	  verbosity_level++;
 	  break;
 	case 'V': /* --version */
-	    print_version ();
-	    break;
+	  print_version ();
+	  break;
 	case 'd': /* --dump */
-      do_dump = 1;
-	    break;
+	  do_dump = 1;
+	  break;
 	case 'D': /* --debug */
-	    do_debug = 1;
-	    break;
+	  do_debug = 1;
+	  break;
 	case 'P': /* --plugin */
-	    if (optarg)
-		plugin_output_filename = optarg;
-	    else
-		fatal ("missing plugin output file name");
-	    break;
+	  if (optarg)
+	    plugin_output_filename = optarg;
+	  else
+	    fatal ("missing plugin output file name");
+	  break;
 	case 'S': /* --srcdir */
-	    if (optarg)
-		srcdir = optarg;
-	    else
-		fatal ("missing source directory");
-	    srcdir_len = strlen (srcdir);
-	    break;
+	  if (optarg)
+	    srcdir = optarg;
+	  else
+	    fatal ("missing source directory");
+	  srcdir_len = strlen (srcdir);
+	  break;
 	case 'B': /* --backupdir */
-	    if (optarg)
-		srcdir = optarg;
-	    else
-		fatal ("missing backup directory");
-	    srcdir_len = strlen (srcdir);
-	    break;
+	  if (optarg)
+	    srcdir = optarg;
+	  else
+	    fatal ("missing backup directory");
+	  srcdir_len = strlen (srcdir);
+	  break;
 	case 'I': /* --inputs */
-	    if (optarg)
-		inputlist = optarg;
-	    else
-		fatal ("missing input list");
-	    break;
+	  if (optarg)
+	    inputlist = optarg;
+	  else
+	    fatal ("missing input list");
+	  break;
 	case 'r': /* --read-state */
-	    if (optarg)
-		read_state_filename = optarg;
-	    else
-		fatal ("missing read state file");
-	    DBGPRINTF ("read state %s\n", optarg);
-	    break;
+	  if (optarg)
+	    read_state_filename = optarg;
+	  else
+	    fatal ("missing read state file");
+	  DBGPRINTF ("read state %s\n", optarg);
+	  break;
 	case 'w': /* --write-state */
-	    DBGPRINTF ("write state %s\n", optarg);
-	    if (optarg)
-		write_state_filename = optarg;
-	    else
-		fatal ("missing write state file");
-	    break;
+	  DBGPRINTF ("write state %s\n", optarg);
+	  if (optarg)
+	    write_state_filename = optarg;
+	  else
+	    fatal ("missing write state file");
+	  break;
 	default:
-	    fprintf (stderr, "%s: unknown flag '%c'\n", progname, opt);
-	    print_usage ();
-	    fatal ("unexpected flag");
-    }
+	  fprintf (stderr, "%s: unknown flag '%c'\n", progname, opt);
+	  print_usage ();
+	  fatal ("unexpected flag");
+	}
     };
-    if (plugin_output_filename)
+  if (plugin_output_filename)
     {
-	/* In plugin mode we require some input files.  */
-	int i = 0;
-	if (optind >= argc)
-	    fatal ("no source files given in plugin mode");
-	nb_plugin_files = argc - optind;
-	for (i = 0; i < (int) nb_plugin_files; i++)
-      {
-	    char *name = argv[i + optind];
-	    plugin_files[i] = name;
-      }
+      /* In plugin mode we require some input files.  */
+      int i = 0;
+      if (optind >= argc)
+	fatal ("no source files given in plugin mode");
+      nb_plugin_files = argc - optind;
+      for (i = 0; i < (int) nb_plugin_files; i++)
+	{
+	  char *name = argv[i + optind];
+	  plugin_files[i] = input_file_by_name (name);
+	}
     }
 }
 
 
+
+/******* Manage input files.  ******/
+
+/* Hash table of unique input file names.  */
+static htab_t input_file_htab;
+
+/* Find or allocate a new input_file by hash-consing it.  */
+input_file*
+input_file_by_name (const char* name)
+{
+  PTR* slot;
+  input_file* f = NULL;
+  int namlen = 0;
+  if (!name)
+    return NULL;
+  namlen = strlen (name);
+  f = XCNEWVAR (input_file, sizeof (input_file)+namlen+2);
+  f->inpbitmap = 0;
+  f->inpoutf = NULL;
+  f->inpmagic = INPUT_FILE_MAGIC;
+  strcpy (f->inpname, name);
+  slot = htab_find_slot (input_file_htab, f, INSERT);
+  gcc_assert (slot != NULL);
+  if (*slot)
+    {
+      /* Already known input file.  */
+      free (f);
+      return (input_file*)(*slot);
+    }
+  /* New input file.  */
+  *slot = f;
+  return f;
+}
+
+/* Hash table support routines for input_file-s.  */
+static hashval_t
+htab_hash_inputfile (const void *p)
+{
+  const input_file *inpf = (const input_file *) p;
+  gcc_assert (inpf);
+  return htab_hash_string (get_input_file_name (inpf));
+}
+
+static int
+htab_eq_inputfile (const void *x, const void *y)
+{
+  const input_file *inpfx = (const input_file *) x;
+  const input_file *inpfy = (const input_file *) y;
+  gcc_assert (inpfx != NULL && inpfy != NULL);
+  return !strcmp (get_input_file_name (inpfx), get_input_file_name (inpfy));
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -4519,6 +4532,12 @@  main (int argc, char **argv)
   /* Set the scalar_is_char union number for predefined scalar types.  */
   scalar_nonchar.u.scalar_is_char = FALSE;
   scalar_char.u.scalar_is_char = TRUE;
+  /* Create the hash-table used to hash-cons input files.  */
+  input_file_htab =
+    htab_create (800, htab_hash_inputfile, htab_eq_inputfile, NULL);
+  /* Initialize our special input files.  */
+  this_file = input_file_by_name (__FILE__);
+  system_h_file = input_file_by_name ("system.h");
 
   parse_program_options (argc, argv);
 
@@ -4557,10 +4576,11 @@  main (int argc, char **argv)
       do_scalar_typedef ("void", &pos); pos.line++;
       do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
       read_input_list (inputlist);
-      for (i = 0; i < num_gt_files; i++) {
-	parse_file (gt_files[i]);
-	DBGPRINTF ("parsed file #%d %s", (int) i, gt_files[i]);
-      }
+      for (i = 0; i < num_gt_files; i++)
+	{
+	  parse_file (get_input_file_name (gt_files[i]));
+	  DBGPRINTF ("parsed file #%d %s", (int) i, get_input_file_name (gt_files[i]));
+	}
       DBGPRINT_COUNT_TYPE ("structures after parsing", structures);
       DBGPRINT_COUNT_TYPE ("param_structs after parsing", param_structs);
       if (verbosity_level >= 1)
@@ -4586,11 +4606,14 @@  main (int argc, char **argv)
 
       /* Parse our plugin files.  */
       for (ix = 0; ix < nb_plugin_files; ix++)
-	parse_file (plugin_files[ix]);
+	{
+	  parse_file (get_input_file_name (plugin_files[ix]));
+	  DBGPRINTF ("parsed plugin file #%d %s", (int) ix,
+		     get_input_file_name (plugin_files[ix]));
+	}
 
       if (hit_error)
 	return 1;
-
       plugin_output = create_file ("GCC", plugin_output_filename);
       DBGPRINTF ("created plugin_output %p named %s",
 		 (void*) plugin_output, plugin_output->name);
--- ../thirdround_02_verbosity//gengtype.h	2010-09-20 22:03:42.000000000 +0200
+++ gcc/gengtype.h	2010-09-21 10:27:50.000000000 +0200
@@ -25,13 +25,116 @@  along with GCC; see the file COPYING3.
    represented by a bitmap.  */
 typedef unsigned lang_bitmap;
 
-/* A file position, mostly for error messages.
-   The FILE element may be compared using pointer equality.  */
+/* Variable length structure representing an input file.  A hash table
+   ensure uniqueness for a given input file name.  The only function
+   allocating input_file-s is input_file_by_name.  */
+struct input_file_st {
+#if ENABLE_CHECKING
+  /* The magic number is intended to help debugging gengtype.  We
+     check that it is indeed what it should be.  This could help
+     catching bugs where an input_file pointer is bogus.  */
+  int inpmagic;		/* Always INPUT_FILE_MAGIC.  */
+#endif /*ENABLE_CHECKING*/
+  struct outf* inpoutf;	/* Cached corresponding output file, computed
+			           in get_output_file_with_visibility.  */
+  lang_bitmap inpbitmap; /* The set of languages using this file.  */
+  char inpname[1]; /* a flexible array, ended by a null char.  */
+};
+typedef struct input_file_st input_file;
+
+#if ENABLE_CHECKING
+/*  0x371c433f is 924599103 in decimal, and was randomly choosen.  The
+    input file magic number is intended to help catching bugs.  */
+#define INPUT_FILE_MAGIC 0x371c433f
+  /* This is a fancy assert which displays a more precise message.  It
+     should never happen!  But it can help a lot when hacking
+     gengtype.  */
+#define CHECK_INPUT_FILE_MAGIC(Inpf)				\
+    do {							\
+      const input_file* badinpf = Inpf;			\
+      if (badinpf && badinpf->inpmagic != INPUT_FILE_MAGIC)	\
+	fatal ("corrupted input file %p bad magic %d in %s:%d",	\
+	       (const void*) badinpf, badinpf->inpmagic,	\
+	       lbasename (__FILE__), __LINE__);			\
+    } while (0)
+#else
+#define CHECK_INPUT_FILE_MAGIC(Inpf) do{} while (0)
+#endif	/* ENABLE_CHECKING */
+
+/* Table of all input files, and its size.  */
+extern input_file** gt_files;
+extern size_t num_gt_files;
+
+/* A number of places use the name of this "gengtype.c" file for a
+   location for things that we can't rely on the source to define.  We
+   also need to refer to the "system.h" file specifically.  These two
+   pointers are initialized early in main.  */
+extern input_file* this_file;
+extern input_file* system_h_file;
+
+/* Retrieve or create the input_file for a given name, which is a file
+   path.  This is the only function allocating input_file-s and it is
+   hash-consing them.  */
+input_file* input_file_by_name (const char* name);
+
+
+/* For F an input_file, return the relative path to F from $(srcdir)
+   if the latter is a prefix in F, NULL otherwise.  */
+const char *get_file_srcdir_relative_path (const input_file *inpf);
+
+/* Get the name of an input file.  */
+static inline const char*
+get_input_file_name (const input_file *inpf)
+{
+  if (inpf)
+    {
+      CHECK_INPUT_FILE_MAGIC (inpf);
+      return inpf->inpname;
+    }
+  return NULL;
+}
+
+/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
+   INPUT_FILE is used by <lang>.
+
+   This function should be written to assume that a file _is_ used
+   if the situation is unclear.  If it wrongly assumes a file _is_ used,
+   a linker error will result.  If it wrongly assumes a file _is not_ used,
+   some GC roots may be missed, which is a much harder-to-debug problem.
+  */
+
+static inline lang_bitmap
+get_lang_bitmap (const input_file* inpf)
+{
+  if (inpf == NULL)
+    return 0;
+  CHECK_INPUT_FILE_MAGIC (inpf);
+  return inpf->inpbitmap;
+}
+
+/* Set the bitmap returned by get_lang_bitmap.  The only legitimate
+   callers of this function are read_input_list & read_state_*.  */
+static inline void
+set_lang_bitmap (input_file* inpf, lang_bitmap n)
+{
+  gcc_assert (inpf);
+  CHECK_INPUT_FILE_MAGIC (inpf);
+  inpf->inpbitmap = n;
+}
+
+/* A file position, mostly for error messages.  The FILE element may
+   be compared using pointer equality since it is hash-consed.  */
 struct fileloc {
-  const char *file;
+  input_file *file;
   int line;
 };
 
+/* Vector of per-language directories.  */
+extern const char **lang_dir_names;
+extern size_t num_lang_dirs;
+
+
+
 /* Data types handed around within, but opaque to, the lexer and parser.  */
 typedef struct pair *pair_p;
 typedef struct type *type_p;
@@ -65,10 +168,17 @@  void oprintf (outf_p o, const char *S, .
      ATTRIBUTE_PRINTF_2;
 
 /* An output file, suitable for definitions, that can see declarations
-   made in INPUT_FILE and is linked into every language that uses
-   INPUT_FILE.  May return NULL in plugin mode.  */
-extern outf_p get_output_file_with_visibility
-   (const char *input_file);
+   made in INPF and is linked into every language that uses INPF.  May
+   return NULL in plugin mode.  The INPF argument is almost const, but
+   since the result is cached in its inpoutf field it cannot be
+   declared const, because this function stores the computed output
+   file in that field to speed it up for further invocations.  */
+outf_p get_output_file_with_visibility (input_file* inpf);
+
+/* The name of an output file, suitable for definitions, that can see
+   declarations made in INPF and is linked into every language that
+   uses INPF.  May return NULL.  */
+const char *get_output_file_name (input_file *inpf);
 
 /* Source directory.  */
 extern const char *srcdir;
--- ../thirdround_02_verbosity//gengtype-lex.l	2010-09-21 07:40:27.000000000 +0200
+++ gcc/gengtype-lex.l	2010-09-21 07:34:33.000000000 +0200
@@ -1,6 +1,6 @@ 
 /* -*- indented-text -*- */
 /* Process source files and output type information.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.
 %{
 #include "bconfig.h"
 #include "system.h"
+#include "errors.h"             /* for fatal, needed by gengtype.h */
 
 #define malloc xmalloc
 #define realloc xrealloc
@@ -202,7 +203,7 @@  yybegin (const char *fname)
       perror (fname);
       exit (1);
     }
-  lexer_line.file = fname;
+  lexer_line.file = input_file_by_name (fname);
   lexer_line.line = 1;
 }
 
--- ../thirdround_02_verbosity//gengtype-parse.c	2010-09-21 07:40:34.000000000 +0200
+++ gcc/gengtype-parse.c	2010-09-21 07:36:06.000000000 +0200
@@ -1,5 +1,5 @@ 
 /* Process source files and output type information.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -19,6 +19,7 @@  along with GCC; see the file COPYING3.
 
 #include "bconfig.h"
 #include "system.h"
+#include "errors.h"	/* for fatal, needed by gengtype.h */
 #include "gengtype.h"
 
 /* This is a simple recursive-descent parser which understands a subset of
@@ -135,7 +136,8 @@  parse_error (const char *msg, ...)
 {
   va_list ap;
 
-  fprintf (stderr, "%s:%d: parse error: ", lexer_line.file, lexer_line.line);
+  fprintf (stderr, "%s:%d: parse error: ",
+	   get_input_file_name (lexer_line.file), lexer_line.line);
 
   va_start (ap, msg);
   vfprintf (stderr, msg, ap);
@@ -679,6 +681,7 @@  static type_p
 type (options_p *optsp, bool nested)
 {
   const char *s;
+  static int anonymous_count; /* to generate unique pseudo-identifiers! */
   *optsp = 0;
   switch (token ())
     {
@@ -713,40 +716,61 @@  type (options_p *optsp, bool nested)
 	   that we can't handle.  */
 	if (nested || token () == GTY_TOKEN)
 	  {
-        is_gty = GTY_BEFORE_ID;
-        opts = gtymarker_opt ();
+	    is_gty = GTY_BEFORE_ID;
+	    opts = gtymarker_opt ();
 	  }
 
 	if (token () == ID)
 	  s = advance ();
 	else
-	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
+	  {
+	    /* We don't want to wire in the source directory (because
+	       in plugin mode, the source directory can be unavailable
+	       since gengtype has read its state).  So if the input is
+	       from GCC source directory, we use its relative path to
+	       build an anonymous unique tag.  */
+	    const char* relp = get_file_srcdir_relative_path (lexer_line.file);
+	    anonymous_count++;
+	    if (relp)
+	      /* The input file is a GCC source file, we use a double
+		 colon after anonymous.  To be sure s is truly unique,
+		 we also use anonymous_count.  */
+	      s = xasprintf ("anonymous::%s:%d::%d",
+			     relp, lexer_line.line, anonymous_count);
+	    else
+	      /* The input file is outside of GCC source tree, we use
+		 a single colon after anonymous.  To be sure s is
+		 truly unique, we also use anonymous_count.  */
+	      s = xasprintf ("anonymous:%s:%d::%d",
+			     get_input_file_name (lexer_line.file),
+			     lexer_line.line, anonymous_count);
+	  }
 
         /* Unfortunately above GTY_TOKEN check does not capture the
            typedef struct_type GTY case.  */
 	if (token () == GTY_TOKEN)
 	  {
-        is_gty = GTY_AFTER_ID;
-        opts = gtymarker_opt ();
+	    is_gty = GTY_AFTER_ID;
+	    opts = gtymarker_opt ();
 	  }
 
-    if (is_gty)
-      {
-        if (token () == '{')
-          {
-            pair_p fields;
-
-            if (is_gty == GTY_AFTER_ID)
-                parse_error ("GTY must be specified before identifier");
-
-            advance ();
-            fields = struct_field_seq ();
-            require ('}');
-            return new_structure (s, is_union, &lexer_line, fields, opts);
-          }
-      }
-    else if (token () == '{')
-      consume_balanced ('{', '}');
+	if (is_gty)
+	  {
+	    if (token () == '{')
+	      {
+		pair_p fields;
+
+		if (is_gty == GTY_AFTER_ID)
+		  parse_error ("GTY must be specified before identifier");
+
+		advance ();
+		fields = struct_field_seq ();
+		require ('}');
+		return new_structure (s, is_union, &lexer_line, fields, opts);
+	      }
+	  }
+	else if (token () == '{')
+	  consume_balanced ('{', '}');
 	if (opts)
 	  *optsp = opts;
 	return find_structure (s, is_union);
@@ -754,11 +778,22 @@  type (options_p *optsp, bool nested)
 
     case ENUM:
       advance ();
-	if (token () == ID)
-	  s = advance ();
-	else
-	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
-
+      if (token () == ID)
+	s = advance ();
+      else
+	{
+	    /* Again, we don't want to wire in the GCC source tree
+	       directory.  */
+	    const char* relp = get_file_srcdir_relative_path (lexer_line.file);
+	    anonymous_count++;
+	    if (relp)
+	      s = xasprintf ("anonymous::%s:%d::%d",
+			     relp, lexer_line.line, anonymous_count);
+	    else
+	      s = xasprintf ("anonymous:%s:%d::%d",
+			     get_input_file_name (lexer_line.file),
+			     lexer_line.line, anonymous_count);
+	}
       if (token () == '{')
 	consume_balanced ('{','}');
       return create_scalar_type (s);