bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master: merge maint


From: Akim Demaille
Subject: master: merge maint
Date: Tue, 13 Jan 2015 15:49:57 +0100

This is the merge commit itself:

commit dfd5b89d017bda9801814a5d817f8ab1095e1443
Merge: 13e294e ca5a716
Author: Akim Demaille <address@hidden>
Date:   Tue Jan 13 14:43:02 2015 +0100

    Merge remote-tracking branch 'origin/maint'
    
    * origin/maint:
      tests: split a large test case into several smaller ones
      package: a bit of trouble shooting indications
      doc: liby's main arms the internationalization
      bison: avoid warnings from static code analysis
      c++: fix the use of destructors when variants are enabled
      style: tests: simplify the handling of some C++ tests
      c++: symbols can be empty, so use it
      c++: variants: don't leak the lookahead in error recovery
      c++: provide a means to clear symbols
      c++: clean up the handling of empty symbols
      c++: comment and style changes
      c++: variants: comparing addresses of typeid.name() is undefined
      c++: locations: complete the API and fix comments
      build: do not clean figure sources in make clean

diff --cc src/symlist.c
index 38f5fc8,d851463..d70763b
--- a/src/symlist.c
+++ b/src/symlist.c
@@@ -198,14 -192,7 +192,7 @@@ symbol_list_n_get (symbol_list *l, int 
  uniqstr
  symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
  {
-   l = symbol_list_n_get (l, n);
-   if (!l)
-     {
-       complain (&loc, complaint, _("invalid $ value: $%d"), n);
-       return NULL;
-     }
-   aver (l->content_type == SYMLIST_SYMBOL);
-   return l->content.sym->content->type_name;
 -  return symbol_list_n_get (l, n)->content.sym->type_name;
++  return symbol_list_n_get (l, n)->content.sym->content->type_name;
  }
  
  bool


and this is the diff with the previous state of master:

diff --git a/NEWS b/NEWS
index 490e89e..1877194 100644
--- a/NEWS
+++ b/NEWS
@@ -4,19 +4,23 @@ GNU Bison NEWS
 
 ** Bug fixes
 
-*** Named %union support
+*** C++ with Variants (lalr1.cc)
+
+  Problems with %destructor and '%define parse.assert' have been fixed.
+
+*** Named %union support (yacc.c, glr.c)
 
   Bison 3.0 introduced a regression on named %union such as
 
     %union foo { int ival; };
 
-  The possibility to use a name was introduced ``for Yacc compatibility''.
+  The possibility to use a name was introduced "for Yacc compatibility".
   It is however not required by POSIX Yacc, and its usefulness is not clear.
 
-*** %define api.value.type union with %defines
+*** %define api.value.type union with %defines (yacc.c, glr.c)
 
-  The yacc.c and glr.c parsers were broken when %defines was used
-  together with "%define api.value.type union".
+  The C parsers were broken when %defines was used together with "%define
+  api.value.type union".
 
 *** Redeclarations are reported in proper order
 
diff --git a/README-hacking b/README-hacking
index 4b77374..25e4ef3 100644
--- a/README-hacking
+++ b/README-hacking
@@ -103,15 +103,17 @@ to perform the first checkout of the submodules, run
 
        $ git submodule update --init
 
-Git submodule support is weak before versions 1.6 and later, you
-should probably upgrade Git if your version is older.
+Git submodule support is weak before versions 1.6 and later, upgrade Git if
+your version is older.
 
 The next step is to get other files needed to build, which are
 extracted from other source packages:
 
         $ ./bootstrap
 
-And there you are!  Just
+If it fails with missing symbols (e.g., "error: possibly undefined macro:
+AC_PROG_GNU_M4"), you are likely to have forgotten the submodule
+initialization part.  Otherwise, there you are!  Just
 
         $ ./configure
         $ make
diff --git a/THANKS b/THANKS
index 2436f00..b984910 100644
--- a/THANKS
+++ b/THANKS
@@ -12,6 +12,7 @@ Andreas Schwab            address@hidden
 Andrew Suffield           address@hidden
 Angelo Borsotti           address@hidden
 Anthony Heading           address@hidden
+Antonio Silva Correia     address@hidden
 Arnold Robbins            address@hidden
 Art Haas                  address@hidden
 Baron Schwartz            address@hidden
@@ -82,15 +83,19 @@ Martin Mokrejs            address@hidden
 Martin Nylin              address@hidden
 Matt Kraai                address@hidden
 Matt Rosing               address@hidden
+Michael Catanzaro         address@hidden
 Michael Felt              address@hidden
 Michael Hayes             address@hidden
 Michael Raskin            address@hidden
+Michel d'Hooge            address@hidden
 Michiel De Wilde          address@hidden
 Mickael Labau             address@hidden
 Mike Castle               address@hidden
+Mike Sullivan             address@hidden
 Neil Booth                address@hidden
 Nelson H. F. Beebe        address@hidden
 Nick Bowler               address@hidden
+Nicolas Bedon             address@hidden
 Nicolas Burrus            address@hidden
 Nicolas Tisserand         address@hidden
 Noah Friedman             address@hidden
@@ -132,6 +137,7 @@ Steve Murphy              address@hidden
 Sum Wu                    address@hidden
 Théophile Ranquet         address@hidden
 Thiru Ramakrishnan        address@hidden
+Thomas Jahns              address@hidden
 Tim Josling               address@hidden
 Tim Landscheidt           address@hidden
 Tim Van Holder            address@hidden
diff --git a/data/c++.m4 b/data/c++.m4
index 7c0fd78..4321c30 100644
--- a/data/c++.m4
+++ b/data/c++.m4
@@ -174,9 +174,12 @@ m4_define([b4_public_types_declare],
     /// (External) token type, as returned by yylex.
     typedef token::yytokentype token_type;
 
-    /// Internal symbol number.
+    /// Symbol type: an internal symbol number.
     typedef int symbol_number_type;
 
+    /// The symbol type number to denote an empty symbol.
+    enum { empty_symbol = -2 };
+
     /// Internal symbol number for tokens (subsumed by symbol_number_type).
     typedef ]b4_int_type_for([b4_translate])[ token_number_type;
 
@@ -209,8 +212,15 @@ m4_define([b4_public_types_declare],
                     const semantic_type& v]b4_locations_if([,
                     const location_type& l])[);
 
+      /// Destroy the symbol.
       ~basic_symbol ();
 
+      /// Destroy contents, and record that is empty.
+      void clear ();
+
+      /// Whether empty.
+      bool empty () const;
+
       /// Destructive move, \a s is emptied into this.
       void move (basic_symbol& s);
 
@@ -240,21 +250,23 @@ m4_define([b4_public_types_declare],
       /// Constructor from (external) token numbers.
       by_type (kind_type t);
 
+      /// Record that this symbol is empty.
+      void clear ();
+
       /// Steal the symbol type from \a that.
       void move (by_type& that);
 
       /// The (internal) type number (corresponding to \a type).
-      /// -1 when this symbol is empty.
+      /// \a empty when empty.
       symbol_number_type type_get () const;
 
       /// The token.
       token_type token () const;
 
-      enum { empty = 0 };
-
       /// The symbol type.
-      /// -1 when this symbol is empty.
-      token_number_type type;
+      /// \a empty_symbol when empty.
+      /// An int, not token_number_type, to be able to store empty_symbol.
+      int type;
     };
 
     /// "External" symbols: returned by the scanner.
@@ -323,9 +335,18 @@ m4_define([b4_public_types_define],
   template <typename Base>
   inline
   ]b4_parser_class_name[::basic_symbol<Base>::~basic_symbol ()
+  {
+    clear ();
+  }
+
+  template <typename Base>
+  inline
+  void
+  ]b4_parser_class_name[::basic_symbol<Base>::clear ()
   {]b4_variant_if([[
     // User destructor.
     symbol_number_type yytype = this->type_get ();
+    basic_symbol<Base>& yysym = *this;
     switch (yytype)
     {
 ]b4_symbol_foreach([b4_symbol_destructor])dnl
@@ -335,6 +356,15 @@ m4_define([b4_public_types_define],
 
     // Type destructor.
   ]b4_symbol_variant([[yytype]], [[value]], [[template destroy]])])[
+    Base::clear ();
+  }
+
+  template <typename Base>
+  inline
+  bool
+  ]b4_parser_class_name[::basic_symbol<Base>::empty () const
+  {
+    return Base::type_get () == empty_symbol;
   }
 
   template <typename Base>
@@ -352,7 +382,7 @@ m4_define([b4_public_types_define],
   // by_type.
   inline
   ]b4_parser_class_name[::by_type::by_type ()
-     : type (empty)
+    : type (empty_symbol)
   {}
 
   inline
@@ -367,10 +397,17 @@ m4_define([b4_public_types_define],
 
   inline
   void
+  ]b4_parser_class_name[::by_type::clear ()
+  {
+    type = empty_symbol;
+  }
+
+  inline
+  void
   ]b4_parser_class_name[::by_type::move (by_type& that)
   {
     type = that.type;
-    that.type = empty;
+    that.clear ();
   }
 
   inline
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 1bbec8a..0e0e17a 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -214,9 +214,9 @@ b4_location_define])])[
 
     /// Generate an error message.
     /// \param yystate   the state where the error occurred.
-    /// \param yytoken   the lookahead token type, or yyempty_.
+    /// \param yyla      the lookahead token.
     virtual std::string yysyntax_error_ (state_type yystate,
-                                         symbol_number_type yytoken) const;
+                                         const symbol_type& yyla) const;
 
     /// Compute post-reduction state.
     /// \param yystate   the current state
@@ -288,16 +288,21 @@ b4_location_define])])[
       /// Copy constructor.
       by_state (const by_state& other);
 
+      /// Record that this symbol is empty.
+      void clear ();
+
       /// Steal the symbol type from \a that.
       void move (by_state& that);
 
       /// The (internal) type number (corresponding to \a state).
-      /// "empty" when empty.
+      /// \a empty_symbol when empty.
       symbol_number_type type_get () const;
 
-      enum { empty = 0 };
+      /// The state number used to denote an empty symbol.
+      enum { empty_state = -1 };
 
       /// The state.
+      /// \a empty when empty.
       state_type state;
     };
 
