lalr1.cc: support compilation with disabled support for exceptions

Reported by Brooks Moses <bmoses@google.com>
http://lists.gnu.org/archive/html/bison-patches/2018-02/msg00000.html

* data/lalr1.cc (YY_EXCEPTIONS): New.
Use it to disable try/catch clauses.

* doc/bison.texi (C++ Parser Interface): Document it.

* configure.ac (CXXFLAGS_NO_EXCEPTIONS): New.
* tests/atlocal.in: Receive it.
* tests/local.at (AT_FULL_COMPILE, AT_LANG_COMPILE):
Accept a new argument, extra compiler flags.
* tests/calc.at: Run the C++ calculator with exception support disabled.
This commit is contained in:
Akim Demaille
2018-08-17 19:28:50 +02:00
parent 32e0fd1a99
commit 44e76d801f
8 changed files with 68 additions and 28 deletions

7
NEWS
View File

@@ -74,6 +74,13 @@ GNU Bison NEWS
input: '0' | exp
^^^
*** C++: Generated parsers can be compiled with -fno-exceptions (lalr1.cc)
When compiled with exceptions disabled, the generated parsers no longer
uses try/catch clauses.
Currently only GCC and Clang are supported.
** Bug fixes
*** GLR: Predicates support broken by #line directives

1
THANKS
View File

@@ -25,6 +25,7 @@ Bert Deknuydt Bert.Deknuydt@esat.kuleuven.ac.be
Bill Allombert Bill.Allombert@math.u-bordeaux1.fr
Bob Rossi bob@brasko.net
Brandon Lucia blucia@gmail.com
Brooks Moses bmoses@google.com
Bruce Lilly blilly@erols.com
Bruno Haible bruno@clisp.org
Charles-Henri de Boysson de-boy_c@epita.fr

View File

@@ -153,6 +153,7 @@ if test "$enable_gcc_warnings" = yes; then
# ... possiby in std=c++11 mode.
gl_WARN_ADD([-Wno-zero-as-null-pointer-constant], [FLEX_SCANNER_CXXFLAGS])
CXXFLAGS=$save_CXXFLAGS
gl_WARN_ADD([-fno-exceptions], [CXXFLAGS_NO_EXCEPTIONS])
AC_LANG_POP([C++])
fi

View File

@@ -424,6 +424,15 @@ m4_if(b4_prefix, [yy], [],
# endif
#endif
// Whether we are compiled with exception support.
#ifndef YY_EXCEPTIONS
# if defined __GNUC__ && !defined __EXCEPTIONS
# define YY_EXCEPTIONS 0
# else
# define YY_EXCEPTIONS 1
# endif
#endif
]b4_locations_if([dnl
[#define YYRHSLOC(Rhs, K) ((Rhs)[K].location)
]b4_yylloc_default_define])[
@@ -717,7 +726,9 @@ m4_if(b4_prefix, [yy], [],
/// The return value of parse ().
int yyresult;
#if YY_EXCEPTIONS
try
#endif // YY_EXCEPTIONS
{
YYCDEBUG << "Starting parse\n";
@@ -755,17 +766,21 @@ b4_dollar_popdef])[]dnl
if (yyla.empty ())
{
YYCDEBUG << "Reading a token: ";
#if YY_EXCEPTIONS
try
#endif // YY_EXCEPTIONS
{]b4_token_ctor_if([[
symbol_type yylookahead (]b4_lex[);
yyla.move (yylookahead);]], [[
yyla.type = yytranslate_ (]b4_lex[);]])[
}
#if YY_EXCEPTIONS
catch (const syntax_error& yyexc)
{
error (yyexc);
goto yyerrlab1;
}
#endif // YY_EXCEPTIONS
}
YY_SYMBOL_PRINT ("Next token is", yyla);
@@ -835,7 +850,9 @@ b4_dollar_popdef])[]dnl
// Perform the reduction.
YY_REDUCE_PRINT (yyn);
#if YY_EXCEPTIONS
try
#endif // YY_EXCEPTIONS
{
switch (yyn)
{
@@ -844,11 +861,13 @@ b4_dollar_popdef])[]dnl
break;
}
}
#if YY_EXCEPTIONS
catch (const syntax_error& yyexc)
{
error (yyexc);
YYERROR;
}
#endif // YY_EXCEPTIONS
YY_SYMBOL_PRINT ("-> $$ =", yylhs);
yypop_ (yylen);
yylen = 0;
@@ -973,6 +992,7 @@ b4_dollar_popdef])[]dnl
return yyresult;
}
#if YY_EXCEPTIONS
catch (...)
{
YYCDEBUG << "Exception caught: cleaning lookahead and stack\n";
@@ -988,6 +1008,7 @@ b4_dollar_popdef])[]dnl
}
throw;
}
#endif // YY_EXCEPTIONS
}
void

