]> git.saurik.com Git - bison.git/commitdiff
Merge remote-tracking branch 'origin/maint'
authorAkim Demaille <akim@lrde.epita.fr>
Fri, 28 Sep 2012 13:28:46 +0000 (15:28 +0200)
committerAkim Demaille <akim@lrde.epita.fr>
Mon, 1 Oct 2012 10:12:38 +0000 (12:12 +0200)
* origin/maint:
  gnulib: update
  errors: indent "user token number redeclaration" context

Conflicts:
src/symtab.c

1  2 
src/symtab.c
tests/input.at

diff --combined src/symtab.c
index 916536ae3d05e3c12fcfb608857cbb07465e44eb,56cfe5118d1dd145a81ed81777752ba82b8671f0..66e20c0520e2c0566e2a0ca38ba6b08f8de51145
@@@ -33,7 -33,6 +33,7 @@@
  `-------------------------------------------------------------------*/
  
  static symbol **symbols_sorted = NULL;
 +static symbol **semantic_types_sorted = NULL;
  
  /*------------------------.
  | Distinguished symbols.  |
@@@ -46,6 -45,14 +46,6 @@@ symbol *accept = NULL
  symbol *startsymbol = NULL;
  location startsymbol_location;
  
 -/*---------------------------------------.
 -| Default %destructor's and %printer's.  |
 -`---------------------------------------*/
 -
 -static code_props default_tagged_destructor = CODE_PROPS_NONE_INIT;
 -static code_props default_tagless_destructor = CODE_PROPS_NONE_INIT;
 -static code_props default_tagged_printer = CODE_PROPS_NONE_INIT;
 -static code_props default_tagless_printer = CODE_PROPS_NONE_INIT;
  
  /*---------------------------------.
  | Create a new symbol, named TAG.  |
@@@ -60,16 -67,16 +60,16 @@@ symbol_new (uniqstr tag, location loc
  
    /* If the tag is not a string (starts with a double quote), check
       that it is valid for Yacc. */
 -  if (tag[0] != '\"' && tag[0] != '\'' && mbschr (tag, '-'))
 -    yacc_at (loc, _("POSIX Yacc forbids dashes in symbol names: %s"),
 -             tag);
 +  if (tag[0] != '\"' && tag[0] != '\'' && strchr (tag, '-'))
 +    complain_at (loc, Wyacc,
 +                 _("POSIX Yacc forbids dashes in symbol names: %s"), tag);
  
    res->tag = tag;
    res->location = loc;
  
    res->type_name = NULL;
 -  code_props_none_init (&res->destructor);
 -  code_props_none_init (&res->printer);
 +  for (int i = 0; i < CODE_PROPS_SIZE; ++i)
 +    code_props_none_init (&res->props[i]);
  
    res->number = NUMBER_UNDEFINED;
    res->prec = 0;
  
    res->alias = NULL;
    res->class = unknown_sym;
 -  res->declared = false;
 +  res->status = undeclared;
  
    if (nsyms == SYMBOL_NUMBER_MAXIMUM)
 -    fatal (_("too many symbols in input grammar (limit is %d)"),
 -         SYMBOL_NUMBER_MAXIMUM);
 +    complain (fatal, _("too many symbols in input grammar (limit is %d)"),
 +              SYMBOL_NUMBER_MAXIMUM);
    nsyms++;
    return res;
  }
  
 +char const *
 +code_props_type_string (code_props_type kind)
 +{
 +  switch (kind)
 +    {
 +    case destructor:
 +      return "%destructor";
 +    case printer:
 +      return "%printer";
 +    }
 +  assert (0);
 +}
 +
  /*----------------------------------------.
  | Create a new semantic type, named TAG.  |
  `----------------------------------------*/
  
  static semantic_type *
 -semantic_type_new (uniqstr tag)
 +semantic_type_new (uniqstr tag, const location *loc)
  {
    semantic_type *res = xmalloc (sizeof *res);
  
    uniqstr_assert (tag);
    res->tag = tag;
 -  code_props_none_init (&res->destructor);
 -  code_props_none_init (&res->printer);
 +  if (loc)
 +    res->location = *loc;
 +  for (int i = 0; i < CODE_PROPS_SIZE; ++i)
 +    code_props_none_init (&res->props[i]);
  
    return res;
  }
  | Print a symbol.  |
  `-----------------*/
  
 -#define SYMBOL_ATTR_PRINT(Attr)                               \
 -  if (s->Attr)                                                \
 +#define SYMBOL_ATTR_PRINT(Attr)                         \
 +  if (s->Attr)                                          \
      fprintf (f, " %s { %s }", #Attr, s->Attr)
  
 -#define SYMBOL_CODE_PRINT(Attr)                         \
 -  if (s->Attr.code)                                     \
 -    fprintf (f, " %s { %s }", #Attr, s->Attr.code)
 +#define SYMBOL_CODE_PRINT(Attr)                                         \
 +  if (s->props[Attr].code)                                              \
 +    fprintf (f, " %s { %s }", #Attr, s->props[Attr].code)
  
  void
 -symbol_print (symbol *s, FILE *f)
 +symbol_print (symbol const *s, FILE *f)
  {
    if (s)
      {
  #undef SYMBOL_ATTR_PRINT
  #undef SYMBOL_CODE_PRINT
  
 +
 +/*----------------------------------.
 +| Whether S is a valid identifier.  |
 +`----------------------------------*/
 +
 +static bool
 +is_identifier (uniqstr s)
 +{
 +  static char const alphanum[26 + 26 + 1 + 10] =
 +    "abcdefghijklmnopqrstuvwxyz"
 +    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 +    "_"
 +    "0123456789";
 +  if (!s || ! memchr (alphanum, *s, sizeof alphanum - 10))
 +    return false;
 +  for (++s; *s; ++s)
 +    if (! memchr (alphanum, *s, sizeof alphanum))
 +      return false;
 +  return true;
 +}
 +
 +
 +/*-----------------------------------------------.
 +| Get the identifier associated to this symbol.  |
 +`-----------------------------------------------*/
 +uniqstr
 +symbol_id_get (symbol const *sym)
 +{
 +  aver (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
 +  if (sym->alias)
 +    sym = sym->alias;
 +  return is_identifier (sym->tag) ? sym->tag : 0;
 +}
 +
 +
  /*------------------------------------------------------------------.
  | Complain that S's WHAT is redeclared at SECOND, and was first set |
  | at FIRST.                                                         |
@@@ -194,11 -151,9 +194,11 @@@ symbol_redeclaration (symbol *s, const 
                        location second)
  {
    unsigned i = 0;
 -  complain_at_indent (second, &i, _("%s redeclaration for %s"), what, s->tag);
 +  complain_at_indent (second, complaint, &i,
 +                      _("%s redeclaration for %s"), what, s->tag);
    i += SUB_INDENT;
 -  complain_at_indent (first, &i, _("previous declaration"));
 +  complain_at_indent (first, complaint, &i,
 +                      _("previous declaration"));
  }
  
  static void
@@@ -206,11 -161,9 +206,11 @@@ semantic_type_redeclaration (semantic_t
                               location second)
  {
    unsigned i = 0;
 -  complain_at_indent (second, &i, _("%s redeclaration for <%s>"), what, s->tag);
 +  complain_at_indent (second, complaint, &i,
 +                      _("%s redeclaration for <%s>"), what, s->tag);
    i += SUB_INDENT;
 -  complain_at_indent (first, &i, _("previous declaration"));
 +  complain_at_indent (first, complaint, &i,
 +                      _("previous declaration"));
  }
  
  
@@@ -226,73 -179,122 +226,73 @@@ symbol_type_set (symbol *sym, uniqstr t
    if (type_name)
      {
        if (sym->type_name)
 -      symbol_redeclaration (sym, "%type", sym->type_location, loc);
 +        symbol_redeclaration (sym, "%type", sym->type_location, loc);
        uniqstr_assert (type_name);
        sym->type_name = type_name;
        sym->type_location = loc;
      }
  }
  
 -/*-----------------------------------------.
 -| Set the DESTRUCTOR associated with SYM.  |
 -`-----------------------------------------*/
 +/*--------------------------------------------------------.
 +| Set the DESTRUCTOR or PRINTER associated with the SYM.  |
 +`--------------------------------------------------------*/
  
  void
 -symbol_destructor_set (symbol *sym, code_props const *destructor)
 +symbol_code_props_set (symbol *sym, code_props_type kind,
 +                       code_props const *code)
  {
 -  if (sym->destructor.code)
 -    symbol_redeclaration (sym, "%destructor", sym->destructor.location,
 -                          destructor->location);
 -  sym->destructor = *destructor;
 +  if (sym->props[kind].code)
 +    symbol_redeclaration (sym, code_props_type_string (kind),
 +                          sym->props[kind].location,
 +                          code->location);
 +  sym->props[kind] = *code;
  }
  
 -/*------------------------------------------.
 -| Set the DESTRUCTOR associated with TYPE.  |
 -`------------------------------------------*/
 +/*-----------------------------------------------------.
 +| Set the DESTRUCTOR or PRINTER associated with TYPE.  |
 +`-----------------------------------------------------*/
  
  void
 -semantic_type_destructor_set (semantic_type *type,
 -                              code_props const *destructor)
 +semantic_type_code_props_set (semantic_type *type,
 +                              code_props_type kind,
 +                              code_props const *code)
  {
 -  if (type->destructor.code)
 -    semantic_type_redeclaration (type, "%destructor",
 -                                 type->destructor.location,
 -                                 destructor->location);
 -  type->destructor = *destructor;
 +  if (type->props[kind].code)
 +    semantic_type_redeclaration (type, code_props_type_string (kind),
 +                                 type->props[kind].location,
 +                                 code->location);
 +  type->props[kind] = *code;
  }
  
 -/*---------------------------------------.
 -| Get the computed %destructor for SYM.  |
 -`---------------------------------------*/
 +/*---------------------------------------------------.
 +| Get the computed %destructor or %printer for SYM.  |
 +`---------------------------------------------------*/
  
 -code_props const *
 -symbol_destructor_get (symbol const *sym)
 +code_props *
 +symbol_code_props_get (symbol *sym, code_props_type kind)
  {
 -  /* Per-symbol %destructor.  */
 -  if (sym->destructor.code)
 -    return &sym->destructor;
 +  /* Per-symbol code props.  */
 +  if (sym->props[kind].code)
 +    return &sym->props[kind];
  
 -  /* Per-type %destructor.  */
 +  /* Per-type code props.  */
    if (sym->type_name)
      {
 -      code_props const *destructor =
 -        &semantic_type_get (sym->type_name)->destructor;
 -      if (destructor->code)
 -        return destructor;
 +      code_props *code =
 +        &semantic_type_get (sym->type_name, NULL)->props[kind];
 +      if (code->code)
 +        return code;
      }
  
 -  /* Apply default %destructor's only to user-defined symbols.  */
 -  if (sym->tag[0] == '$' || sym == errtoken)
 -    return &code_props_none;
 -
 -  if (sym->type_name)
 -    return &default_tagged_destructor;
 -  return &default_tagless_destructor;
 -}
 -
 -/*--------------------------------------.
 -| Set the PRINTER associated with SYM.  |
 -`--------------------------------------*/
 -
 -void
 -symbol_printer_set (symbol *sym, code_props const *printer)
 -{
 -  if (sym->printer.code)
 -    symbol_redeclaration (sym, "%printer",
 -                          sym->printer.location, printer->location);
 -  sym->printer = *printer;
 -}
 -
 -/*---------------------------------------.
 -| Set the PRINTER associated with TYPE.  |
 -`---------------------------------------*/
 -
 -void
 -semantic_type_printer_set (semantic_type *type, code_props const *printer)
 -{
 -  if (type->printer.code)
 -    semantic_type_redeclaration (type, "%printer",
 -                                 type->printer.location, printer->location);
 -  type->printer = *printer;
 -}
 -
 -/*------------------------------------.
 -| Get the computed %printer for SYM.  |
 -`------------------------------------*/
 -
 -code_props const *
 -symbol_printer_get (symbol const *sym)
 -{
 -  /* Per-symbol %printer.  */
 -  if (sym->printer.code)
 -    return &sym->printer;
 -
 -  /* Per-type %printer.  */
 -  if (sym->type_name)
 +  /* Apply default code props's only to user-defined symbols.  */
 +  if (sym->tag[0] != '$' && sym != errtoken)
      {
 -      code_props const *printer = &semantic_type_get (sym->type_name)->printer;
 -      if (printer->code)
 -        return printer;
 +      code_props *code =
 +        &semantic_type_get (sym->type_name ? "*" : "", NULL)->props[kind];
 +      if (code->code)
 +        return code;
      }
 -
 -  /* Apply the default %printer only to user-defined symbols.  */
 -  if (sym->tag[0] == '$' || sym == errtoken)
 -    return &code_props_none;
 -
 -  if (sym->type_name)
 -    return &default_tagged_printer;
 -  return &default_tagless_printer;
 +  return &code_props_none;
  }
  
  /*-----------------------------------------------------------------.
@@@ -306,7 -308,7 +306,7 @@@ symbol_precedence_set (symbol *sym, in
    if (a != undef_assoc)
      {
        if (sym->prec != 0)
 -      symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
 +        symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
                                loc);
        sym->prec = prec;
        sym->assoc = a;
  void
  symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
  {
 +  bool warned = false;
    if (sym->class != unknown_sym && sym->class != class)
      {
 -      complain_at (loc, _("symbol %s redefined"), sym->tag);
 -      sym->declared = false;
 +      complain_at (loc, complaint, _("symbol %s redefined"), sym->tag);
 +      // Don't report both "redefined" and "redeclared".
 +      warned = true;
      }
  
    if (class == nterm_sym && sym->class != nterm_sym)
  
    if (declaring)
      {
 -      if (sym->declared)
 -      warn_at (loc, _("symbol %s redeclared"), sym->tag);
 -      sym->declared = true;
 +      if (sym->status == declared && !warned)
 +        complain_at (loc, Wother, _("symbol %s redeclared"), sym->tag);
 +      sym->status = declared;
      }
  }
  
@@@ -364,8 -364,7 +364,8 @@@ symbol_user_token_number_set (symbol *s
      user_token_numberp = &sym->alias->user_token_number;
    if (*user_token_numberp != USER_NUMBER_UNDEFINED
        && *user_token_numberp != user_token_number)
 -    complain_at (loc, _("redefining user token number of %s"), sym->tag);
 +    complain_at (loc, complaint, _("redefining user token number of %s"),
 +                 sym->tag);
  
    *user_token_numberp = user_token_number;
    /* User defined $end token? */
      {
        endtoken = sym;
        /* It is always mapped to 0, so it was already counted in
 -       NTOKENS.  */
 +         NTOKENS.  */
        if (endtoken->number != NUMBER_UNDEFINED)
          --ntokens;
        endtoken->number = 0;
@@@ -391,51 -390,14 +391,51 @@@ symbol_check_defined (symbol *sym
  {
    if (sym->class == unknown_sym)
      {
 -      complain_at
 -      (sym->location,
 -       _("symbol %s is used, but is not defined as a token and has no rules"),
 -       sym->tag);
 +      assert (sym->status != declared);
 +      complain_at (sym->location,
 +                   sym->status == needed ? complaint : Wother,
 +                   _("symbol %s is used, but is not defined as a token"
 +                     " and has no rules"),
 +                   sym->tag);
        sym->class = nterm_sym;
        sym->number = nvars++;
      }
  
 +  for (int i = 0; i < 2; ++i)
 +    symbol_code_props_get (sym, i)->is_used = true;
 +
 +  /* Set the semantic type status associated to the current symbol to
 +     'declared' so that we could check semantic types unnecessary uses. */
 +  if (sym->type_name)
 +    {
 +      semantic_type *sem_type = semantic_type_get (sym->type_name, NULL);
 +      if (sem_type)
 +        sem_type->status = declared;
 +    }
 +
 +  return true;
 +}
 +
 +static inline bool
 +semantic_type_check_defined (semantic_type *sem_type)
 +{
 +  // <*> and <> do not have to be "declared".
 +  if (sem_type->status == declared
 +      || !*sem_type->tag
 +      || STREQ(sem_type->tag, "*"))
 +    {
 +      for (int i = 0; i < 2; ++i)
 +        if (sem_type->props[i].kind != CODE_PROPS_NONE
 +            && ! sem_type->props[i].is_used)
 +          complain_at (sem_type->location, Wother,
 +                       _("useless %s for type <%s>"),
 +                       code_props_type_string (i), sem_type->tag);
 +    }
 +  else
 +    complain_at (sem_type->location, Wother,
 +                 _("type <%s> is used, but is not associated to any symbol"),
 +                 sem_type->tag);
 +
    return true;
  }
  
@@@ -445,23 -407,16 +445,23 @@@ symbol_check_defined_processor (void *s
    return symbol_check_defined (sym);
  }
  
 +static bool
 +semantic_type_check_defined_processor (void *sem_type,
 +                                       void *null ATTRIBUTE_UNUSED)
 +{
 +  return semantic_type_check_defined (sem_type);
 +}
 +
  
  void
  symbol_make_alias (symbol *sym, symbol *str, location loc)
  {
    if (str->alias)
 -    warn_at (loc, _("symbol %s used more than once as a literal string"),
 -             str->tag);
 +    complain_at (loc, Wother,
 +              _("symbol %s used more than once as a literal string"), str->tag);
    else if (sym->alias)
 -    warn_at (loc, _("symbol %s given more than one literal string"),
 -             sym->tag);
 +    complain_at (loc, Wother,
 +              _("symbol %s given more than one literal string"), sym->tag);
    else
      {
        str->class = token_sym;
@@@ -494,32 -449,42 +494,32 @@@ symbol_check_alias_consistency (symbol 
    if (str->type_name != sym->type_name)
      {
        if (str->type_name)
 -      symbol_type_set (sym, str->type_name, str->type_location);
 +        symbol_type_set (sym, str->type_name, str->type_location);
        else
 -      symbol_type_set (str, sym->type_name, sym->type_location);
 +        symbol_type_set (str, sym->type_name, sym->type_location);
      }
  
  
 -  if (str->destructor.code || sym->destructor.code)
 -    {
 -      if (str->destructor.code)
 -      symbol_destructor_set (sym, &str->destructor);
 -      else
 -      symbol_destructor_set (str, &sym->destructor);
 -    }
 -
 -  if (str->printer.code || sym->printer.code)
 -    {
 -      if (str->printer.code)
 -      symbol_printer_set (sym, &str->printer);
 -      else
 -      symbol_printer_set (str, &sym->printer);
 -    }
 +  for (int i = 0; i < CODE_PROPS_SIZE; ++i)
 +    if (str->props[i].code)
 +      symbol_code_props_set (sym, i, &str->props[i]);
 +    else if (sym->props[i].code)
 +      symbol_code_props_set (str, i, &sym->props[i]);
  
    if (sym->prec || str->prec)
      {
        if (str->prec)
 -      symbol_precedence_set (sym, str->prec, str->assoc,
 -                             str->prec_location);
 +        symbol_precedence_set (sym, str->prec, str->assoc,
 +                               str->prec_location);
        else
 -      symbol_precedence_set (str, sym->prec, sym->assoc,
 -                             sym->prec_location);
 +        symbol_precedence_set (str, sym->prec, sym->assoc,
 +                               sym->prec_location);
      }
  }
  
  static bool
  symbol_check_alias_consistency_processor (void *this,
 -                                        void *null ATTRIBUTE_UNUSED)
 +                                          void *null ATTRIBUTE_UNUSED)
  {
    symbol_check_alias_consistency (this);
    return true;
@@@ -566,10 -531,11 +566,11 @@@ user_token_number_redeclaration (int nu
        first = second;
        second = tmp;
      }
 -  complain_at_indent (second->location, &i,
 +  complain_at_indent (second->location, complaint, &i,
                        _("user token number %d redeclaration for %s"),
                        num, second->tag);
 -  complain_at_indent (first->location, &i,
+   i += SUB_INDENT;
 +  complain_at_indent (first->location, complaint, &i,
                        _("previous declaration for %s"),
                        first->tag);
  }
@@@ -587,7 -553,7 +588,7 @@@ symbol_translation (symbol *this
      {
        /* A token which translation has already been set? */
        if (token_translations[this->user_token_number] != undeftoken->number)
 -      user_token_number_redeclaration
 +        user_token_number_redeclaration
            (this->user_token_number,
             symbols[token_translations[this->user_token_number]],
             this);
@@@ -675,15 -641,15 +676,15 @@@ voi
  symbols_new (void)
  {
    symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
 -                                NULL,
 -                                hash_symbol_hasher,
 -                                hash_symbol_comparator,
 -                                free);
 +                                  NULL,
 +                                  hash_symbol_hasher,
 +                                  hash_symbol_comparator,
 +                                  free);
    semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
 -                                       NULL,
 -                                       hash_semantic_type_hasher,
 -                                       hash_semantic_type_comparator,
 -                                       free);
 +                                         NULL,
 +                                         hash_semantic_type_hasher,
 +                                         hash_semantic_type_comparator,
 +                                         free);
  }
  
  
@@@ -719,7 -685,7 +720,7 @@@ symbol_from_uniqstr (const uniqstr key
  `-----------------------------------------------------------------------*/
  
  semantic_type *
 -semantic_type_from_uniqstr (const uniqstr key)
 +semantic_type_from_uniqstr (const uniqstr key, const location *loc)
  {
    semantic_type probe;
    semantic_type *entry;
    if (!entry)
      {
        /* First insertion in the hash. */
 -      entry = semantic_type_new (key);
 +      entry = semantic_type_new (key, loc);
        if (!hash_insert (semantic_type_table, entry))
          xalloc_die ();
      }
@@@ -756,9 -722,9 +757,9 @@@ symbol_get (const char *key, location l
  `-----------------------------------------------------------------------*/
  
  semantic_type *
 -semantic_type_get (const char *key)
 +semantic_type_get (const char *key, const location *loc)
  {
 -  return semantic_type_from_uniqstr (uniqstr_new (key));
 +  return semantic_type_from_uniqstr (uniqstr_new (key), loc);
  }
  
  
@@@ -821,20 -787,20 +822,20 @@@ symbols_cmp_qsort (void const *a, void 
  }
  
  static void
 -symbols_do (Hash_processor processor, void *processor_data)
 +symbols_do (Hash_processor processor, void *processor_data,
 +            struct hash_table *table, symbol **sorted)
  {
 -  size_t count = hash_get_n_entries (symbol_table);
 -  if (!symbols_sorted)
 +  size_t count = hash_get_n_entries (table);
 +  if (!sorted)
      {
 -      symbols_sorted = xnmalloc (count, sizeof *symbols_sorted);
 -      hash_get_entries (symbol_table, (void**)symbols_sorted, count);
 -      qsort (symbols_sorted, count, sizeof *symbols_sorted,
 -             symbols_cmp_qsort);
 +      sorted = xnmalloc (count, sizeof *sorted);
 +      hash_get_entries (table, (void**)sorted, count);
 +      qsort (sorted, count, sizeof *sorted, symbols_cmp_qsort);
      }
    {
      size_t i;
      for (i = 0; i < count; ++i)
 -      processor (symbols_sorted[i], processor_data);
 +      processor (sorted[i], processor_data);
    }
  }
  
  void
  symbols_check_defined (void)
  {
 -  symbols_do (symbol_check_defined_processor, NULL);
 +  symbols_do (symbol_check_defined_processor, NULL,
 +              symbol_table, symbols_sorted);
 +  symbols_do (semantic_type_check_defined_processor, NULL,
 +              semantic_type_table, semantic_types_sorted);
  }
  
  /*------------------------------------------------------------------.
@@@ -870,12 -833,12 +871,12 @@@ symbols_token_translations_init (void
      {
        symbol *this = symbols[i];
        if (this->user_token_number != USER_NUMBER_UNDEFINED)
 -      {
 -        if (this->user_token_number > max_user_token_number)
 -          max_user_token_number = this->user_token_number;
 -        if (this->user_token_number == 256)
 -          num_256_available_p = false;
 -      }
 +        {
 +          if (this->user_token_number > max_user_token_number)
 +            max_user_token_number = this->user_token_number;
 +          if (this->user_token_number == 256)
 +            num_256_available_p = false;
 +        }
      }
  
    /* If 256 is not used, assign it to error, to follow POSIX.  */
      {
        symbol *this = symbols[i];
        if (this->user_token_number == USER_NUMBER_UNDEFINED)
 -      this->user_token_number = ++max_user_token_number;
 +        this->user_token_number = ++max_user_token_number;
        if (this->user_token_number > max_user_token_number)
 -      max_user_token_number = this->user_token_number;
 +        max_user_token_number = this->user_token_number;
      }
  
    token_translations = xnmalloc (max_user_token_number + 1,
 -                               sizeof *token_translations);
 +                                 sizeof *token_translations);
  
 -  /* Initialize all entries for literal tokens to 2, the internal
 -     token number for $undefined, which represents all invalid inputs.
 -     */
 +  /* Initialize all entries for literal tokens to the internal token
 +     number for $undefined, which represents all invalid inputs.  */
    for (i = 0; i < max_user_token_number + 1; i++)
      token_translations[i] = undeftoken->number;
 -  symbols_do (symbol_translation_processor, NULL);
 +  symbols_do (symbol_translation_processor, NULL,
 +              symbol_table, symbols_sorted);
  }
  
  
  void
  symbols_pack (void)
  {
 -  symbols_do (symbol_check_alias_consistency_processor, NULL);
 +  symbols_do (symbol_check_alias_consistency_processor, NULL,
 +              symbol_table, symbols_sorted);
  
    symbols = xcalloc (nsyms, sizeof *symbols);
 -  symbols_do (symbol_pack_processor, NULL);
 +  symbols_do (symbol_pack_processor, NULL, symbol_table, symbols_sorted);
  
    /* Aliases leave empty slots in symbols, so remove them.  */
    {
    symbols_token_translations_init ();
  
    if (startsymbol->class == unknown_sym)
 -    fatal_at (startsymbol_location,
 -            _("the start symbol %s is undefined"),
 -            startsymbol->tag);
 +    complain_at (startsymbol_location, fatal,
 +                 _("the start symbol %s is undefined"),
 +                 startsymbol->tag);
    else if (startsymbol->class == token_sym)
 -    fatal_at (startsymbol_location,
 -            _("the start symbol %s is a token"),
 -            startsymbol->tag);
 -}
 -
 -
 -/*--------------------------------------------------.
 -| Set default tagged/tagless %destructor/%printer.  |
 -`--------------------------------------------------*/
 -
 -void
 -default_tagged_destructor_set (code_props const *destructor)
 -{
 -  if (default_tagged_destructor.code)
 -    {
 -      unsigned i = 0;
 -      complain_at_indent (destructor->location, &i,
 -                          _("redeclaration for default tagged %%destructor"));
 -      i += SUB_INDENT;
 -      complain_at_indent (default_tagged_destructor.location, &i,
 -                        _("previous declaration"));
 -    }
 -  default_tagged_destructor = *destructor;
 -}
 -
 -void
 -default_tagless_destructor_set (code_props const *destructor)
 -{
 -  if (default_tagless_destructor.code)
 -    {
 -      unsigned i = 0;
 -      complain_at_indent (destructor->location, &i,
 -                          _("redeclaration for default tagless %%destructor"));
 -      i += SUB_INDENT;
 -      complain_at_indent (default_tagless_destructor.location, &i,
 -                          _("previous declaration"));
 -    }
 -  default_tagless_destructor = *destructor;
 -}
 -
 -void
 -default_tagged_printer_set (code_props const *printer)
 -{
 -  if (default_tagged_printer.code)
 -    {
 -      unsigned i = 0;
 -      complain_at_indent (printer->location, &i,
 -                          _("redeclaration for default tagged %%printer"));
 -      i += SUB_INDENT;
 -      complain_at_indent (default_tagged_printer.location, &i,
 -                        _("previous declaration"));
 -    }
 -  default_tagged_printer = *printer;
 -}
 -
 -void
 -default_tagless_printer_set (code_props const *printer)
 -{
 -  if (default_tagless_printer.code)
 -    {
 -      unsigned i = 0;
 -      complain_at_indent (printer->location, &i,
 -                          _("redeclaration for default tagless %%printer"));
 -      i += SUB_INDENT;
 -      complain_at_indent (default_tagless_printer.location, &i,
 -                        _("previous declaration"));
 -    }
 -  default_tagless_printer = *printer;
 +    complain_at (startsymbol_location, fatal,
 +                 _("the start symbol %s is a token"),
 +                 startsymbol->tag);
  }
diff --combined tests/input.at
index 188ed166e823ac8beadd5a6d4dfcbef5600696a2,86a955dc7e652161c85610be2d8cd0c12c4feee2..ac9be79d2f91f09307b37da7959def260d665da2
@@@ -60,9 -60,9 +60,9 @@@ exp: foo { $$; } foo { $2; } fo
  AT_BISON_CHECK([input.y], [1], [],
  [[input.y:5.12-13: error: $$ for the midrule at $2 of 'exp' has no declared type
  input.y:5.24-25: error: $2 of 'exp' has no declared type
 -input.y:5.6-32: warning: type clash on default action: <bar> != <>
 -input.y:6.6-8: warning: type clash on default action: <bar> != <>
 -input.y:7.5: warning: empty rule for typed nonterminal, and no action
 +input.y:5.6-32: warning: type clash on default action: <bar> != <> [-Wother]
 +input.y:6.6-8: warning: type clash on default action: <bar> != <> [-Wother]
 +input.y:7.5: warning: empty rule for typed nonterminal, and no action [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -72,6 -72,7 +72,6 @@@
  # --------------------------------
  # Generate the token, type, and destructor
  # declarations for the unused values tests.
 -
  m4_define([_AT_UNUSED_VALUES_DECLARATIONS],
  [[[%token <integer> INT;
  %type <integer> a b c d e f g h i j k l;
  
  
  # AT_CHECK_UNUSED_VALUES(DECLARATIONS_AFTER, CHECK_MIDRULE_VALUES)
 -# ------------------------------------------------------------------
 -# Generate a grammar to test unused values,
 -# compile it, run it.  If DECLARATIONS_AFTER
 -# is set, then the token, type, and destructor
 -# declarations are generated after the rules
 -# rather than before.  If CHECK_MIDRULE_VALUES
 -# is set, then --warnings=midrule-values is
 -# set.
 -
 +# ----------------------------------------------------------------
 +# Generate a grammar to test unused values, compile it, run it.  If
 +# DECLARATIONS_AFTER is set, then the token, type, and destructor
 +# declarations are generated after the rules rather than before.  If
 +# CHECK_MIDRULE_VALUES is set, then --warnings=midrule-values is set.
  m4_define([AT_CHECK_UNUSED_VALUES],
  [AT_DATA([input.y],
  m4_ifval($1, [
@@@ -113,39 -118,39 +113,39 @@@ _AT_UNUSED_VALUES_DECLARATIONS]
  )
  
  AT_BISON_CHECK(m4_ifval($2, [ --warnings=midrule-values ])[ input.y], [0], [],
 -[[input.y:11.10-32: warning: unset value: $]$[
 -input.y:11.10-32: warning: unused value: $]1[
 -input.y:11.10-32: warning: unused value: $]3[
 -input.y:11.10-32: warning: unused value: $]5[
 -input.y:12.9: warning: empty rule for typed nonterminal, and no action
 -]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$
 -input.y:13.26-41: warning: unset value: $$
 -]]])[[input.y:13.10-62: warning: unset value: $]$[
 -input.y:13.10-62: warning: unused value: $]3[
 -input.y:13.10-62: warning: unused value: $]5[
 -]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$
 -]]])[[input.y:14.10-49: warning: unset value: $]$[
 -input.y:14.10-49: warning: unused value: $]3[
 -input.y:14.10-49: warning: unused value: $]5[
 -input.y:15.10-37: warning: unset value: $]$[
 -input.y:15.10-37: warning: unused value: $]3[
 -input.y:15.10-37: warning: unused value: $]5[
 -input.y:17.10-58: warning: unset value: $]$[
 -input.y:17.10-58: warning: unused value: $]1[
 -]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[
 -]]])[[input.y:17.10-58: warning: unused value: $]3[
 -]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[
 -]]])[[input.y:17.10-58: warning: unused value: $]5[
 -input.y:18.10-72: warning: unset value: $]$[
 -input.y:18.10-72: warning: unused value: $]1[
 -input.y:18.10-72: warning: unused value: $]3[
 -]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[
 -]]])[[input.y:18.10-72: warning: unused value: $]5[
 -]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[
 -]]])[[input.y:21.10-68: warning: unset value: $]$[
 -input.y:21.10-68: warning: unused value: $]1[
 -input.y:21.10-68: warning: unused value: $]2[
 -]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[
 +[[input.y:11.10-32: warning: unset value: $]$[ [-Wother]
 +input.y:11.10-32: warning: unused value: $]1[ [-Wother]
 +input.y:11.10-32: warning: unused value: $]3[ [-Wother]
 +input.y:11.10-32: warning: unused value: $]5[ [-Wother]
 +input.y:12.9: warning: empty rule for typed nonterminal, and no action [-Wother]
 +]]m4_ifval($2, [[[input.y:13.14-20: warning: unset value: $$ [-Wmidrule-values]
 +input.y:13.26-41: warning: unset value: $$ [-Wmidrule-values]
 +]]])[[input.y:13.10-62: warning: unset value: $]$[ [-Wother]
 +input.y:13.10-62: warning: unused value: $]3[ [-Wother]
 +input.y:13.10-62: warning: unused value: $]5[ [-Wother]
 +]]m4_ifval($2, [[[input.y:14.14-16: warning: unset value: $$ [-Wmidrule-values]
 +]]])[[input.y:14.10-49: warning: unset value: $]$[ [-Wother]
 +input.y:14.10-49: warning: unused value: $]3[ [-Wother]
 +input.y:14.10-49: warning: unused value: $]5[ [-Wother]
 +input.y:15.10-37: warning: unset value: $]$[ [-Wother]
 +input.y:15.10-37: warning: unused value: $]3[ [-Wother]
 +input.y:15.10-37: warning: unused value: $]5[ [-Wother]
 +input.y:17.10-58: warning: unset value: $]$[ [-Wother]
 +input.y:17.10-58: warning: unused value: $]1[ [-Wother]
 +]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]2[ [-Wmidrule-values]
 +]]])[[input.y:17.10-58: warning: unused value: $]3[ [-Wother]
 +]]m4_ifval($2, [[[input.y:17.10-58: warning: unused value: $]4[ [-Wmidrule-values]
 +]]])[[input.y:17.10-58: warning: unused value: $]5[ [-Wother]
 +input.y:18.10-72: warning: unset value: $]$[ [-Wother]
 +input.y:18.10-72: warning: unused value: $]1[ [-Wother]
 +input.y:18.10-72: warning: unused value: $]3[ [-Wother]
 +]]m4_ifval($2, [[[input.y:18.10-72: warning: unused value: $]4[ [-Wmidrule-values]
 +]]])[[input.y:18.10-72: warning: unused value: $]5[ [-Wother]
 +]]m4_ifval($2, [[[input.y:20.10-55: warning: unused value: $]3[ [-Wmidrule-values]
 +]]])[[input.y:21.10-68: warning: unset value: $]$[ [-Wother]
 +input.y:21.10-68: warning: unused value: $]1[ [-Wother]
 +input.y:21.10-68: warning: unused value: $]2[ [-Wother]
 +]]m4_ifval($2, [[[input.y:21.10-68: warning: unused value: $]4[ [-Wmidrule-values]
  ]]]))])
  
  