@@ -338,13 +343,12 @@ b4_location_define])])[
     /// Pop \a n symbols the three stacks.
     void yypop_ (unsigned int n = 1);
 
-    // Constants.
+    /// Constants.
     enum
     {
       yyeof_ = 0,
       yylast_ = ]b4_last[,     ///< Last index in yytable_.
       yynnts_ = ]b4_nterms_number[,  ///< Number of nonterminal symbols.
-      yyempty_ = -2,
       yyfinal_ = ]b4_final_state_number[, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
@@ -464,7 +468,7 @@ m4_if(b4_prefix, [yy], [],
 #endif // !]b4_api_PREFIX[DEBUG
 
 #define yyerrok         (yyerrstatus_ = 0)
-#define yyclearin       (yyempty = true)
+#define yyclearin       (yyla.clear ())
 
 #define YYACCEPT        goto yyacceptlab
 #define YYABORT         goto yyabortlab
@@ -533,7 +537,7 @@ m4_if(b4_prefix, [yy], [],
   // by_state.
   inline
   ]b4_parser_class_name[::by_state::by_state ()
-    : state (empty)
+    : state (empty_state)
   {}
 
   inline
@@ -543,10 +547,17 @@ m4_if(b4_prefix, [yy], [],
 
   inline
   void
+  ]b4_parser_class_name[::by_state::clear ()
+  {
+    state = empty_state;
+  }
+
+  inline
+  void
   ]b4_parser_class_name[::by_state::move (by_state& that)
   {
     state = that.state;
-    that.state = empty;
+    that.clear ();
   }
 
   inline
@@ -558,7 +569,7 @@ m4_if(b4_prefix, [yy], [],
   ]b4_parser_class_name[::symbol_number_type
   ]b4_parser_class_name[::by_state::type_get () const
   {
-    return state == empty ? 0 : yystos_[state];
+    return state == empty_state ? empty_symbol : yystos_[state];
   }
 
   inline
@@ -574,7 +585,7 @@ m4_if(b4_prefix, [yy], [],
                                       [value], [move], [that.value])],
                    [[value = that.value;]])[
     // that is emptied.
-    that.type = empty;
+    that.type = empty_symbol;
   }
 
   inline
@@ -695,9 +706,6 @@ m4_if(b4_prefix, [yy], [],
   int
   ]b4_parser_class_name[::parse ()
   {
-    /// Whether yyla contains a lookahead.
-    bool yyempty = true;
-
     // State.
     int yyn;
     /// Length of the RHS of the rule being reduced.
@@ -754,7 +762,7 @@ b4_dollar_popdef])[]dnl
       goto yydefault;
 
     // Read a lookahead token.
-    if (yyempty)
+    if (yyla.empty ())
       {
         YYCDEBUG << "Reading a token: ";
         try
@@ -768,7 +776,6 @@ b4_dollar_popdef])[]dnl
             error (yyexc);
             goto yyerrlab1;
           }
-        yyempty = false;
       }
     YY_SYMBOL_PRINT ("Next token is", yyla);
 
@@ -788,9 +795,6 @@ b4_dollar_popdef])[]dnl
         goto yyreduce;
       }
 
