tests: make sure the default action properly works in C++

See e3fdc37049: 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.
This commit is contained in:
Akim Demaille
2019-06-08 22:05:03 +02:00
parent 73797b2552
commit d84b245c63
2 changed files with 67 additions and 3 deletions

View File

@@ -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 <memory> // unique_ptr
}
%code {
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
]AT_BISON_OPTIONS[
%define api.value.automove
%token ONE TWO EOI 0
%type <std::unique_ptr<int>> 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<int> (10));
else if (res == '2')
return yy::parser::make_TWO (std::make_unique<int> (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

View File

@@ -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])])
])