View File

@@ -10885,13 +10885,12 @@ use @code{yy::parser::token::FOO}. The scanner can use
@defcv {Type} {parser} {syntax_error}
This class derives from @code{std::runtime_error}. Throw instances of it
from the scanner or from the user actions to raise parse errors. This is
equivalent with first
invoking @code{error} to report the location and message of the syntax
error, and then to invoke @code{YYERROR} to enter the error-recovery mode.
But contrary to @code{YYERROR} which can only be invoked from user actions
(i.e., written in the action itself), the exception can be thrown from
function invoked from the user action.
from the scanner or from the actions to raise parse errors. This is
equivalent with first invoking @code{error} to report the location and
message of the syntax error, and then to invoke @code{YYERROR} to enter the
error-recovery mode. But contrary to @code{YYERROR} which can only be
invoked from user actions (i.e., written in the action itself), the
exception can be thrown from function invoked from the user action.
@end defcv
@deftypemethod {parser} {} parser (@var{type1} @var{arg1}, ...)
@@ -10911,6 +10910,10 @@ Run the syntactic analysis, and return 0 on success, 1 otherwise.
The whole function is wrapped in a @code{try}/@code{catch} block, so that
when an exception is thrown, the @code{%destructor}s are called to release
the lookahead symbol, and the symbols pushed on the stack.
Exception related code in the generated parser is protected by CPP guards
(@code{#if}) and disabled when exceptions are not supported (i.e., passing
@code{-fno-exceptions} to the C++ compiler).
@end deftypemethod
@deftypemethod {parser} {std::ostream&} debug_stream ()

View File

@@ -50,6 +50,9 @@ CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@"
# If 'exit 77'; skip all C++ tests; otherwise ':'.
BISON_CXX_WORKS='@BISON_CXX_WORKS@'
# Compiler flags to disable exception support.
CXXFLAGS_NO_EXCEPTIONS='@CXXFLAGS_NO_EXCEPTIONS@'
# Be sure that the C++ compiler is not broken because of gnulib. This
# cannot be checked in configure (gnulib is not parameterized yet),
# and checking this in every C++ test in AC_COMPILE_CXX is too costly.

View File

@@ -481,20 +481,20 @@ m4_define([AT_CHECK_SPACES],
])
# AT_CHECK_CALC([BISON-OPTIONS])
# ------------------------------
# AT_CHECK_CALC([BISON-OPTIONS], [COMPILER-OPTIONS])
# --------------------------------------------------
# Start a testing chunk which compiles 'calc' grammar with
# BISON-OPTIONS, and performs several tests over the parser.
m4_define([AT_CHECK_CALC],
[m4_ifval([$2], [m4_fatal([$0: expected a single argument])])
[m4_ifval([$3], [m4_fatal([$0: expected at most two arguments])])
# We use integers to avoid dependencies upon the precision of doubles.
AT_SETUP([Calculator $1])
AT_SETUP([Calculator $1 $2])
AT_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_CALC_Y([$1])
AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]]))
AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]]), [], [$2])
AT_CHECK_SPACES(m4_join([ ],
[calc.AT_SKEL_CC_IF([cc], [c])],
[AT_DEFINES_IF([calc.AT_SKEL_CC_IF([hh], [h])])]))
@@ -677,10 +677,11 @@ AT_CHECK_CALC([%skeleton "lalr1.cc" %defines])
# Start a testing chunk which compiles 'calc' grammar with
# the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_CC],
[AT_CHECK_CALC([%language "C++"] $@)])
[AT_CHECK_CALC([%language "C++" $1], [$2])])
AT_CHECK_CALC_LALR1_CC([])
AT_CHECK_CALC_LALR1_CC([%locations])
AT_CHECK_CALC_LALR1_CC([%locations], [$CXXFLAGS_NO_EXCEPTIONS])
AT_CHECK_CALC_LALR1_CC([%locations %define api.location.type {Span}])
AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])