-    // Discard the token being shifted.
-    yyempty = true;
-
     // Count tokens shifted since error; after three, turn off error status.
     if (yyerrstatus_)
       --yyerrstatus_;
@@ -873,8 +877,7 @@ b4_dollar_popdef])[]dnl
       {
         ++yynerrs_;
         error (]b4_join(b4_locations_if([yyla.location]),
-                        [[yysyntax_error_ (yystack_[0].state,
-                                           yyempty ? yyempty_ : yyla.type_get 
())]])[);
+                        [[yysyntax_error_ (yystack_[0].state, yyla)]])[);
       }
 
 ]b4_locations_if([[
@@ -887,10 +890,10 @@ b4_dollar_popdef])[]dnl
         // Return failure if at end of input.
         if (yyla.type_get () == yyeof_)
           YYABORT;
-        else if (!yyempty)
+        else if (!yyla.empty ())
           {
             yy_destroy_ ("Error: discarding", yyla);
-            yyempty = true;
+            yyla.clear ();
           }
       }
 
@@ -966,7 +969,7 @@ b4_dollar_popdef])[]dnl
     goto yyreturn;
 
   yyreturn:
-    if (!yyempty)
+    if (!yyla.empty ())
       yy_destroy_ ("Cleanup: discarding lookahead", yyla);
 
     /* Do not reclaim the symbols of the rule whose action triggered
@@ -986,7 +989,7 @@ b4_dollar_popdef])[]dnl
                  << std::endl;
         // Do not try to display the values of the reclaimed symbols,
         // as their printer might throw an exception.
-        if (!yyempty)
+        if (!yyla.empty ())
           yy_destroy_ (YY_NULLPTR, yyla);
 
         while (1 < yystack_.size ())
@@ -1008,10 +1011,9 @@ b4_dollar_popdef])[]dnl
   // Generate an error message.
   std::string
   ]b4_parser_class_name[::yysyntax_error_ (]dnl
-b4_error_verbose_if([state_type yystate, symbol_number_type yytoken],
-                    [state_type, symbol_number_type])[) const
+b4_error_verbose_if([state_type yystate, const symbol_type& yyla],
+                    [state_type, const symbol_type&])[) const
   {]b4_error_verbose_if([[
-    std::string yyres;
     // Number of reported tokens (one for the "unexpected", one per
     // "expected").
     size_t yycount = 0;
@@ -1025,7 +1027,7 @@ b4_error_verbose_if([state_type yystate, 
symbol_number_type yytoken],
          the only way this function was invoked is if the default action
          is an error action.  In that case, don't check for expected
          tokens because there are none.
-       - The only way there can be no lookahead present (in yytoken) is
+       - The only way there can be no lookahead present (in yyla) is
          if this state is a consistent state with a default action.
          Thus, detecting the absence of a lookahead is sufficient to
          determine that there is no unexpected or expected token to
@@ -1045,8 +1047,9 @@ b4_error_verbose_if([state_type yystate, 
symbol_number_type yytoken],
          token that will not be accepted due to an error action in a
          later state.
     */
