diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2021-01-31 16:05:13 +0100 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2021-02-01 05:54:06 +0100 |
commit | 9acc9d2aeeee21be4572a0eaac6146867f264243 (patch) | |
tree | 833812ec39398a25a1510d902c452bfc71e15d3d | |
parent | dc8fe0678a6f32a1d755bb163efcac42976220d9 (diff) | |
download | bison-9acc9d2aeeee21be4572a0eaac6146867f264243.tar.gz |
c++: issue a compile-time warning when #define YYSTYPE is used
Using #define YYSTYPE has always been strongly discouraged in C++.
Macros are dangerous and can result in subtle bugs.
https://lists.gnu.org/r/bug-bison/2020-12/msg00007.html
Maybe some people are currently using #define YYSTYPE. Instead of
dropping support right now, first issue a warning. Bison can "see" if
YYDEBUG is defined (it could even be on the command line), only the
compiler knows. Unfortunately `#warning` is non-portable, and
actually GCC even dies on it when `-pedantic` is enabled. So we need
to use `#pragma message`. We must make it conditional as some
compilers might not support it, but it doesn't matter if only _some_
compilers emit the warning: it should be enough to catch the attention
of the developers.
* data/skeletons/c++.m4: Issue a warning when the user defined
YYSTYPE.
* tests/actions.at: Don't #define YYSTYPE.
* tests/headers.at (Several parsers): Ignore the YYSTYPE in the
warning.
-rw-r--r-- | data/skeletons/c++.m4 | 9 | ||||
-rw-r--r-- | tests/actions.at | 4 | ||||
-rw-r--r-- | tests/headers.at | 17 |
3 files changed, 18 insertions, 12 deletions
diff --git a/data/skeletons/c++.m4 b/data/skeletons/c++.m4 index 212978a2..cd6fdb03 100644 --- a/data/skeletons/c++.m4 +++ b/data/skeletons/c++.m4 @@ -227,10 +227,13 @@ m4_define([b4_value_type_declare], # Define the public types: token, semantic value, location, and so forth. # Depending on %define token_lex, may be output in the header or source file. m4_define([b4_public_types_declare], -[[#ifndef ]b4_api_PREFIX[STYPE -]b4_value_type_declare[ -#else +[[#ifdef ]b4_api_PREFIX[STYPE +# ifdef __GNUC__ +# pragma GCC message "bison: do not #define ]b4_api_PREFIX[STYPE in C++, use %define api.value.type" +# endif typedef ]b4_api_PREFIX[STYPE value_type; +#else +]b4_value_type_declare[ #endif /// Backward compatibility (Bison 3.8). typedef value_type semantic_type;]b4_locations_if([ diff --git a/tests/actions.at b/tests/actions.at index ed1e8d68..e08734b5 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -1777,8 +1777,6 @@ AT_DATA_GRAMMAR([[input.y]], float fval; } sem_type; -# define YYSTYPE sem_type - ]AT_CXX_IF([[ # include <cstdio> // EOF. # include <iostream> @@ -1800,6 +1798,8 @@ AT_DATA_GRAMMAR([[input.y]], ]])[ } +%define api.value.type {sem_type} + %code { ]AT_YYERROR_DECLARE[ diff --git a/tests/headers.at b/tests/headers.at index b3262fad..57a5591f 100644 --- a/tests/headers.at +++ b/tests/headers.at @@ -328,15 +328,18 @@ AT_TEST([xb], [%locations %define api.location.file none %language "c++" %define # C++ output relies on namespaces and still uses yy a lot. # # - no 'YY' left. -# Ignore comments, YYChar (template parameter), YYPUSH_MORE(_DEFINED)? -# (constant definition), YY_\w+_INCLUDED (header guards). +# Ignore YYPUSH_MORE(_DEFINED)? (constant definition), # YYDEBUG (not renamed) can be read, but not changed. AT_PERL_CHECK([[-n -0777 -e ' + # Ignore comments. s{/\*.*?\*/}{}gs; s{//.*}{}g; + # Ignore warnings. + s{# *pragma .* message ".*"}{}g; + s{\b((defined|if)\ YYDEBUG - |YYChar - |YYNTOKENS # This is actual scoped in a C++ class. + |YYChar # Template parameter. + |YYNTOKENS # This is actually scoped in a C++ class. |YYPUSH_MORE(?:_DEFINED)? |S_(YY(ACCEPT|EMPTY|EOF|error|UNDEF)) # These guys are scoped. |YY(?:_REINTERPRET)?_CAST @@ -354,9 +357,9 @@ AT_PERL_CHECK([[-n -0777 -e ' |YY_NULLPTR |YY_RVREF |YY_USE - |YY_\w+_INCLUDED - |FILE\ \*yyo # Function argument. - |const\ yylocp # Function argument. + |YY_\w+_INCLUDED # Header guards. + |FILE\ \*yyo # Function argument. + |const\ yylocp # Function argument. )\b}{}gx; while (/^(.*YY.*)$/gm) { |