From d84b245c638e173f95286826cb6c3cd9598c43c5 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Sat, 8 Jun 2019 22:05:03 +0200 Subject: [PATCH] tests: make sure the default action properly works in C++ See e3fdc370495ffdedadd6ac621e32e34a0e1a9de0: in C++ we generate explicitly the code for the default action instead of simply copying blindly the semantic value buffer. This is important when copying raw memory is not enough, as exemplified by move-only types. This is currently tested by examples/c++/variant.yy and variant-11.yy. But it is safer to also have a test in the main test suite. * tests/local.at (AT_REQUIRE_CXX_STD): Fix. (AT_BISON_OPTION_PUSHDEFS, AT_BISON_OPTION_POPDEFS): Define/undefine AT_BISON_OPTIONS. * tests/c++.at (Default action): New. --- tests/c++.at | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/local.at | 10 ++++++--- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/tests/c++.at b/tests/c++.at index e2e73fc2..868ab3a4 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -1479,3 +1479,63 @@ AT_COMPILE_CXX([parser], [[x[12].o main.cc]], [-Iinclude]) AT_PARSER_CHECK([parser], [0]) AT_CLEANUP + + + +## ---------------- ## +## Default action. ## +## ---------------- ## + +# In C++ we generate explicitly the code for the default action +# instead of simply copying blindly the semantic value buffer. This +# is important when copying raw memory is not enough, as exemplified +# by move-only types. + +AT_SETUP([Default action]) +AT_KEYWORDS([action]) + +AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" +%define api.token.constructor +%define api.value.type variant]) + +AT_DATA_GRAMMAR([test.y], +[[%code requires { +#include // unique_ptr +} +%code { + ]AT_YYERROR_DECLARE[ + ]AT_YYLEX_DECLARE[ +} +]AT_BISON_OPTIONS[ +%define api.value.automove +%token ONE TWO EOI 0 +%type > ONE TWO one two one.opt two.opt +%% +exp: one.opt two.opt { std::cout << *$][1 << ", " << *$][2 << '\n'; } +one.opt: one | %empty {} +two.opt: two | %empty {} +one: ONE +two: TWO +%% +]AT_YYERROR_DEFINE[ +]AT_YYLEX_DEFINE(["12"], +[ if (res == '1') + return yy::parser::make_ONE (std::make_unique (10)); + else if (res == '2') + return yy::parser::make_TWO (std::make_unique (20)); + else + return yy::parser::make_EOI (); +])[ +]AT_MAIN_DEFINE[ +]]) + +AT_LANG_FOR_EACH_STD([ + AT_REQUIRE_CXX_STD(14, [echo "$at_std not supported"; continue]) + AT_FULL_COMPILE([[test]], [], [], [], [-fcaret]) + AT_PARSER_CHECK([[test]], 0, [[10, 20 +]]) +]) + +AT_BISON_OPTION_POPDEFS + +AT_CLEANUP diff --git a/tests/local.at b/tests/local.at index ee55efd6..63310901 100644 --- a/tests/local.at +++ b/tests/local.at @@ -137,7 +137,9 @@ m4_define([AT_BISON_OPTION_PUSHDEFS], # inside macros, because issuing '[$1]' is not possible in M4 :(. # This sucks hard, GNU M4 should really provide M5-like $$1. m4_define([_AT_BISON_OPTION_PUSHDEFS], -[m4_if([$1$2], $[1]$[2], [], +[m4_pushdef([AT_BISON_OPTIONS], [$3]) + +m4_if([$1$2], $[1]$[2], [], [m4_fatal([$0: invalid arguments: $@])])dnl m4_pushdef([AT_AUTOMOVE_IF], [m4_bmatch([$3], [%define api\.value\.automove], [$1], [$2])]) @@ -306,7 +308,9 @@ AT_GLR_IF([AT_KEYWORDS([glr])]) # ----------------------- m4_define([AT_BISON_OPTION_POPDEFS], [m4_divert_text([KILL], -[m4_popdef([AT_YYLEX_PRE_ARGS]) +[m4_popdef([AT_BISON_OPTIONS]) + +m4_popdef([AT_YYLEX_PRE_ARGS]) m4_popdef([AT_YYLEX_PRE_FORMALS]) m4_popdef([AT_USE_LEX_ARGS]) m4_popdef([AT_YYLEX_ARGS]) @@ -1126,7 +1130,7 @@ m4_ifval([$2], [if test $at_status != 0; then $2 fi], - [SKIP_IF([test $at_status != 0])]) + [AT_SKIP_IF([test $at_status != 0])]) ])