@@@ -200,29 -205,29 +200,29 @@@ start: 
  ]])
  
  AT_BISON_CHECK([input.y], [1], [],
 -[[input.y:1.13-29: error: redeclaration for default tagged %destructor
 +[[input.y:1.13-29: error: %destructor redeclaration for <*>
  input.y:1.13-29:     previous declaration
 -input.y:2.10-24: error: redeclaration for default tagged %printer
 +input.y:2.10-24: error: %printer redeclaration for <*>
  input.y:2.10-24:     previous declaration
 -input.y:4.13-29: error: redeclaration for default tagged %destructor
 +input.y:4.13-29: error: %destructor redeclaration for <*>
  input.y:1.13-29:     previous declaration
 -input.y:5.10-24: error: redeclaration for default tagged %printer
 +input.y:5.10-24: error: %printer redeclaration for <*>
  input.y:2.10-24:     previous declaration
 -input.y:7.13-29: error: redeclaration for default tagless %destructor
 +input.y:7.13-29: error: %destructor redeclaration for <>
  input.y:7.13-29:     previous declaration
 -input.y:8.10-24: error: redeclaration for default tagless %printer
 +input.y:8.10-24: error: %printer redeclaration for <>
  input.y:8.10-24:     previous declaration
 -input.y:10.13-29: error: redeclaration for default tagless %destructor
 +input.y:10.13-29: error: %destructor redeclaration for <>
  input.y:7.13-29:      previous declaration
 -input.y:11.10-24: error: redeclaration for default tagless %printer
 +input.y:11.10-24: error: %printer redeclaration for <>
  input.y:8.10-24:      previous declaration
 -input.y:17.13-29: error: redeclaration for default tagged %destructor
 +input.y:17.13-29: error: %destructor redeclaration for <*>
  input.y:4.13-29:      previous declaration
 -input.y:18.10-24: error: redeclaration for default tagged %printer
 +input.y:18.10-24: error: %printer redeclaration for <*>
  input.y:5.10-24:      previous declaration
 -input.y:20.13-29: error: redeclaration for default tagless %destructor
 +input.y:20.13-29: error: %destructor redeclaration for <>
  input.y:10.13-29:     previous declaration
 -input.y:21.10-24: error: redeclaration for default tagless %printer
 +input.y:21.10-24: error: %printer redeclaration for <>
  input.y:11.10-24:     previous declaration
  ]])
  
@@@ -271,123 -276,6 +271,123 @@@ input.y:5.10-24:      previous declarat
  
  AT_CLEANUP
  
 +## ------------------- ##
 +## Undefined symbols.  ##
 +## ------------------- ##
 +
 +AT_SETUP([Undefined symbols])
 +
 +AT_DATA([[input.y]],
 +[[%printer {} foo baz
 +%destructor {} bar
 +%type <foo> qux
 +%%
 +exp: bar;
 +]])
 +
 +AT_BISON_CHECK([input.y], [1], [],
 +[[input.y:2.16-18: error: symbol bar is used, but is not defined as a token and has no rules
 +input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother]
 +input.y:1.13-15: warning: symbol foo is used, but is not defined as a token and has no rules [-Wother]
 +input.y:3.13-15: warning: symbol qux is used, but is not defined as a token and has no rules [-Wother]
 +]])
 +
 +AT_CLEANUP
 +
 +
 +## ----------------------------------------------------- ##
 +## Unassociated types used for a printer or destructor.  ##
 +## ----------------------------------------------------- ##
 +
 +AT_SETUP([Unassociated types used for a printer or destructor])
 +
 +AT_DATA([[input.y]],
 +[[%token <type1> tag1
 +%type <type2> tag2
 +
 +%printer { } <type1> <type3>
 +%destructor { } <type2> <type4>
 +
 +%%
 +
 +exp: tag1 { $1; }
 +   | tag2 { $1; }
 +
 +tag2: "a" { $$; }
 +]])
 +
 +AT_BISON_CHECK([input.y], [0], [],
 +[[input.y:4.22-28: warning: type <type3> is used, but is not associated to any symbol [-Wother]
 +input.y:5.25-31: warning: type <type4> is used, but is not associated to any symbol [-Wother]
 +]])
 +
 +AT_CLEANUP
 +
 +
 +## --------------------------------- ##
 +## Useless printers or destructors.  ##
 +## --------------------------------- ##
 +
 +AT_SETUP([Useless printers or destructors])
 +
 +# AT_TEST([INPUT], [STDERR])
 +# --------------------------
 +m4_pushdef([AT_TEST],
 +[AT_DATA([[input.y]],
 +[$1
 +])
 +AT_BISON_CHECK([input.y], [0], [], [$2
 +])])
 +
 +AT_TEST([[%token <type1> token1
 +%token <type2> token2
 +%token <type3> token3
 +%token <type4> token4
 +%token <type5> token51 token52
 +%token <type6> token61 token62
 +%token <type7> token7
 +
 +%printer {} token1
 +%destructor {} token2
 +%printer {} token51
 +%destructor {} token61
 +
 +%printer {} token7
 +
 +%printer {} <type1>
 +%destructor {} <type2>
 +%printer {} <type3>
 +%destructor {} <type4>
 +
 +%printer {} <type5>
 +%destructor {} <type6>
 +
 +%destructor {} <type7>
 +
 +%%
 +exp: "a";]],
 +[[input.y:16.13-19: warning: useless %printer for type <type1> [-Wother]
 +input.y:17.16-22: warning: useless %destructor for type <type2> [-Wother]]])
 +
 +# If everybody is typed, <> is useless.
 +AT_TEST([[%type <type> exp
 +%token <type> a
 +%printer {} <> <*>
 +%%
 +exp: a;]],
 +[[input.y:3.13-14: warning: useless %printer for type <> [-Wother]]])
 +
 +# If nobody is typed, <*> is useless.
 +AT_TEST([[%token a
 +%printer {} <> <*>
 +%%
 +exp: a;]],
 +[[input.y:2.16-18: warning: useless %printer for type <*> [-Wother]]])
 +
 +m4_popdef([AT_TEST])
 +
 +AT_CLEANUP
 +
  
  ## ---------------------------------------- ##
  ## Unused values with default %destructor.  ##
@@@ -407,9 -295,9 +407,9 @@@ tagged: { } 
  ]])
  
  AT_BISON_CHECK([input.y], [0], [],
 -[[input.y:6.8-45: warning: unset value: $$
 -input.y:6.8-45: warning: unused value: $2
 -input.y:7.6-8: warning: unset value: $$
 +[[input.y:6.8-45: warning: unset value: $$ [-Wother]
 +input.y:6.8-45: warning: unused value: $2 [-Wother]
 +input.y:7.6-8: warning: unset value: $$ [-Wother]
  ]])
  
  AT_DATA([[input.y]],
@@@ -424,8 -312,8 +424,8 @@@ tagged: { } 
  ]])
  
  AT_BISON_CHECK([input.y], [0], [],
 -[[input.y:6.8-45: warning: unused value: $4
 -input.y:8.9-11: warning: unset value: $$
 +[[input.y:6.8-45: warning: unused value: $4 [-Wother]
 +input.y:8.9-11: warning: unset value: $$ [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -448,9 -336,9 +448,9 @@@ end: { }  
  ]])
  
  AT_BISON_CHECK([input.y], [0], [],
 -[[input.y:6.8-22: warning: unset value: $$
 -input.y:6.8-22: warning: unused value: $2
 -input.y:7.6-8: warning: unset value: $$
 +[[input.y:6.8-22: warning: unset value: $$ [-Wother]
 +input.y:6.8-22: warning: unused value: $2 [-Wother]
 +input.y:7.6-8: warning: unset value: $$ [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -628,7 -516,7 +628,7 @@@ yylex (void
  }
  ]])
  
 -# Pacify Emacs' font-lock-mode: "
 +# Pacify Emacs'font-lock-mode: "
  
  AT_DATA([main.c],
  [[typedef int value;
@@@ -707,8 -595,8 +707,8 @@@ AT_CHECK_REQUIRE(100.0, 63
  
  AT_SETUP([String aliases for character tokens])
  
 -# Bison once thought a character token and its alias were different symbols
 -# with the same user token number.
 +# Bison once thought a character token and its alias were different
 +# symbols with the same user token number.
  
  AT_DATA_GRAMMAR([input.y],
  [[%token 'a' "a"
@@@ -751,15 -639,15 +751,15 @@@ without_period: "WITHOUT.PERIOD"
  AT_BISON_OPTION_POPDEFS
  
  # POSIX Yacc accept periods, but not dashes.
 -AT_BISON_CHECK([--yacc input.y], [1], [],
 -[[input.y:9.8-16: POSIX Yacc forbids dashes in symbol names: WITH-DASH
 -input.y:18.8-16: POSIX Yacc forbids dashes in symbol names: with-dash
 +AT_BISON_CHECK([--yacc -Wno-error input.y], [], [],
 +[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
 +input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
  ]])
  
  # So warn about them.
  AT_BISON_CHECK([-Wyacc input.y], [], [],
 -[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH
 -input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash
 +[[input.y:9.8-16: warning: POSIX Yacc forbids dashes in symbol names: WITH-DASH [-Wyacc]
 +input.y:18.8-16: warning: POSIX Yacc forbids dashes in symbol names: with-dash [-Wyacc]
  ]])
  
  # Dashes are fine for GNU Bison.
@@@ -805,9 -693,9 +805,9 @@@ start: DECIMAL_1 HEXADECIMAL_2
  
  AT_BISON_CHECK([redecl.y], [1], [],
  [[redecl.y:10.10-22: error: user token number 11259375 redeclaration for HEXADECIMAL_1
- redecl.y:9.8-16:   previous declaration for DECIMAL_1
+ redecl.y:9.8-16:       previous declaration for DECIMAL_1
  redecl.y:12.10-18: error: user token number 16702650 redeclaration for DECIMAL_2
- redecl.y:11.10-22: previous declaration for HEXADECIMAL_2
+ redecl.y:11.10-22:     previous declaration for HEXADECIMAL_2
  ]])
  
  AT_DATA_GRAMMAR([too-large.y],
@@@ -832,10 -720,10 +832,10 @@@ AT_CLEANU
  
  AT_SETUP([Unclosed constructs])
  
 -# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed constructs, so
 -# they were prepended to whatever it STRING_GROW'ed next.  It also threw them
 -# away rather than returning them to the parser.  The effect was confusing
 -# subsequent error messages.
 +# Bison's scan-gram.l once forgot to STRING_FINISH some unclosed
 +# constructs, so they were prepended to whatever it STRING_GROW'ed
 +# next.  It also threw them away rather than returning them to the
 +# parser.  The effect was confusing subsequent error messages.
  
  AT_DATA([input.y],
  [[%token A "a
@@@ -877,8 -765,8 +877,8 @@@ AT_CLEANU
  
  AT_SETUP([%start after first rule])
  
 -# Bison once complained that a %start after the first rule was a redeclaration
 -# of the start symbol.
 +# Bison once complained that a %start after the first rule was a
 +# redeclaration of the start symbol.
  
  AT_DATA([input.y],
  [[%%
@@@ -927,7 -815,7 +927,7 @@@ start: %prec PREC 
  ]])
  
  AT_BISON_CHECK([[input.y]], [[0]], [],
 -[[input.y:2.8-17: warning: token for %prec is not defined: PREC
 +[[input.y:2.8-17: warning: token for %prec is not defined: PREC [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -1181,8 -1069,7 +1181,8 @@@ AT_DATA([[input.y]]
  start: ;
  ]])
  AT_BISON_CHECK([[input.y]], [1], [],
 -[[input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
 +[[input.y:1.9-21: warning: deprecated %define variable name: 'api.push_pull', use 'api.push-pull' [-Wdeprecated]
 +input.y:1.9-21: error: invalid value for %define variable 'api.push-pull': 'neither'
  input.y:1.9-21: error: accepted value: 'pull'
  input.y:1.9-21: error: accepted value: 'push'
  input.y:1.9-21: error: accepted value: 'both'
@@@ -1194,20 -1081,7 +1194,20 @@@ AT_DATA([[input.y]]
  start: ;
  ]])
  AT_BISON_CHECK([[input.y]], [1], [],
 -[[input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
 +[[input.y:1.9-34: warning: deprecated %define variable name: 'lr.keep_unreachable_states', use 'lr.keep-unreachable-states' [-Wdeprecated]
 +input.y:1.9-34: error: invalid value for %define Boolean variable 'lr.keep-unreachable-states'
 +]])
 +
 +AT_DATA([[input.y]],
 +[[%define namespace "foo"
 +%define api.namespace "foo"
 +%%
 +start: ;
 +]])
 +AT_BISON_CHECK([[input.y]], [1], [],
 +[[input.y:1.9-17: warning: deprecated %define variable name: 'namespace', use 'api.namespace' [-Wdeprecated]
 +input.y:2.9-21: error: %define variable 'api.namespace' redefined
 +input.y:1.9-17:     previous definition
  ]])
  
  AT_DATA([[input.y]],
@@@ -1268,14 -1142,14 +1268,14 @@@ m4_define([AT_CHECK_NAMESPACE_ERROR]
  AT_DATA([[input.y]],
  [[%language "C++"
  %defines
 -%define namespace "]$1["
 +%define api.namespace "]$1["
  %%
  start: ;
  ]])
  
  AT_BISON_CHECK([[input.y]], [1], [],
  [m4_foreach([b4_arg], m4_dquote(m4_shift($@)),
 -[[input.y:3.9-17: error: ]b4_arg[
 +[[input.y:3.9-21: error: ]b4_arg[
  ]])])
  ])
  
@@@ -1324,10 -1198,10 +1324,10 @@@ start: 
  AT_CHECK([[perl -e "print 'start: \'';" >> empty.y || exit 77]])
  
  AT_BISON_CHECK([empty.y], [1], [],
 -[[empty.y:2.8-9: warning: empty character literal
 -empty.y:3.8-4.0: warning: empty character literal
 +[[empty.y:2.8-9: warning: empty character literal [-Wother]
 +empty.y:3.8-4.0: warning: empty character literal [-Wother]
  empty.y:3.8-4.0: error: missing "'" at end of line
 -empty.y:4.8: warning: empty character literal
 +empty.y:4.8: warning: empty character literal [-Wother]
  empty.y:4.8: error: missing "'" at end of file
  ]])
  
@@@ -1339,10 -1213,10 +1339,10 @@@ start: 'a
  AT_CHECK([[perl -e "print 'start: \'ab';" >> two.y || exit 77]])
  
  AT_BISON_CHECK([two.y], [1], [],
 -[[two.y:2.8-11: warning: extra characters in character literal
 -two.y:3.8-4.0: warning: extra characters in character literal
 +[[two.y:2.8-11: warning: extra characters in character literal [-Wother]
 +two.y:3.8-4.0: warning: extra characters in character literal [-Wother]
  two.y:3.8-4.0: error: missing "'" at end of line
 -two.y:4.8-10: warning: extra characters in character literal
 +two.y:4.8-10: warning: extra characters in character literal [-Wother]
  two.y:4.8-10: error: missing "'" at end of file
  ]])
  
@@@ -1354,10 -1228,10 +1354,10 @@@ start: 'ab
  AT_CHECK([[perl -e "print 'start: \'abc';" >> three.y || exit 77]])
  
  AT_BISON_CHECK([three.y], [1], [],
 -[[three.y:2.8-12: warning: extra characters in character literal
 -three.y:3.8-4.0: warning: extra characters in character literal
 +[[three.y:2.8-12: warning: extra characters in character literal [-Wother]
 +three.y:3.8-4.0: warning: extra characters in character literal [-Wother]
  three.y:3.8-4.0: error: missing "'" at end of line
 -three.y:4.8-11: warning: extra characters in character literal
 +three.y:4.8-11: warning: extra characters in character literal [-Wother]
  three.y:4.8-11: error: missing "'" at end of file
  ]])
  
@@@ -1385,25 -1259,25 +1385,25 @@@ AT_CHECK([[perl -e 'print "start: \"\\\
  
  AT_BISON_CHECK([input.y], [1], [],
  [[input.y:2.9-12: error: invalid number after \-escape: 777
 -input.y:2.8-13: warning: empty character literal
 +input.y:2.8-13: warning: empty character literal [-Wother]
  input.y:2.16-17: error: invalid number after \-escape: 0
 -input.y:2.15-18: warning: empty character literal
 +input.y:2.15-18: warning: empty character literal [-Wother]
  input.y:2.21-25: error: invalid number after \-escape: xfff
 -input.y:2.20-26: warning: empty character literal
 +input.y:2.20-26: warning: empty character literal [-Wother]
  input.y:2.29-31: error: invalid number after \-escape: x0
 -input.y:2.28-32: warning: empty character literal
 +input.y:2.28-32: warning: empty character literal [-Wother]
  input.y:3.9-14: error: invalid number after \-escape: uffff
 -input.y:3.8-15: warning: empty character literal
 +input.y:3.8-15: warning: empty character literal [-Wother]
  input.y:3.18-23: error: invalid number after \-escape: u0000
 -input.y:3.17-24: warning: empty character literal
 +input.y:3.17-24: warning: empty character literal [-Wother]
  input.y:3.27-36: error: invalid number after \-escape: Uffffffff
 -input.y:3.26-37: warning: empty character literal
 +input.y:3.26-37: warning: empty character literal [-Wother]
  input.y:3.40-49: error: invalid number after \-escape: U00000000
 -input.y:3.39-50: warning: empty character literal
 +input.y:3.39-50: warning: empty character literal [-Wother]
  input.y:4.9-10: error: invalid character after \-escape: ' '
 -input.y:4.8-11: warning: empty character literal
 +input.y:4.8-11: warning: empty character literal [-Wother]
  input.y:4.14-15: error: invalid character after \-escape: A
 -input.y:4.13-16: warning: empty character literal
 +input.y:4.13-16: warning: empty character literal [-Wother]
  input.y:5.9-16: error: invalid character after \-escape: \t
  input.y:5.17: error: invalid character after \-escape: \f
  input.y:5.18: error: invalid character after \-escape: \0
@@@ -1448,19 -1322,20 +1448,19 @@@ foo-bar: 
  
  # -Werror is not enabled by -Wall or equivalent.
  AT_BISON_CHECK([[-Wall input.y]], [[0]], [[]],
 -[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  AT_BISON_CHECK([[-W input.y]], [[0]], [[]],
 -[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  AT_BISON_CHECK([[-Wno-none input.y]], [[0]], [[]],
 -[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar [-Wyacc]
  ]])
  
  # -Werror is not disabled by -Wnone or equivalent.
  AT_BISON_CHECK([[-Werror,none,yacc input.y]], [[1]], [[]], [[stderr]])
  AT_CHECK([[sed 's/^.*bison:/bison:/' stderr]], [[0]],
 -[[bison: warnings being treated as errors
 -input.y:2.1-7: warning: POSIX Yacc forbids dashes in symbol names: foo-bar
 +[[input.y:2.1-7: error: POSIX Yacc forbids dashes in symbol names: foo-bar [-Werror=yacc]
  ]])
  [mv stderr experr]
  AT_BISON_CHECK([[-Werror,no-all,yacc input.y]], [[1]], [[]], [[experr]])
@@@ -1507,8 -1382,7 +1507,8 @@@ AT_SETUP([[Stray $ or @]]
  # check that the warnings are reported once, not three times.
  
  AT_DATA_GRAMMAR([[input.y]],
 -[[%token TOK
 +[[%type <TYPE> exp
 +%token <TYPE> TOK TOK2
  %destructor     { $%; @%; } <*> exp TOK;
  %initial-action { $%; @%; };
  %printer        { $%; @%; } <*> exp TOK;
@@@ -1517,14 -1391,14 +1517,14 @@@ exp: TOK        { $%; @%; $$ = $1; }
  ]])
  
  AT_BISON_CHECK([[input.y]], 0, [],
 -[[input.y:10.19: warning: stray '$'
 -input.y:10.23: warning: stray '@'
 -input.y:11.19: warning: stray '$'
 -input.y:11.23: warning: stray '@'
 -input.y:12.19: warning: stray '$'
 -input.y:12.23: warning: stray '@'
 -input.y:14.19: warning: stray '$'
 -input.y:14.23: warning: stray '@'
 +[[input.y:11.19: warning: stray '$' [-Wother]
 +input.y:11.23: warning: stray '@' [-Wother]
 +input.y:12.19: warning: stray '$' [-Wother]
 +input.y:12.23: warning: stray '@' [-Wother]
 +input.y:13.19: warning: stray '$' [-Wother]
 +input.y:13.23: warning: stray '@' [-Wother]
 +input.y:15.19: warning: stray '$' [-Wother]
 +input.y:15.23: warning: stray '@' [-Wother]
  ]])
  
  AT_CLEANUP
@@@ -1547,7 -1421,6 +1547,7 @@@ m4_pushdef([AT_TEST]
  [AT_DATA([[input.y]],
  [[%type <$1(DEAD %type)> exp
  %token <$1(DEAD %token)> a
 +%token b
  %initial-action
  {
    $$;
  };
  %%
  exp:
 -  a a[last]
 +  a a[name] b
    {
      $$;
      $][1;
      $<$1(DEAD action 1)>$
      $<$1(DEAD action 2)>1
 -    $<$1(DEAD action 3)>last
 +    $<$1(DEAD action 3)>name
      $<$1(DEAD action 4)>0
      ;
    };