-    if (yytoken != yyempty_)
+    if (!yyla.empty ())
       {
+        int yytoken = yyla.type_get ();
         yyarg[yycount++] = yytname_[yytoken];
         int yyn = yypact_[yystate];
         if (!yy_pact_value_is_default_ (yyn))
@@ -1089,6 +1092,7 @@ b4_error_verbose_if([state_type yystate, 
symbol_number_type yytoken],
 #undef YYCASE_
       }
 
+    std::string yyres;
     // Argument number.
     size_t yyi = 0;
     for (char const* yyp = yyformat; *yyp; ++yyp)
diff --git a/data/location.cc b/data/location.cc
index 8e8a2c2..53fddd4 100644
--- a/data/location.cc
+++ b/data/location.cc
@@ -83,7 +83,7 @@ m4_define([b4_position_define],
     }
   };
 
-  /// Add and assign a position.
+  /// Add \a width columns, in place.
   inline position&
   operator+= (position& res, int width)
   {
@@ -91,21 +91,21 @@ m4_define([b4_position_define],
     return res;
   }
 
-  /// Add two position objects.
+  /// Add \a width columns.
   inline position
   operator+ (position res, int width)
   {
     return res += width;
   }
 
-  /// Add and assign a position.
+  /// Subtract \a width columns, in place.
   inline position&
   operator-= (position& res, int width)
   {
     return res += -width;
   }
 
-  /// Add two position objects.
+  /// Subtract \a width columns.
   inline position
   operator- (position res, int width)
   {
@@ -216,36 +216,42 @@ m4_define([b4_location_define],
     position end;
   };
 
-  /// Join two location objects to create a location.
-  inline location operator+ (location res, const location& end)
+  /// Join two locations, in place.
+  inline location& operator+= (location& res, const location& end)
   {
     res.end = end.end;
     return res;
   }
 
-  /// Change end position in place.
+  /// Join two locations.
+  inline location operator+ (location res, const location& end)
+  {
+    return res += end;
+  }
+
+  /// Add \a width columns to the end position, in place.
   inline location& operator+= (location& res, int width)
   {
     res.columns (width);
     return res;
   }
 
-  /// Change end position.
+  /// Add \a width columns to the end position.
   inline location operator+ (location res, int width)
   {
     return res += width;
   }
 
-  /// Change end position in place.
+  /// Subtract \a width columns to the end position, in place.
   inline location& operator-= (location& res, int width)
   {
     return res += -width;
   }
 
-  /// Change end position.
-  inline location operator- (const location& begin, int width)
+  /// Subtract \a width columns to the end position.
+  inline location operator- (location res, int width)
   {
-    return begin + -width;
+    return res -= width;
   }
 ]b4_percent_define_flag_if([[define_location_comparison]], [[
   /// Compare two location objects.
diff --git a/data/variant.hh b/data/variant.hh
index 78c2f94..f918e34 100644
--- a/data/variant.hh
+++ b/data/variant.hh
@@ -95,13 +95,13 @@ m4_define([b4_variant_define],
 
     /// Empty construction.
     variant ()]b4_parse_assert_if([
-      : yytname_ (YY_NULLPTR)])[
+      : yytypeid_ (YY_NULLPTR)])[
     {}
 
     /// Construct and fill.
     template <typename T>
     variant (const T& t)]b4_parse_assert_if([
-      : yytname_ (typeid (T).name ())])[
+      : yytypeid_ (&typeid (T))])[
     {
       YYASSERT (sizeof (T) <= S);
       new (yyas_<T> ()) T (t);
@@ -110,7 +110,7 @@ m4_define([b4_variant_define],
     /// Destruction, allowed only if empty.
     ~variant ()
     {]b4_parse_assert_if([
-      YYASSERT (!yytname_);
+      YYASSERT (!yytypeid_);
     ])[}
 
     /// Instantiate an empty \a T in here.
@@ -118,9 +118,9 @@ m4_define([b4_variant_define],
     T&
     build ()
     {]b4_parse_assert_if([
-      YYASSERT (!yytname_);
+      YYASSERT (!yytypeid_);
       YYASSERT (sizeof (T) <= S);
-      yytname_ = typeid (T).name ();])[
+      yytypeid_ = & typeid (T);])[
       return *new (yyas_<T> ()) T;
     }
 
@@ -129,9 +129,9 @@ m4_define([b4_variant_define],
     T&
     build (const T& t)
     {]b4_parse_assert_if([
-      YYASSERT (!yytname_);
+      YYASSERT (!yytypeid_);
       YYASSERT (sizeof (T) <= S);
-      yytname_ = typeid (T).name ();])[
+      yytypeid_ = & typeid (T);])[
       return *new (yyas_<T> ()) T (t);
     }
 
@@ -140,7 +140,7 @@ m4_define([b4_variant_define],
     T&
     as ()
     {]b4_parse_assert_if([
-      YYASSERT (yytname_ == typeid (T).name ());
+      YYASSERT (*yytypeid_ == typeid (T));
       YYASSERT (sizeof (T) <= S);])[
       return *yyas_<T> ();
     }
@@ -150,7 +150,7 @@ m4_define([b4_variant_define],
     const T&
     as () const
     {]b4_parse_assert_if([
-      YYASSERT (yytname_ == typeid (T).name ());
+      YYASSERT (*yytypeid_ == typeid (T));
       YYASSERT (sizeof (T) <= S);])[
       return *yyas_<T> ();
     }
@@ -167,8 +167,8 @@ m4_define([b4_variant_define],
     void
     swap (self_type& other)
     {]b4_parse_assert_if([
-      YYASSERT (yytname_);
-      YYASSERT (yytname_ == other.yytname_);])[
+      YYASSERT (yytypeid_);
+      YYASSERT (*yytypeid_ == *other.yytypeid_);])[
       std::swap (as<T> (), other.as<T> ());
     }
 
@@ -198,7 +198,7 @@ m4_define([b4_variant_define],
     destroy ()
     {
       as<T> ().~T ();]b4_parse_assert_if([
-      yytname_ = YY_NULLPTR;])[
+      yytypeid_ = YY_NULLPTR;])[
     }
 
   private:
@@ -233,7 +233,7 @@ m4_define([b4_variant_define],
     } yybuffer_;]b4_parse_assert_if([
 
     /// Whether the content is built: if defined, the name of the stored type.
-    const char *yytname_;])[
+    const std::type_info *yytypeid_;])[
   };
 ]])
 
diff --git a/doc/bison.texi b/doc/bison.texi
index 11bd2d8..1a2b169 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -10382,9 +10382,23 @@ declare @code{yyerror} as follows:
 int yyerror (char const *);
 @end example
 
-Bison ignores the @code{int} value returned by this @code{yyerror}.
-If you use the Yacc library's @code{main} function, your
address@hidden function should have the following type signature:
address@hidden
+The @code{int} value returned by this @code{yyerror} is ignored.
+
+The implementation of Yacc library's @code{main} function is:
+
address@hidden
+int main (void)
address@hidden
+  setlocale (LC_ALL, "");
+  return yyparse ();
address@hidden
address@hidden example
+
address@hidden
+so if you use it, the internationalization support is enabled (e.g., error
+messages are translated), and your @code{yyparse} function should have the
+following type signature:
 
 @example
 int yyparse (void);
@@ -10686,12 +10700,17 @@ The first, inclusive, position of the range, and the 
first beyond.
 Forwarded to the @code{end} position.
 @end deftypemethod
 
address@hidden {location} {location} operator+ (const location& @var{end})
address@hidden {location} {location} operator+ (int @var{width})
address@hidden  {location} {location} operator+  (int @var{width})
 @deftypemethodx {location} {location} operator+= (int @var{width})
address@hidden {location} {location} operator- (int @var{width})
address@hidden {location} {location} operator-  (int @var{width})
 @deftypemethodx {location} {location} operator-= (int @var{width})
-Various forms of syntactic sugar.
+Various forms of syntactic sugar for @code{columns}.
address@hidden deftypemethod
+
address@hidden {location} {location} operator+ (const location& @var{end})
address@hidden {location} {location} operator+= (const location& @var{end})
+Join two locations: starts at the position of the first one, and ends at the
+position of the second.
 @end deftypemethod
 
 @deftypemethod {location} {void} step ()
diff --git a/doc/local.mk b/doc/local.mk
index e92ea71..c340452 100644
--- a/doc/local.mk
+++ b/doc/local.mk
@@ -132,7 +132,7 @@ endif
 ## Graphviz examples generation. ##
 ## ----------------------------- ##
 
-CLEANDIRS += doc/figs
+CLEANFILES += $(FIGS_GV:.gv=.eps) $(FIGS_GV:.gv=.pdf) $(FIGS_GV:.gv=.png)
 FIGS_GV =                                               \
   doc/figs/example.gv                                   \
   doc/figs/example-reduce.gv doc/figs/example-shift.gv
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ee34879..8086f55 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -15,7 +15,6 @@ src/reduce.c
 src/scan-code.l
 src/scan-gram.l
 src/scan-skel.l
-src/symlist.c
 src/symtab.c
 
 djgpp/subpipe.c
diff --git a/src/scan-code.l b/src/scan-code.l
index f90916c..308d1d0 100644
--- a/src/scan-code.l
+++ b/src/scan-code.l
@@ -711,7 +711,7 @@ handle_action_dollar (symbol_list *rule, char *text, 
location dollar_loc)
                       "]b4_rhs_value(%d, %d, ", effective_rule_length, n);
       obstack_quote (&obstack_for_string, type_name);
       obstack_sgrow (&obstack_for_string, ")[");
-      if (n > 0)
+      if (0 < n)
         symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
           true;
       break;
diff --git a/src/symlist.c b/src/symlist.c
index 38f5fc8..d70763b 100644
--- a/src/symlist.c
+++ b/src/symlist.c
@@ -21,7 +21,6 @@
 #include <config.h>
 #include "system.h"
 
-#include "complain.h"
 #include "symlist.h"
 
 /*--------------------------------------.
@@ -174,22 +173,17 @@ symbol_list *
 symbol_list_n_get (symbol_list *l, int n)
 {
   int i;
-
-  if (n < 0)
-    return NULL;
-
+  aver (0 <= n);
   for (i = 0; i < n; ++i)
     {
       l = l->next;
-      if (l == NULL
-          || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL))
-        return NULL;
+      aver (l);
     }
-
+  aver (l->content_type == SYMLIST_SYMBOL);
+  aver (l->content.sym);
   return l;
 }
 
-
 /*--------------------------------------------------------------.
 | Get the data type (alternative in the union) of the value for |
 | symbol N in symbol list L.                                    |
@@ -198,21 +192,14 @@ symbol_list_n_get (symbol_list *l, int n)
 uniqstr
 symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
 {
-  l = symbol_list_n_get (l, n);
-  if (!l)
-    {
-      complain (&loc, complaint, _("invalid $ value: $%d"), n);
-      return NULL;
-    }
-  aver (l->content_type == SYMLIST_SYMBOL);
-  return l->content.sym->content->type_name;
+  return symbol_list_n_get (l, n)->content.sym->content->type_name;
 }
 
 bool
 symbol_list_null (symbol_list *node)
 {
-  return !node ||
-    (node->content_type == SYMLIST_SYMBOL && !(node->content.sym));
+  return (!node
+          || (node->content_type == SYMLIST_SYMBOL && !node->content.sym));
 }
 
 void
diff --git a/src/symlist.h b/src/symlist.h
index 639b593..aeb4622 100644
--- a/src/symlist.h
+++ b/src/symlist.h
@@ -116,7 +116,10 @@ void symbol_list_free (symbol_list *list);
 /** Return the length of \c l. */
 int symbol_list_length (symbol_list const *l);
 
-/** Get item \c n in symbol list \c l.  */
+/** Get item \c n in symbol list \c l.
+ ** \pre  0 <= n
+ ** \post res != NULL
+ **/
 symbol_list *symbol_list_n_get (symbol_list *l, int n);
 
 /* Get the data type (alternative in the union) of the value for
diff --git a/tests/c++.at b/tests/c++.at
index f1586f5..737037d 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -60,8 +60,10 @@ main (void)
 {
   int fail = 0;
   ]AT_YYLTYPE[ loc;  fail += check (loc, "1.1");
+                     fail += check (loc + 10, "1.1-10");
   loc += 10;         fail += check (loc, "1.1-10");
   loc += -5;         fail += check (loc, "1.1-5");
+                     fail += check (loc - 5, "1.1");
   loc -= 5;          fail += check (loc, "1.1");
   // Check that we don't go below.
   // http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html
@@ -70,6 +72,11 @@ main (void)
   loc.columns (10); loc.lines (10); fail += check (loc, "1.1-11.0");
   loc.lines (-2);                   fail += check (loc, "1.1-9.0");
   loc.lines (-10);                  fail += check (loc, "1.1");
+
+  ]AT_YYLTYPE[ loc2 (YY_NULLPTR, 5, 10);
+                   fail += check (loc2, "5.10");
+                   fail += check (loc + loc2, "1.1-5.9");
+  loc += loc2;     fail += check (loc, "1.1-5.9");
   return !fail;
 }
 ]])
@@ -168,6 +175,9 @@ AT_CLEANUP
 ## Variants.  ##
 ## ---------- ##
 
+# Check that the variants are properly supported, including in error
+# recovery.
+
 # AT_TEST([DIRECTIVES])
 # ---------------------
 # Check the support of variants in C++, with the additional DIRECTIVES.
@@ -225,7 +235,7 @@ typedef std::list<std::string> strings_type;
   template <typename T>
     inline
     std::string
-    string_cast (const T& t)
+    to_string (const T& t)
   {
     std::ostringstream o;
     o << t;
@@ -236,15 +246,18 @@ typedef std::list<std::string> strings_type;
 %token <::std::string> TEXT;
 %token <int> NUMBER;
 %token END_OF_FILE 0;
+%token COMMA ","
 
 %type <::std::string> item;
 // Using the template type to exercize its parsing.
 // Starting with :: to ensure we don't output "<::" which starts by the
 // digraph for the left square bracket.
-%type <::std::list<std::string>> list result;
+%type <::std::list<std::string>> list;
 
 %printer { yyo << $$; }
   <int> <::std::string> <::std::list<std::string>>;
+%destructor { std::cerr << "Destroy: " << $$ << '\n'; } <*>;
+%destructor { std::cerr << "Destroy: \"" << $$ << "\"\n"; } <::std::string>;
 %%
 
 result:
@@ -252,14 +265,14 @@ result:
 ;
 
 list:
-  /* nothing */ { /* Generates an empty string list */ }
-| list item     { std::swap ($$,$][1); $$.push_back ($][2); }
-| list error    { std::swap ($$,$][1); }
+  item          { $$.push_back ($][1); }
+| list "," item { std::swap ($$, $][1); $$.push_back ($][3); }
+| list error    { std::swap ($$, $][1); }
 ;
 
 item:
-  TEXT          { std::swap ($$,$][1); }
-| NUMBER        { if ($][1 == 3) YYERROR; else $$ = string_cast ($][1); }
+  TEXT          { std::swap ($$, $][1); }
+| NUMBER        { if ($][1 == 3) YYERROR; else $$ = to_string ($][1); }
 ;
 %%
 ]AT_TOKEN_CTOR_IF([],
@@ -278,30 +291,43 @@ namespace yy
                             parser::location_type* yylloc])[)]])[
   {]AT_LOCATION_IF([
     typedef parser::location_type location;])[
-    static int stage = -1;
-    ++stage;
-    if (stage == STAGE_MAX)
-      {]AT_TOKEN_CTOR_IF([[
+    // The 5 is a syntax error whose recovery requires that we discard
+    // the lookahead.  This tests a regression, see
+    // <http://savannah.gnu.org/support/?108481>.
+    static char const *input = "0,1,2,3,45,6";
+    switch (int stage = *input++)
+    {
+      case 0:]AT_TOKEN_CTOR_IF([[
         return parser::make_END_OF_FILE (]AT_LOCATION_IF([location ()])[);]],
 [AT_LOCATION_IF([
         *yylloc = location ();])[
         return parser::token::END_OF_FILE;]])[
-      }
-    else if (stage % 2)
-      {]AT_TOKEN_CTOR_IF([[
-        return parser::make_NUMBER (stage]AT_LOCATION_IF([, location ()])[);]],
-[[
-        yylval->BUILD (int, stage);]AT_LOCATION_IF([
-        *yylloc = location ();])[
-        return parser::token::NUMBER;]])[
-      }
-    else
-      {]AT_TOKEN_CTOR_IF([[
-        return parser::make_TEXT (string_cast (stage)]AT_LOCATION_IF([, 
location ()])[);]], [[
-        yylval->BUILD (std::string, string_cast (stage));]AT_LOCATION_IF([
+
+      case ',':
+        ]AT_TOKEN_CTOR_IF([[
+        return parser::make_COMMA (]AT_LOCATION_IF([location ()])[);]], [[
+]AT_LOCATION_IF([
         *yylloc = location ();])[
-        return parser::token::TEXT;]])[
-      }
+        return parser::token::COMMA;]])[
+
+      default:
+        stage = stage - '0';
+        if (stage % 2)
+         {]AT_TOKEN_CTOR_IF([[
+           return parser::make_NUMBER (stage]AT_LOCATION_IF([, location 
()])[);]], [[
+           yylval->BUILD (int, stage);]AT_LOCATION_IF([
+           *yylloc = location ();])[
+           return parser::token::NUMBER;]])[
+         }
+       else
+         {]AT_TOKEN_CTOR_IF([[
+           return parser::make_TEXT (to_string (stage)]AT_LOCATION_IF([, 
location ()])[);]], [[
+           yylval->BUILD (std::string, to_string (stage));]AT_LOCATION_IF([
+           *yylloc = location ();])[
+           return parser::token::TEXT;]])[
+         }
+    }
+
     abort ();
   }
 }
@@ -312,8 +338,31 @@ namespace yy
 
 AT_FULL_COMPILE([list])
 AT_PARSER_CHECK([./list], 0,
-[(0, 1, 2, 4)
-])
+[[(0, 1, 2, 4, 6)
+]],
+[[Destroy: ""
+Destroy: "0"
+Destroy: (0)
+Destroy: 1
+Destroy: "1"
+Destroy: ()
+Destroy: ""
+Destroy: "2"
+Destroy: ()
+Destroy: ""
+Destroy: 3
+Destroy: ()
+Destroy: ""
+Destroy: "4"
+Destroy: ()
+Destroy: ()
+Destroy: 5
+Destroy: ()
+Destroy: ""
+Destroy: "6"
+Destroy: ()
+Destroy: (0, 1, 2, 4, 6)
+]])
 
 AT_BISON_OPTION_POPDEFS
 AT_CLEANUP
@@ -321,11 +370,11 @@ AT_CLEANUP
 
 AT_TEST([[%skeleton "lalr1.cc" ]])
 AT_TEST([[%skeleton "lalr1.cc" %define parse.assert]])
-AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert]])
+AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %locations]])
 AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %code {\n#define 
TWO_STAGE_BUILD\n}]])
 AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define 
