Subject: bug#68832: Testing: POSIX yacc and C++ linkage

From: Marcel Telka <[email-masked]>
Date: Tue, 30 Jan 2024 21:35:41 +0100

Hi,

I ran tests for automake 1.16.5 on OpenIndiana and following 4 tests
failed:

FAIL: t/yacc-cxx.sh
FAIL: t/yacc-clean-cxx.sh
FAIL: t/yacc-d-cxx.sh
FAIL: t/yacc-mix-c-cxx.sh

The cause for the failure is this:

parse1.yy:30:7: error: conflicting declaration of 'void yyerror(const char*)' with 'C' linkage
parse1.yy:7:6: note: previous declaration with 'C++' linkage
    7 | void yyerror (const char *s) {}
      |      ^~~~~~~
parse1.yy:34:6: error: conflicting declaration of 'int yylex()' with 'C' linkage
parse1.yy:6:5: note: previous declaration with 'C++' linkage
    6 | int yylex (void) { return std::getchar (); }
      |     ^~~~~

For testing there is the default system yacc used.  It is the illumos
yacc as inherited from Solaris with some changes[1].  The generated code
that causes the failure is this:

 24 #if defined(__cplusplus) || defined(__STDC__)
 25 
 26 #if defined(__cplusplus)
 27 extern "C" {
 28 #endif
 29 #ifndef yyerror
 30 #if defined(__cplusplus)
 31         void yyerror(YYCONST char *);
 32 #endif
 33 #endif
 34 #ifndef yylex
 35         int yylex(void);
 36 #endif
 37         int yyparse(void);
 38 #if defined(__cplusplus)
 39 }
 40 #endif
 41 
 42 #endif

The issue is apparent.  The yacc generated code create both yyerror()
and yylex() with the C linkage, but testing expects C++ linkage.  This
is exactly what the compiler error says.

All of this is obvious.  So where is the bug and what should be fixed?
There are few possible views:

1. yacc is buggy and should not force C linkage for C++ source.  This is
grey area because POSIX says nothing about linkage or C++[2].

2. The tests' expectations about yacc behavior re C++ are too strong.
This seems to be true for illumos yacc.  Other yacc implementations, for
example GNU bison, does better job and do not force C linkage for
affected functions.

My proposal to solve the issue is to change affected tests to require
bison instead of yacc.  Please see attachment.

Thank you.

[1] for example this: https://www.illumos.org/issues/16136
[2] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/yacc.html

-- 
+-------------------------------------------+
| Marcel Telka   e-mail:   [email-masked]  |
|                homepage: http://telka.sk/ |
+-------------------------------------------+
--- automake-1.16.5/t/yacc-cxx.sh.orig
+++ automake-1.16.5/t/yacc-cxx.sh
@@ -18,7 +18,7 @@
 # headers are not involved).
 # Keep in sync with sister test 'yacc-basic.sh'.
 
-required='c++ yacc'
+required='c++ bison'
 . test-init.sh
 
 cat >> configure.ac << 'END'
--- automake-1.16.5/t/yacc-clean-cxx.sh.orig
+++ automake-1.16.5/t/yacc-clean-cxx.sh
@@ -20,7 +20,7 @@
 # "make maintainer-clean".
 # See also sister test 'yacc-clean.sh'.
 
-required='c++ yacc'
+required='c++ bison'
 . test-init.sh
 
 cat >> configure.ac << 'END'
--- automake-1.16.5/t/yacc-d-cxx.sh.orig
+++ automake-1.16.5/t/yacc-d-cxx.sh
@@ -18,7 +18,7 @@
 # (i.e., '-d' in *YFLAGS).
 # Keep in sync with sister test 'yacc-d-basic.sh'.
 
-required='c++ yacc'
+required='c++ bison'
 . test-init.sh
 
 write_parse ()
--- automake-1.16.5/t/yacc-mix-c-cxx.sh.orig
+++ automake-1.16.5/t/yacc-mix-c-cxx.sh
@@ -17,7 +17,7 @@
 # Check that many different Yacc parsers (both C and C++) can co-exists
 # in the same directory.
 
-required='cc c++ yacc'
+required='cc c++ bison'
 . test-init.sh
 
 cat >> configure.ac << 'END'