From: Akim Demaille Date: Thu, 11 Apr 2013 07:53:18 +0000 (+0200) Subject: c++: fix several issues with locations X-Git-Tag: v2.7.90~34 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/75ae8299840bbd854fa2474d38402bbb933c6511 c++: fix several issues with locations Reported by Daniel Frużyński. http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html * data/location.cc (position::columns, position::lines): Check for underflow. Fix some weird function signatures. (location): Accept signed integers as arguments where appropriate. Add operator- and operator+=. * doc/bison.texi (C++ position, C++ location): Various fixes and completion. * tests/c++.at (C++ Locations): New tests. --- diff --git a/NEWS b/NEWS index d7d89d2a..cf118c15 100644 --- a/NEWS +++ b/NEWS @@ -569,6 +569,11 @@ GNU Bison NEWS ... } +*** C++ locations + + There are operator- and operator-= for 'location'. Negative line/column + increments can no longer underflow the resulting value. + * Noteworthy changes in release ?.? (????-??-??) [?] ** Bug fixes diff --git a/THANKS b/THANKS index a7d1d47e..320e26f1 100644 --- a/THANKS +++ b/THANKS @@ -29,6 +29,7 @@ Cris Bailiff c.bailiff+bison@awayweb.com Cris van Pelt cris@amf03054.office.wxs.nl Csaba Raduly csaba_22@yahoo.co.uk Dagobert Michelsen dam@baltic-online.de +Daniel Frużyński daniel@poradnik-webmastera.com Daniel Hagerty hag@gnu.org David J. MacKenzie djm@gnu.org David Kastrup dak@gnu.org diff --git a/data/location.cc b/data/location.cc index 987843b2..309b9c0f 100644 --- a/data/location.cc +++ b/data/location.cc @@ -25,8 +25,7 @@ m4_define([b4_position_define], [[ /// Abstract a position. class position { - public: -]m4_ifdef([b4_location_constructors], [[ + public:]m4_ifdef([b4_location_constructors], [[ /// Construct a position. explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL, unsigned int l = ]b4_location_initial_line[u, @@ -53,14 +52,23 @@ m4_define([b4_position_define], /// (line related) Advance to the COUNT next lines. void lines (int count = 1) { - column = ]b4_location_initial_column[u; - line += count; + if (count) + { + column = ]b4_location_initial_column[u; + line = + 0 < count || -count < line + ? line + count + : ]b4_location_initial_line[; + } } /// (column related) Advance to the COUNT next columns. void columns (int count = 1) { - column = std::max (]b4_location_initial_column[u, column + count); + column = + 0 < count || -count < column + ? column + count + : ]b4_location_initial_column[; } /** \} */ @@ -74,32 +82,31 @@ m4_define([b4_position_define], /// Add and assign a position. inline position& - operator+= (position& res, const int width) + operator+= (position& res, int width) { res.columns (width); return res; } /// Add two position objects. - inline const position - operator+ (const position& begin, const int width) + inline position + operator+ (position res, int width) { - position res = begin; return res += width; } /// Add and assign a position. inline position& - operator-= (position& res, const int width) + operator-= (position& res, int width) { return res += -width; } /// Add two position objects. - inline const position - operator- (const position& begin, const int width) + inline position + operator- (position res, int width) { - return begin + -width; + return res -= width; } ]b4_percent_define_flag_if([[define_location_comparison]], [[ /// Compare two position objects. @@ -186,13 +193,13 @@ m4_define([b4_location_define], } /// Extend the current location to the COUNT next columns. - void columns (unsigned int count = 1) + void columns (int count = 1) { end += count; } /// Extend the current location to the COUNT next lines. - void lines (unsigned int count = 1) + void lines (int count = 1) { end.lines (count); } @@ -207,26 +214,35 @@ m4_define([b4_location_define], }; /// Join two location objects to create a location. - inline const location operator+ (const location& begin, const location& end) + inline location operator+ (location res, const location& end) { - location res = begin; res.end = end.end; return res; } - /// Add two location objects. - inline const location operator+ (const location& begin, unsigned int width) + /// Change end position in place. + inline location& operator+= (location& res, int width) { - location res = begin; res.columns (width); return res; } - /// Add and assign a location. - inline location& operator+= (location& res, unsigned int width) + /// Change end position. + inline location operator+ (location res, int width) { - res.columns (width); - return res; + return res += width; + } + + /// Change 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) + { + return begin + -width; } ]b4_percent_define_flag_if([[define_location_comparison]], [[ /// Compare two location objects. diff --git a/doc/bison.texi b/doc/bison.texi index 250e94d8..72847a1e 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -10591,16 +10591,18 @@ filename_type "@var{type}"}. The line, starting at 1. @end deftypeivar -@deftypemethod {position} {uint} lines (int @var{height} = 1) -Advance by @var{height} lines, resetting the column number. +@deftypemethod {position} {void} lines (int @var{height} = 1) +If @var{height} is not null, advance by @var{height} lines, resetting the +column number. The resulting line number cannot be less than 1. @end deftypemethod @deftypeivar {position} {uint} column The column, starting at 1. @end deftypeivar -@deftypemethod {position} {uint} columns (int @var{width} = 1) -Advance by @var{width} columns, without changing the line number. +@deftypemethod {position} {void} columns (int @var{width} = 1) +Advance by @var{width} columns, without changing the line number. The +resulting column number cannot be less than 1. @end deftypemethod @deftypemethod {position} {position&} operator+= (int @var{width}) @@ -10642,14 +10644,16 @@ Reset the location to an empty range at the given values. The first, inclusive, position of the range, and the first beyond. @end deftypeivar -@deftypemethod {location} {uint} columns (int @var{width} = 1) -@deftypemethodx {location} {uint} lines (int @var{height} = 1) -Advance the @code{end} position. +@deftypemethod {location} {void} columns (int @var{width} = 1) +@deftypemethodx {location} {void} lines (int @var{height} = 1) +Forwarded to the @code{end} position. @end deftypemethod @deftypemethod {location} {location} operator+ (const location& @var{end}) @deftypemethodx {location} {location} operator+ (int @var{width}) @deftypemethodx {location} {location} operator+= (int @var{width}) +@deftypemethodx {location} {location} operator- (int @var{width}) +@deftypemethodx {location} {location} operator-= (int @var{width}) Various forms of syntactic sugar. @end deftypemethod diff --git a/tests/c++.at b/tests/c++.at index 3300352d..387d4878 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -18,6 +18,68 @@ AT_BANNER([[C++ Features.]]) +## --------------- ## +## C++ Locations. ## +## --------------- ## + +AT_SETUP([C++ Locations]) + +AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "lalr1.cc"]) +AT_DATA_GRAMMAR([[input.y]], +[[%code {#include } +%locations +%debug +%skeleton "lalr1.cc" +%code +{ +]AT_YYERROR_DECLARE[ +]AT_YYLEX_DECLARE[ +} +%% +exp: %empty; +%% +]AT_YYERROR_DEFINE[ +]AT_YYLEX_DEFINE[ + +template +bool +check (const T& in, const std::string& s) +{ + std::stringstream os; + os << in; + if (os.str () != s) + { + std::cerr << "fail: " << os.str () << ", expected: " << s << std::endl; + return false; + } + return true; +} + +int +main (void) +{ + int fail = 0; + ]AT_YYLTYPE[ loc; fail += check (loc, "1.1"); + loc += 10; fail += check (loc, "1.1-10"); + loc += -5; fail += check (loc, "1.1-5"); + 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 + loc -= 10; fail += check (loc, "1.1"); + + 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"); + return !fail; +} +]]) + +AT_FULL_COMPILE([input]) +AT_PARSER_CHECK([./input], 0) +AT_BISON_OPTION_POPDEFS +AT_CLEANUP + + ## --------------------------- ## ## C++ Variant-based Symbols. ## ## --------------------------- ##