api.token.constructor]])
 AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define 
api.token.constructor %define api.token.prefix {TOK_}]])
-AT_TEST([[%skeleton "lalr1.cc" %locations %define parse.assert %define 
api.token.constructor %define api.token.prefix {TOK_}]])
+AT_TEST([[%skeleton "lalr1.cc" %define parse.assert %define 
api.token.constructor %define api.token.prefix {TOK_} %locations]])
 
 m4_popdef([AT_TEST])
 
@@ -345,6 +394,7 @@ AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
 AT_DATA([input.yy],
 [[%skeleton "lalr1.cc"
 %locations
+%defines
 %debug
 %%
 exp: /* empty */;
@@ -352,7 +402,7 @@ exp: /* empty */;
 ]AT_YYERROR_DEFINE[
 ]])
 
-AT_BISON_CHECK([-o input.cc input.yy], 0)
+AT_BISON_CHECK([-o input.cc input.yy])
 
 AT_DATA([Doxyfile],
 [# The PROJECT_NAME tag is a single word (or a sequence of words
@@ -423,7 +473,7 @@ AT_CHECK_DOXYGEN([Private])
 # so don't check compilation.
 m4_pushdef([AT_TEST],
 [AT_BISON_OPTION_PUSHDEFS([%language "C++" %define api.namespace {$1}])
-AT_DATA_GRAMMAR([[input.y]],
+AT_DATA_GRAMMAR([[input.yy]],
 [[%language "C++"
 %define api.namespace {]$1[}
 %union { int i; }
@@ -455,10 +505,10 @@ void
 ]])
 
 
-AT_BISON_CHECK([[-o input.cc input.y]])
+AT_BISON_CHECK([[-o input.cc input.yy]])
 
 m4_if([$#], [1],
-[AT_COMPILE_CXX([[input]], [[input.cc]])
+[AT_COMPILE_CXX([[input]])
 AT_PARSER_CHECK([[./input]])])
 AT_BISON_OPTION_POPDEFS
 ])
@@ -502,7 +552,7 @@ AT_SETUP([[Syntax error discarding no lookahead]])
 
 AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
 
-AT_DATA_GRAMMAR([[input.yy]],
+AT_DATA_GRAMMAR([[input.y]],
 [[%skeleton "lalr1.cc"
 
 %code {
@@ -555,8 +605,7 @@ yy::parser::error (const std::string &m)
 ]AT_MAIN_DEFINE[
 ]])
 
-AT_BISON_CHECK([[-o input.cc input.yy]])
-AT_COMPILE_CXX([[input]])
+AT_FULL_COMPILE([[input]])
 # This used to print "Discarding 'a'." again at the end.
 AT_PARSER_CHECK([[./input]], [[1]], [[]],
 [[syntax error
@@ -576,7 +625,7 @@ AT_SETUP([[Syntax error as exception]])
 
 AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
 
-AT_DATA_GRAMMAR([[input.yy]],
+AT_DATA_GRAMMAR([[input.y]],
 [[%skeleton "lalr1.cc"
 
 %code
@@ -631,8 +680,7 @@ yy::parser::error (const std::string &m)
 ]AT_MAIN_DEFINE[
 ]])
 
-AT_BISON_CHECK([[-o input.cc input.yy]])
-AT_COMPILE_CXX([[input]])
+AT_FULL_COMPILE([[input]])
 
 AT_PARSER_CHECK([[./input]], [[0]], [[]],
 [[error: invalid expression
@@ -803,10 +851,10 @@ list:
 
 item:
   'a'     { $$ = $][1; }
-| 'e'     { YYUSE ($$); YYUSE($][1); error ("syntax error"); }
+| 'e'     { YYUSE ($$); YYUSE ($][1); error ("syntax error"); }
 // Not just 'E', otherwise we reduce when 'E' is the lookahead, and
 // then the stack is emptied, defeating the point of the test.
-| 'E' 'a' { YYUSE($][1); $$ = $][2; }
+| 'E' 'a' { YYUSE ($][1); $$ = $][2; }
 | 'R'     { ]AT_VARIANT_IF([], [$$ = YY_NULLPTR; delete $][1]; )[YYERROR; }
 | 'p'     { $$ = $][1; }
 | 's'     { $$ = $][1; throw std::runtime_error ("reduction"); }
@@ -929,9 +977,9 @@ AT_TEST([%define api.value.type variant], [without])
 
 m4_popdef([AT_TEST])
 
-## ------------------------------------ ##
-## C++ GLR parser identifier shadowing  ##
-## ------------------------------------ ##
+## ------------------------------------- ##
+## C++ GLR parser identifier shadowing.  ##
+## ------------------------------------- ##
 
 AT_SETUP([[C++ GLR parser identifier shadowing]])
 
@@ -967,7 +1015,7 @@ int yylex (yy::parser::semantic_type *yylval)
 void yy::parser::error (std::string const&)
 {}
 
-int main()
+int main ()
 {}
 ])
 
diff --git a/tests/conflicts.at b/tests/conflicts.at
index 819b992..03b8fa2 100644
--- a/tests/conflicts.at
+++ b/tests/conflicts.at
@@ -393,10 +393,10 @@ AT_CLEANUP
 ## parse.error=verbose and consistent errors.  ##
 ## ------------------------------------------- ##
 
-AT_SETUP([[parse.error=verbose and consistent errors]])
-
 m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [
 
+AT_SETUP([[parse.error=verbose and consistent errors: $1]])
+
 AT_BISON_OPTION_PUSHDEFS([$1])
 
 m4_pushdef([AT_YYLEX_PROTOTYPE],
@@ -483,7 +483,11 @@ m4_popdef([AT_EXPECTING])
 m4_popdef([AT_YYLEX_PROTOTYPE])
 AT_BISON_OPTION_POPDEFS
 
-])
+AT_CLEANUP
+]) dnl AT_CONSISTENT_ERRORS_CHECK
+
+
+
 
 m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR],
 [[%nonassoc 'a';
@@ -653,7 +657,6 @@ m4_popdef([AT_USER_ACTION_INPUT])
 
 m4_popdef([AT_CONSISTENT_ERRORS_CHECK])
 
-AT_CLEANUP
 
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]