c++: fix generated headers

A forthcoming commit (tokens: properly define the "error" token kind)
revealed a problem in the C++ generated headers: they are not
self-contained.  With this file:

    %language "c++"
    %define api.value.type variant

    %code {
      static int yylex (yy::parser::semantic_type *lvalp);
    }

    %token <int> X

    %%

    exp:
      X { printf ("x\n"); }
    ;

    %%

    void
    yy::parser::error (const std::string& m)
    {
      std::cerr << m << '\n';
    }

    static
    int yylex (yy::parser::semantic_type *lvalp)
    {
      static int const input[] = {yy::parser::token::X, 0};
      static int toknum = 0;
      return input[toknum++];
    }

    int
    main (int argc, char const* argv[])
    {
      yy::parser p;
      return p.parse ();
    }

the generated header fails to compile cleanly (foo.cc just #includes
the generated header):

    $ clang++-mp-9.0 -c -Wundefined-func-template foo.cc
    In file included from foo.cc:1:
    bar.tab.hh:550:12: warning: instantiation of function 'yy::parser::basic_symbol<yy::parser::by_type>::basic_symbol' required here, but no definition is available
          [-Wundefined-func-template]
        struct symbol_type : basic_symbol<by_type>
               ^
    bar.tab.hh:436:7: note: forward declaration of template entity is here
          basic_symbol (basic_symbol&& that);
          ^
    bar.tab.hh:550:12: note: add an explicit instantiation declaration to suppress this warning if 'yy::parser::basic_symbol<yy::parser::by_type>::basic_symbol' is explicitly instantiated
          in another translation unit
        struct symbol_type : basic_symbol<by_type>
               ^
    1 warning generated.

* data/skeletons/c++.m4 (b4_public_types_define): Move the
implementation of the basic_symbol move-ctor to...
(b4_public_types_define): here, its declaration.
* tests/headers.at (Sane headers): Use a declared token so that the
corresponding token constructor is declared.  Which triggers the
aforementioned issue.
This commit is contained in:
Akim Demaille
2020-04-11 17:59:55 +02:00
parent 8dcc25a1e4
commit ecd5cae2d4
2 changed files with 13 additions and 16 deletions

View File

@@ -301,7 +301,14 @@ m4_define([b4_symbol_type_define],
#if 201103L <= YY_CPLUSPLUS #if 201103L <= YY_CPLUSPLUS
/// Move constructor. /// Move constructor.
basic_symbol (basic_symbol&& that); basic_symbol (basic_symbol&& that)
: Base (std::move (that))
, value (]b4_variant_if([], [std::move (that.value)]))b4_locations_if([
, location (std::move (that.location))])[
{]b4_variant_if([
b4_symbol_variant([this->type_get ()], [value], [move],
[std::move (that.value)])
])[}
#endif #endif
/// Copy constructor. /// Copy constructor.
@@ -417,18 +424,6 @@ m4_define([b4_symbol_type_define],
# Provide the implementation needed by the public types. # Provide the implementation needed by the public types.
m4_define([b4_public_types_define], m4_define([b4_public_types_define],
[[ // basic_symbol. [[ // basic_symbol.
#if 201103L <= YY_CPLUSPLUS
template <typename Base>
]b4_parser_class[::basic_symbol<Base>::basic_symbol (basic_symbol&& that)
: Base (std::move (that))
, value (]b4_variant_if([], [std::move (that.value)]))b4_locations_if([
, location (std::move (that.location))])[
{]b4_variant_if([
b4_symbol_variant([this->type_get ()], [value], [move],
[std::move (that.value)])
])[}
#endif
template <typename Base> template <typename Base>
]b4_parser_class[::basic_symbol<Base>::basic_symbol (const basic_symbol& that) ]b4_parser_class[::basic_symbol<Base>::basic_symbol (const basic_symbol& that)
: Base (that) : Base (that)

View File

@@ -125,7 +125,9 @@ AT_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_GRAMMAR([input.y], AT_DATA_GRAMMAR([input.y],
[[$1 [[$1
%define parse.error verbose %define parse.error verbose
]AT_VARIANT_IF([%token <int> 'x'], [%union {int integer;}])[ ]AT_VARIANT_IF([%token <int> X],
[%union {int integer;}
%token <integer> X])[
%code { %code {
#include <stdio.h> /* printf. */ #include <stdio.h> /* printf. */
]AT_PUSH_IF([[ ]AT_PUSH_IF([[
@@ -138,12 +140,12 @@ AT_DATA_GRAMMAR([input.y],
} }
%% %%
exp: exp:
'x' { printf ("x\n"); } X { printf ("x\n"); }
; ;
%% %%
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["x"])[ ]AT_YYLEX_DEFINE([{AT_CXX_IF([yy::parser::token::])X, 0}])[
]]) ]])
AT_BISON_CHECK([-d -o input.AT_LANG_EXT input.y]) AT_BISON_CHECK([-d -o input.AT_LANG_EXT input.y])