View File

@@ -740,8 +740,8 @@ m4_define([AT_QUELL_VALGRIND],
## ------------------------ ##
# AT_COMPILE(OUTPUT, [SOURCES = OUTPUT.c])
# ----------------------------------------
# AT_COMPILE(OUTPUT, [SOURCES = OUTPUT.c], [EXTRA-COMPILER-FLAGS])
# ----------------------------------------------------------------
# Compile SOURCES into OUTPUT.
#
# If OUTPUT does not contain '.', assume that we are linking too,
@@ -758,8 +758,8 @@ AT_CHECK(m4_join([ ],
0, [ignore], [ignore])])
# AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc])
# ---------------------------------------------
# AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc], [EXTRA-COMPILER-FLAGS])
# ---------------------------------------------------------------------
# Compile SOURCES into OUTPUT. If the C++ compiler does not work,
# ignore the test.
#
@@ -770,7 +770,7 @@ m4_define([AT_COMPILE_CXX],
[AT_KEYWORDS(c++)
AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore)
AT_CHECK(m4_join([ ],
[$CXX $CXXFLAGS $CPPFLAGS],
[$CXX $CXXFLAGS $CPPFLAGS $3],
[m4_bmatch([$1], [[.]], [-c], [$LDFLAGS])],
[-o $1],
[m4_default([$2], [m4_bpatsubst([$1], [\.o$]).cc])],
@@ -790,21 +790,21 @@ AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
[[0]], [ignore], [ignore])])
# AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c]
# --------------------------------------------
# AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c], [EXTRA-COMPILER-FLAGS])
# ---------------------------------------------------------------------
# Compile SOURCES into OUTPUT. Skip if compiler does not work.
#
# If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing .o removed, and ".c"/".cc" appended.
m4_define([AT_LANG_COMPILE], [AT_LANG_DISPATCH([$0], $@)])
m4_define([AT_LANG_COMPILE(c)], [AT_COMPILE([$1], [$2])])
m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2])])
m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2])])
m4_define([AT_LANG_COMPILE(c)], [AT_COMPILE([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2], [$3])])
# AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2])
# -------------------------------------------
# AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2], [EXTRA-COMPILER-FLAGS)
# ------------------------------------------------------------------
# Compile OUTPUT.y to OUTPUT.c, OUTPUT.cc, or OUTPUT.java, and then
# compile it to OUTPUT or OUTPUT.class. If OTHER is specified, compile
# OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or
@@ -817,7 +817,8 @@ m4_define([AT_FULL_COMPILE(c)],
m4_join([ ],
[$1.c],
m4_ifval($2, [[$1-$2.c]]),
m4_ifval($3, [[$1-$3.c]])))])
m4_ifval($3, [[$1-$3.c]])),
[$4])])
m4_define([AT_FULL_COMPILE(c++)],
[AT_BISON_CHECK([-o $1.cc $1.y])
@@ -825,7 +826,8 @@ m4_define([AT_FULL_COMPILE(c++)],
m4_join([ ],
[$1.cc],
m4_ifval($2, [[$1-$2.cc]]),
m4_ifval($3, [[$1-$3.cc]])))])
m4_ifval($3, [[$1-$3.cc]])),
[$4])])
m4_define([AT_FULL_COMPILE(java)],
[AT_BISON_CHECK([-o $1.java $1.y])
@@ -833,7 +835,8 @@ m4_define([AT_FULL_COMPILE(java)],
m4_join([ ],
[$1.java],
m4_ifval($2, [[$1-$2.java]]),
m4_ifval($3, [[$1-$3.java]])))])
m4_ifval($3, [[$1-$3.java]])),
[$4])])