[PATCH 1/4] glr2.cc: disable incorrect warnings from GCC6 to 9

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
For instance with GCC8:

    616. regression.at:1560: testing Lex and parse params: glr2.cc ...
    tests/regression.at:1560: COLUMNS=1000; export COLUMNS; NO_TERM_HYPERLINKS=1; export NO_TERM_HYPERLINKS;  bison --color=no -fno-caret  -o input.cc input.y
    tests/regression.at:1560: $CXX $CXXFLAGS $CPPFLAGS  $LDFLAGS -o input input.cc $LIBS
    stderr:
    input.cc: In member function 'YYRESULTTAG glr_stack::yyresolveValue(glr_state*)':
    input.cc:1796:10: error: potential null pointer dereference [-Werror=null-dereference]
       return yypred ? &(asItem(this) - yypred)->getState() : YY_NULLPTR;
              ^~~~~~
    input.cc:1796:10: error: potential null pointer dereference [-Werror=null-dereference]
       return yypred ? &(asItem(this) - yypred)->getState() : YY_NULLPTR;
              ^~~~~~
    cc1plus: all warnings being treated as errors

It complains that the implicit this in yypred might be null.  It fears
it because of loops such as

    for (glr_state* yys = firstTopState();
         yys != yystateStack.yysplitPoint;
         yys = yys->pred())
      yyn += 1;

that could possibly set yys to null, since yys->pred might return
null.  However, the warning is incorrect, since in C++ `this` cannot
be null.  GCC 10 no longer emits this warning.

GCC 7 also complains many times about glr_stack::yyresolveLocations
when NDEBUG is enabled (when it is not, YYASSERT (yyoption !=
YY_NULLPTR) is probably enough to pacify GCC):

    616. regression.at:1560: testing Lex and parse params: glr2.cc ...
    tests/regression.at:1560: COLUMNS=1000; export COLUMNS; NO_TERM_HYPERLINKS=1; export NO_TERM_HYPERLINKS;  bison --color=no -fno-caret  -o input.cc input.y
    tests/regression.at:1560: $CXX $CXXFLAGS $CPPFLAGS  $LDFLAGS -o input input.cc $LIBS
    stderr:
    input.cc: In member function 'void glr_stack::yyresolveLocations(glr_state*, int)':
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc: In member function 'YYRESULTTAG glr_stack::yyresolveValue(glr_state*)':
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
    input.cc:3061:46: error: potential null pointer dereference [-Werror=null-dereference]
                     yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

* data/skeletons/glr2.cc (YY_IGNORE_NULL_DEREFERENCE_BEGIN)
(YY_IGNORE_NULL_DEREFERENCE_BEGIN): New.
(glr_state::pred, glr_stack::yyresolveLocations): Use them.
---
 TODO                   | 13 ++++++++++---
 data/skeletons/glr2.cc | 27 +++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/TODO b/TODO
index 3f4d1978..c692b9f9 100644
--- a/TODO
+++ b/TODO
@@ -158,9 +158,12 @@ Les catégories d'avertissements incluent :
 Line -1 and -3 should mention CATEGORIE, not CATEGORY.
 
 * Bison 3.8
-** Rewrite glr.cc
-*** glr.c
-Get rid of scaffolding in glr.c.
+** Rewrite glr.cc (currently glr2.cc)
+*** Remove jumps
+We can probably replace setjmp/longjmp with exceptions.  That would help
+tremendously other languages such as D and Java that probably have no
+similar feature.  If we remove jumps, we probably no longer need _Noreturn,
+so simplify `b4_attribute_define([noreturn])` into `b4_attribute_define`.
 
 *** Coding style
 Move to our coding conventions.  In particular names such as yy_glr_stack,
@@ -178,6 +181,10 @@ There are many places where pointers should be replaced with references.
 Don't use YYSTYPE and YYLTYPE but parser::semantic_type and
 parser::location_type.  Undefine YYSTYPE and YYLTYPE.
 
+*** glr.c
+When glr2.cc fully replaces glr.cc, get rid of the glr.cc scaffolding in
+glr.c.
+
 * Chains
 ** Unit rules / Injection rules (Akim Demaille)
 Maybe we could expand unit rules (or "injections", see
diff --git a/data/skeletons/glr2.cc b/data/skeletons/glr2.cc
index a7f2d129..e463ffb3 100644
--- a/data/skeletons/glr2.cc
+++ b/data/skeletons/glr2.cc
@@ -126,6 +126,17 @@ b4_percent_code_get([[requires]])[
 ]b4_cast_define[
 ]b4_null_define[
 
+#if defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ && __GNUC__ <= 9
+# define YY_IGNORE_NULL_DEREFERENCE_BEGIN                               \
+  _Pragma ("GCC diagnostic push")                                       \
+  _Pragma ("GCC diagnostic ignored \"-Wnull-dereference\"")
+# define YY_IGNORE_NULL_DEREFERENCE_END         \
+  _Pragma ("GCC diagnostic pop")
+#else
+# define YY_IGNORE_NULL_DEREFERENCE_BEGIN
+# define YY_IGNORE_NULL_DEREFERENCE_END
+#endif
+
 // Whether we are compiled with exception support.
 #ifndef YY_EXCEPTIONS
 # if defined __GNUC__ && !defined __EXCEPTIONS
@@ -1271,12 +1282,18 @@ public:
   bool is_state_;
 };
 
-glr_state* glr_state::pred() {
-  return yypred ? &(asItem(this) - yypred)->getState() : YY_NULLPTR;
+glr_state* glr_state::pred ()
+{
+  YY_IGNORE_NULL_DEREFERENCE_BEGIN
+  return yypred ? &(asItem (this) - yypred)->getState () : YY_NULLPTR;
+  YY_IGNORE_NULL_DEREFERENCE_END
 }
 
-const glr_state* glr_state::pred() const {
-  return yypred ? &(asItem(this) - yypred)->getState() : YY_NULLPTR;
+const glr_state* glr_state::pred () const
+{
+  YY_IGNORE_NULL_DEREFERENCE_BEGIN
+  return yypred ? &(asItem (this) - yypred)->getState () : YY_NULLPTR;
+  YY_IGNORE_NULL_DEREFERENCE_END
 }
 
 void glr_state::setPred(const glr_state* state) {
@@ -2606,7 +2623,9 @@ class glr_stack {
                    detected.  Thus the location of the previous state (but not
                    necessarily the previous state itself) is guaranteed to be
                    resolved already.  */
+                YY_IGNORE_NULL_DEREFERENCE_BEGIN
                 yyrhsloc[0].getState().yyloc = yyoption->state()->yyloc;
+                YY_IGNORE_NULL_DEREFERENCE_END
               }
             YYLLOC_DEFAULT ((yys1->yyloc), yyrhsloc, yynrhs);
           }
-- 
2.28.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.