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 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 ** Bug fixes
*** GLR: Predicates support broken by #line directives *** 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 Bill Allombert Bill.Allombert@math.u-bordeaux1.fr
Bob Rossi bob@brasko.net Bob Rossi bob@brasko.net
Brandon Lucia blucia@gmail.com Brandon Lucia blucia@gmail.com
Brooks Moses bmoses@google.com
Bruce Lilly blilly@erols.com Bruce Lilly blilly@erols.com
Bruno Haible bruno@clisp.org Bruno Haible bruno@clisp.org
Charles-Henri de Boysson de-boy_c@epita.fr 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. # ... possiby in std=c++11 mode.
gl_WARN_ADD([-Wno-zero-as-null-pointer-constant], [FLEX_SCANNER_CXXFLAGS]) gl_WARN_ADD([-Wno-zero-as-null-pointer-constant], [FLEX_SCANNER_CXXFLAGS])
CXXFLAGS=$save_CXXFLAGS CXXFLAGS=$save_CXXFLAGS
gl_WARN_ADD([-fno-exceptions], [CXXFLAGS_NO_EXCEPTIONS])
AC_LANG_POP([C++]) AC_LANG_POP([C++])
fi fi

View File

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

View File

@@ -10885,13 +10885,12 @@ use @code{yy::parser::token::FOO}. The scanner can use
@defcv {Type} {parser} {syntax_error} @defcv {Type} {parser} {syntax_error}
This class derives from @code{std::runtime_error}. Throw instances of it 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 from the scanner or from the actions to raise parse errors. This is
equivalent with first equivalent with first invoking @code{error} to report the location and
invoking @code{error} to report the location and message of the syntax message of the syntax error, and then to invoke @code{YYERROR} to enter the
error, and then to invoke @code{YYERROR} to enter the error-recovery mode. error-recovery mode. But contrary to @code{YYERROR} which can only be
But contrary to @code{YYERROR} which can only be invoked from user actions invoked from user actions (i.e., written in the action itself), the
(i.e., written in the action itself), the exception can be thrown from exception can be thrown from function invoked from the user action.
function invoked from the user action.
@end defcv @end defcv
@deftypemethod {parser} {} parser (@var{type1} @var{arg1}, ...) @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 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 when an exception is thrown, the @code{%destructor}s are called to release
the lookahead symbol, and the symbols pushed on the stack. 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 @end deftypemethod
@deftypemethod {parser} {std::ostream&} debug_stream () @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 ':'. # If 'exit 77'; skip all C++ tests; otherwise ':'.
BISON_CXX_WORKS='@BISON_CXX_WORKS@' 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 # Be sure that the C++ compiler is not broken because of gnulib. This
# cannot be checked in configure (gnulib is not parameterized yet), # cannot be checked in configure (gnulib is not parameterized yet),
# and checking this in every C++ test in AC_COMPILE_CXX is too costly. # 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 # Start a testing chunk which compiles 'calc' grammar with
# BISON-OPTIONS, and performs several tests over the parser. # BISON-OPTIONS, and performs several tests over the parser.
m4_define([AT_CHECK_CALC], 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. # 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_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_CALC_Y([$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([ ], AT_CHECK_SPACES(m4_join([ ],
[calc.AT_SKEL_CC_IF([cc], [c])], [calc.AT_SKEL_CC_IF([cc], [c])],
[AT_DEFINES_IF([calc.AT_SKEL_CC_IF([hh], [h])])])) [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 # Start a testing chunk which compiles 'calc' grammar with
# the C++ skeleton, and performs several tests over the parser. # the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_CC], 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([])
AT_CHECK_CALC_LALR1_CC([%locations]) 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([%locations %define api.location.type {Span}])
AT_CHECK_CALC_LALR1_CC([%defines %locations %define parse.error verbose %name-prefix "calc" %verbose %yacc]) 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. # Compile SOURCES into OUTPUT.
# #
# If OUTPUT does not contain '.', assume that we are linking too, # If OUTPUT does not contain '.', assume that we are linking too,
@@ -758,8 +758,8 @@ AT_CHECK(m4_join([ ],
0, [ignore], [ignore])]) 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, # Compile SOURCES into OUTPUT. If the C++ compiler does not work,
# ignore the test. # ignore the test.
# #
@@ -770,7 +770,7 @@ m4_define([AT_COMPILE_CXX],
[AT_KEYWORDS(c++) [AT_KEYWORDS(c++)
AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore) AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore)
AT_CHECK(m4_join([ ], AT_CHECK(m4_join([ ],
[$CXX $CXXFLAGS $CPPFLAGS], [$CXX $CXXFLAGS $CPPFLAGS $3],
[m4_bmatch([$1], [[.]], [-c], [$LDFLAGS])], [m4_bmatch([$1], [[.]], [-c], [$LDFLAGS])],
[-o $1], [-o $1],
[m4_default([$2], [m4_bpatsubst([$1], [\.o$]).cc])], [m4_default([$2], [m4_bpatsubst([$1], [\.o$]).cc])],
@@ -790,21 +790,21 @@ AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
[[0]], [ignore], [ignore])]) [[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. # Compile SOURCES into OUTPUT. Skip if compiler does not work.
# #
# If OUTPUT does not contain '.', assume that we are linking too, # If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT # otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing .o removed, and ".c"/".cc" appended. # with trailing .o removed, and ".c"/".cc" appended.
m4_define([AT_LANG_COMPILE], [AT_LANG_DISPATCH([$0], $@)]) 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([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2])]) m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2])]) 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 OUTPUT.y to OUTPUT.c, OUTPUT.cc, or OUTPUT.java, and then
# compile it to OUTPUT or OUTPUT.class. If OTHER is specified, compile # 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 # 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([ ], m4_join([ ],
[$1.c], [$1.c],
m4_ifval($2, [[$1-$2.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++)], m4_define([AT_FULL_COMPILE(c++)],
[AT_BISON_CHECK([-o $1.cc $1.y]) [AT_BISON_CHECK([-o $1.cc $1.y])
@@ -825,7 +826,8 @@ m4_define([AT_FULL_COMPILE(c++)],
m4_join([ ], m4_join([ ],
[$1.cc], [$1.cc],
m4_ifval($2, [[$1-$2.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)], m4_define([AT_FULL_COMPILE(java)],
[AT_BISON_CHECK([-o $1.java $1.y]) [AT_BISON_CHECK([-o $1.java $1.y])
@@ -833,7 +835,8 @@ m4_define([AT_FULL_COMPILE(java)],
m4_join([ ], m4_join([ ],
[$1.java], [$1.java],
m4_ifval($2, [[$1-$2.java]]), m4_ifval($2, [[$1-$2.java]]),
m4_ifval($3, [[$1-$3.java]])))]) m4_ifval($3, [[$1-$3.java]])),
[$4])])