From 4e510c69b1cbf711a0d9cba2967a79d6673b4e35 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Tue, 20 Nov 2018 19:28:12 +0100 Subject: [PATCH] c++: using macros around user types breaks when they include comma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We may generate code such as basic_symbol (typename Base::kind_type t, YY_RVREF (std::pair) v); which, of course, breaks, because YY_RVREF sees two arguments. Let's not play tricks with _VA_ARGS__, I'm unsure about it portability. Anyway, I plan to change more things in this area. Reported by Sébastien Villemot. http://lists.gnu.org/archive/html/bug-bison/2018-11/msg00014.html * data/variant.hh (b4_basic_symbol_constructor_declare) (b4_basic_symbol_constructor_define): Don't use macro on user types. * tests/types.at: Check that we support pairs. --- THANKS | 1 + data/variant.hh | 36 +++++++++++++++++++++++++++--------- tests/types.at | 18 ++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/THANKS b/THANKS index e564cf22..3d61e148 100644 --- a/THANKS +++ b/THANKS @@ -151,6 +151,7 @@ Roland Levillain roland@lrde.epita.fr Satya Kiran Popuri satyakiran@gmail.com Sebastian Setzer sebastian.setzer.ext@siemens.com Sebastien Fricker sebastien.fricker@gmail.com +Sébastien Villemot sebastien@debian.org Sergei Steshenko sergstesh@yahoo.com Shura debil_urod@ngs.ru Simon Sobisch simonsobisch@web.de diff --git a/data/variant.hh b/data/variant.hh index 805ddce0..2e0ac139 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -379,26 +379,44 @@ b4_join(b4_symbol_if([$1], [has_type], # ----------------------------------- # Generate a constructor declaration for basic_symbol from given type. m4_define([b4_basic_symbol_constructor_declare], -[[ basic_symbol (]b4_join( +[[# if 201103L <= YY_CPLUSPLUS + basic_symbol (]b4_join( [typename Base::kind_type t], - b4_symbol_if([$1], [has_type], [YY_RVREF (b4_symbol([$1], [type])) v]), - b4_locations_if([YY_RVREF (location_type) l]))[); + b4_symbol_if([$1], [has_type], [b4_symbol([$1], [type])&& v]), + b4_locations_if([location_type&& l]))[); +#else + basic_symbol (]b4_join( + [typename Base::kind_type t], + b4_symbol_if([$1], [has_type], [const b4_symbol([$1], [type])& v]), + b4_locations_if([const location_type& l]))[); +#endif ]]) # b4_basic_symbol_constructor_define # ---------------------------------- # Generate a constructor implementation for basic_symbol from given type. m4_define([b4_basic_symbol_constructor_define], -[[ template +[[# if 201103L <= YY_CPLUSPLUS + template ]b4_parser_class_name[::basic_symbol::basic_symbol (]b4_join( [typename Base::kind_type t], - b4_symbol_if([$1], [has_type], [YY_RVREF (b4_symbol([$1], [type])) v]), - b4_locations_if([YY_RVREF (location_type) l]))[) + b4_symbol_if([$1], [has_type], [b4_symbol([$1], [type])&& v]), + b4_locations_if([location_type&& l]))[) : Base (t)]b4_symbol_if([$1], [has_type], [ - , value (YY_MOVE (v))])[]b4_locations_if([ - , location (YY_MOVE (l))])[ + , value (std::move (v))])[]b4_locations_if([ + , location (std::move (l))])[ {} - +#else + template + ]b4_parser_class_name[::basic_symbol::basic_symbol (]b4_join( + [typename Base::kind_type t], + b4_symbol_if([$1], [has_type], [const b4_symbol([$1], [type])& v]), + b4_locations_if([const location_type& l]))[) + : Base (t)]b4_symbol_if([$1], [has_type], [ + , value (v)])[]b4_locations_if([ + , location (l)])[ + {} +#endif ]]) # b4_symbol_constructor_define diff --git a/tests/types.at b/tests/types.at index 84d3e222..a2758917 100644 --- a/tests/types.at +++ b/tests/types.at @@ -270,6 +270,24 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], AT_VAL.build ("two");], [10, two]) + # Test a regression where we passed user types (we can include + # commas) to a CPP macro. + AT_TEST([%skeleton "]b4_skel[" + %define api.value.type variant], + [%token > '1'; + %token > '2';], + ['1' '2' + { + std::cout << $1.first << ':' << $1.second << ", " + << $2.first << ':' << $2.second << '\n'; + }], + ["12"], + [if (res == '1') + AT_VAL.build (std::make_pair (10, 11)); + else if (res == '2') + AT_VAL.build (std::make_pair ("two", "deux"));], + [10:11, two:deux]) + # Move-only types. AT_TEST([%skeleton "]b4_skel[" %code requires { #include }