summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2021-01-31 16:05:13 +0100
committerAkim Demaille <akim.demaille@gmail.com>2021-02-01 05:54:06 +0100
commit9acc9d2aeeee21be4572a0eaac6146867f264243 (patch)
tree833812ec39398a25a1510d902c452bfc71e15d3d
parentdc8fe0678a6f32a1d755bb163efcac42976220d9 (diff)
downloadbison-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++.m49
-rw-r--r--tests/actions.at4
-rw-r--r--tests/headers.at17
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)
{