Re: bool and C23

2022-09-18 Thread Bruno Haible
Paul Eggert wrote:
> >   #include "unitypes.h"
> >   
> > +/* Get bool.  */
> > +#include 
> 
> In examples like these would it make sense to do the following instead? 
> 
>#if !@HAVE_C_BOOL@ && !defined __cplusplus
> #include 
>#endif

No, this would not work:
  * @HAVE_C_BOOL@ tests a property of the C compiler that has built
libunistring. It is unrelated to the compiler that uses 
after it has been installed in public locations.
  * As we have just discovered (re Sun C++), 'defined __cplusplus' is not
a guarantee that 'true' is defined correctly. So, even in C++ mode,
it may be a win to include . Remember, here we are in a
context where gl_C_BOOL / AC_C_BOOL has not been invoked.

Bruno






Re: bool and C23

2022-09-18 Thread Bruno Haible
Paul Eggert wrote:
> I did notice one glitch (an unnecessary "#undef true" that is always 
> commented out) and a couple of minor opportunities for simplification, 
> and installed the attached update.

OK.

> Use the slightly
> more-elegant ‘!true’ instead of ‘true == 1’; this shouldn’t matter
> in practice

Yes. At least with Sun C++ these two preprocessor expressions are equivalent.

Bruno






Re: bool and C23

2022-09-18 Thread Paul Eggert

On 9/18/22 10:10, Bruno Haible wrote:

   #define true (!false)
works! It evaluates to 1 and is of the right type.


Thanks, that's nicer than the tricky "#define true ((bool) +1)" that I 
was going to suggest.


I did notice one glitch (an unnecessary "#undef true" that is always 
commented out) and a couple of minor opportunities for simplification, 
and installed the attached update.From 154986613fe8d25d086568426b394098a6f2f7aa Mon Sep 17 00:00:00 2001
From: Paul Eggert 
Date: Sun, 18 Sep 2022 11:26:36 -0700
Subject: [PATCH] =?UTF-8?q?stdbool:=20omit=20=E2=80=98#undef=20true?=
 =?UTF-8?q?=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is mostly just simplification.
* m4/c-bool.m4 (gl_C_BOOL): Test all preprocessors when
!HAVE_C_BOOL, not merely __SUNPRO_CC.  Use the slightly
more-elegant ‘!true’ instead of ‘true == 1’; this shouldn’t matter
in practice and if it does matter we want to know about it anyway.
Remove an unnecessary ‘#undef true’ that is simply commented out
by ‘configure’; again, if true is already #defined to be 0 the
system is so messed up we want to know about it anyway.
---
 ChangeLog| 12 
 m4/c-bool.m4 | 16 +++-
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 87c370bd04..77862ed623 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2022-09-18  Paul Eggert  
+
+	stdbool: omit ‘#undef true’
+	This is mostly just simplification.
+	* m4/c-bool.m4 (gl_C_BOOL): Test all preprocessors when
+	!HAVE_C_BOOL, not merely __SUNPRO_CC.  Use the slightly
+	more-elegant ‘!true’ instead of ‘true == 1’; this shouldn’t matter
+	in practice and if it does matter we want to know about it anyway.
+	Remove an unnecessary ‘#undef true’ that is simply commented out
+	by ‘configure’; again, if true is already #defined to be 0 the
+	system is so messed up we want to know about it anyway.
+
 2022-09-18  Bruno Haible  
 
 	stdbool: Ensure that 'true' can be used in the preprocessor.
diff --git a/m4/c-bool.m4 b/m4/c-bool.m4
index 980de611b9..67c2cf2621 100644
--- a/m4/c-bool.m4
+++ b/m4/c-bool.m4
@@ -24,19 +24,17 @@ AC_DEFUN([gl_C_BOOL],
 
   dnl The "zz" puts this toward config.h's end, to avoid potential
   dnl collisions with other definitions.
-  dnl In C++ mode 'bool', 'true', 'false' are keywords and thus we don't need
-  dnl .  But in C mode, we do.
-  dnl Check __bool_true_false_are_defined to avoid re-including .
-  dnl In Sun C++ 5.11 (Solaris Studio 12.2) and older, 'true' as a preprocessor
-  dnl expression evaluates to 0, not 1.  Fix this by overriding 'true'.  Note
-  dnl that the replacement has to be of type 'bool'.
+  dnl If 'bool', 'true' and 'false' do not work, arrange for them to work.
+  dnl In C, this means including  if it is not already included.
+  dnl However, if the preprocessor mistakenly treats 'true' as 0,
+  dnl define it to a bool expression equal to 1; this is needed in
+  dnl Sun C++ 5.11 (Oracle Solaris Studio 12.2, 2010) and older.
   AH_VERBATIM([zzbool],
-[#if !defined HAVE_C_BOOL
+[#ifndef HAVE_C_BOOL
 # if !defined __cplusplus && !defined __bool_true_false_are_defined
 #  include 
 # endif
-# if defined __SUNPRO_CC && true != 1
-#  undef true
+# if !true
 #  define true (!false)
 # endif
 #endif])
-- 
2.37.3



Re: bool and C23

2022-09-18 Thread Paul Eggert

On 9/18/22 06:33, Bruno Haible wrote:

  #include "unitypes.h"
  
+/* Get bool.  */

+#include 


In examples like these would it make sense to do the following instead? 
This would avoid a bit of namespace pollution.


  #if !@HAVE_C_BOOL@ && !defined __cplusplus
   #include 
  #endif



Re: bool and C23

2022-09-18 Thread Bruno Haible
Paul Eggert wrote on 2022-09-10:
> I installed into Gnulib the stdbool patches ...
> 
> After we have more experience with this in Gnulib, we can start thinking 
> about updating Autoconf.

As part of this "gathering experience", I compiled a gnulib testdir with
various compilers on various systems.

No problems seen
  - with GCC,
  - with clang (I tested all versions from clang 3.9 to clang 14),
  - with AIX xlc and xlclang.

But with Sun C++ on Solaris 10 (SOS11, __SUNPRO_CC=0x580 [1]) and
11.3 (solstudio12.2, __SUNPRO_CC=0x5110 [1]) I get a compilation error:

CC -xarch=generic64 -O -DHAVE_CONFIG_H -DEXEEXT=\"\" -I. -I../../gltests -I..   
-DGNULIB_STRICT_CHECKING=1  -DIN_GNULIB_TESTS=1  -I. -I../../gltests  -I.. 
-I../../gltests/..  -I../gllib -I../../gltests/../gllib 
-I/home/haible/prefix-x86_64/include -D_REENTRANT  -g -c -o test-stdbool-c++.o 
../../gltests/test-stdbool-c++.cc
"../../gltests/test-stdbool-c++.cc", line 33: Error: A declaration was expected 
instead of ""error: true is not 1"".
1 Error(s) detected.
*** Error code 1

This compiler defines _BOOL, to indicate that 'bool', 'true', 'false' are
keywords [2]. But in the preprocessor, 'true' evaluates to 0, not 1 !
Although cppreference.com does not clearly state that 'true' and 'false'
must be usable as in preprocessor directives, such a compiler behaviour
will show up as bugs in application programs, when more and more applications
use 'true' and 'false' instead of old-style '1' and '0'. Thus, I think we
should fix this compiler behaviour.

What can the replacement be?

  #define true 1
does not work, because it would be of type 'int' and thus not behave right
w.r.t. overloaded functions, such as
  int func (int);
  int func (bool);

  #define true ((bool) 1)
fixes the type, but is not usable in preprocessor expressions, since casts
are not allowed there.

  #define true (!false)
works! It evaluates to 1 and is of the right type.

Done through the attached patches. The second one should get included into
Autoconf's AC_C_BOOL, when that comes to exist.

[1] https://github.com/cpredef/predef/blob/master/Compilers.md
[2] https://docs.oracle.com/cd/E37069_01/html/E54439/uc-cc-1.html


2022-09-18  Bruno Haible  

stdbool: Ensure that 'true' can be used in the preprocessor.
* m4/c-bool.m4 (gl_C_BOOL): With Sun C++, redefine 'true' if it does not
evaluate to 1 in the preprocessor.

stdbool-c99: Ensure that 'true' can be used in the preprocessor.
* lib/stdbool.in.h (true): Redefine if it does not evaluate to 1 in the
preprocessor.
>From e73f9ba6b3286e4cf570c77cd38f6ceff00653ba Mon Sep 17 00:00:00 2001
From: Bruno Haible 
Date: Sun, 18 Sep 2022 18:45:39 +0200
Subject: [PATCH 1/2] stdbool-c99: Ensure that 'true' can be used in the
 preprocessor.

* lib/stdbool.in.h (true): Redefine if it does not evaluate to 1 in the
preprocessor.
---
 ChangeLog| 6 ++
 lib/stdbool.in.h | 7 +++
 2 files changed, 13 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 9b20b98d4a..3ea944f7d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2022-09-18  Bruno Haible  
+
+	stdbool-c99: Ensure that 'true' can be used in the preprocessor.
+	* lib/stdbool.in.h (true): Redefine if it does not evaluate to 1 in the
+	preprocessor.
+
 2022-09-18  Bruno Haible  
 
 	uni{case,ctype,gbrk,str}/base: Fix installed .h file (regr. 2022-09-10).
diff --git a/lib/stdbool.in.h b/lib/stdbool.in.h
index 36f26560af..834c5f7e78 100644
--- a/lib/stdbool.in.h
+++ b/lib/stdbool.in.h
@@ -109,6 +109,13 @@ typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
 #  define false false
 #  define true true
 # endif
+/* In Sun C++ 5.11 (Solaris Studio 12.2) and older, 'true' as a preprocessor
+   expression evaluates to 0, not 1.  Fix this by overriding 'true'.  Note that
+   the replacement has to be of type 'bool'.  */
+# if defined __SUNPRO_CC && true != 1
+#  undef true
+#  define true (!false)
+# endif
 #else
 # define false 0
 # define true 1
-- 
2.34.1

>From 16a1b6af1e618b22d621edc6054d4225cbcb98a1 Mon Sep 17 00:00:00 2001
From: Bruno Haible 
Date: Sun, 18 Sep 2022 18:47:22 +0200
Subject: [PATCH 2/2] stdbool: Ensure that 'true' can be used in the
 preprocessor.

* m4/c-bool.m4 (gl_C_BOOL): With Sun C++, redefine 'true' if it does not
evaluate to 1 in the preprocessor.
---
 ChangeLog|  4 
 m4/c-bool.m4 | 20 +++-
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3ea944f7d2..87c370bd04 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2022-09-18  Bruno Haible  
 
+	stdbool: Ensure that 'true' can be used in the preprocessor.
+	* m4/c-bool.m4 (gl_C_BOOL): With Sun C++, redefine 'true' if it does not
+	evaluate to 1 in the preprocessor.
+
 	stdbool-c99: Ensure that 'true' can be used in the preprocessor.
 	* lib/stdbool.in.h (true): Redefine if it does not evaluate to 1 in the
 	preprocessor.
diff --git a/m4/c-bool.m4 b/m4/c-bool.m4

Re: bool and C23

2022-09-18 Thread Bruno Haible
Paul Eggert wrote:
> I installed into Gnulib the stdbool patches ...

The changes to the files
  lib/unicase.in.h
  lib/unictype.in.h
  lib/unigbrk.in.h
  lib/unistr.in.h
are not good, because these files ultimately get installed as public header
files:
  1. They get copied to libunistring, with  replaced with
 .
  2. They get installed by "make install".
  3. The user uses them with a compiler that maybe is only C99 compliant.

I did not see this during the review. But the continuous integration caught it.


2022-09-18  Bruno Haible  

uni{case,ctype,gbrk,str}/base: Fix installed .h file (regr. 2022-09-10).
* lib/unicase.in.h: Do include .
* lib/unictype.in.h: Likewise.
* lib/unigbrk.in.h: Likewise.
* lib/unistr.in.h: Likewise.

diff --git a/lib/unicase.in.h b/lib/unicase.in.h
index 5317cd3dd8..9bcc79edd8 100644
--- a/lib/unicase.in.h
+++ b/lib/unicase.in.h
@@ -27,6 +27,9 @@
 
 #include "unitypes.h"
 
+/* Get bool.  */
+#include 
+
 /* Get size_t.  */
 #include 
 
diff --git a/lib/unictype.in.h b/lib/unictype.in.h
index de6a191d87..2f0efefca8 100644
--- a/lib/unictype.in.h
+++ b/lib/unictype.in.h
@@ -19,6 +19,9 @@
 
 #include "unitypes.h"
 
+/* Get bool.  */
+#include 
+
 /* Get size_t.  */
 #include 
 
diff --git a/lib/unigbrk.in.h b/lib/unigbrk.in.h
index 7fbc2a0d57..f1b60e17b9 100644
--- a/lib/unigbrk.in.h
+++ b/lib/unigbrk.in.h
@@ -26,6 +26,9 @@
 #ifndef _UNIGBRK_H
 #define _UNIGBRK_H
 
+/* Get bool.  */
+#include 
+
 /* Get size_t. */
 #include 
 
diff --git a/lib/unistr.in.h b/lib/unistr.in.h
index 40c7929575..4d48751558 100644
--- a/lib/unistr.in.h
+++ b/lib/unistr.in.h
@@ -19,6 +19,9 @@
 
 #include "unitypes.h"
 
+/* Get bool.  */
+#include 
+
 /* Get size_t, ptrdiff_t.  */
 #include 
 






Re: bool and C23

2022-09-10 Thread Bruno Haible
> I'm starting portability tests of it now...

Result of portability testing: All is fine (no compilation error) on
  - glibc (Ubuntu 22.04, Debian 11.1, CentOS 7)
  - musl libc
  - GNU/Hurd
  - macOS
  - FreeBSD 11, 13.1
  - NetBSD 9.0
  - OpenBSD 7.0
  - AIX xlc and xlclang
  - Solaris 10
  - Solaris 11.4
  - Solaris OpenIndiana
  - Solaris OmniOS
  - Cygwin 2.9
  - mingw, msvc

Bruno






Re: bool and C23

2022-09-10 Thread Bruno Haible
I did:
> 2022-09-10  Bruno Haible  
> 
>   Reorganize C++ tests for stdbool and stdbool-c99.
>   * tests/test-stdbool-c++.cc: Don't include  if TEST_STDBOOL_H
>   is not defined. Add a couple of simple tests, from test-stdbool.c.

Oops. This produces a compilation error with MSVC14:

source='../../gltests/test-stdbool-c++.cc' object='test-stdbool-c++.obj' 
libtool=no \
DEPDIR=.deps depmode=msvc7 /bin/sh ../../build-aux/depcomp \
/home/bruno/msvc/compile cl -nologo -DHAVE_CONFIG_H -DEXEEXT=\".exe\" -I. 
-I../../gltests -I..  -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. 
-I../../gltests -I.. -I../../gltests/.. -I../gllib -I../../gltests/../gllib 
-D_WIN32_WINNT=_WIN32_WINNT_WINXP -I/usr/local/msvc32/include  -MD -c -o 
test-stdbool-c++.obj `cygpath -w '../../gltests/test-stdbool-c++.cc'`
test-stdbool-c++.cc
C:\cygwin64\home\bruno\testdir-all\gltests\test-stdbool-c++.cc(36): error 
C2380: type(s) preceding 's' (constructor with return type, or illegal 
redefinition of current class-name?)
C:\cygwin64\home\bruno\testdir-all\gltests\test-stdbool-c++.cc(36): error 
C2460: 's::': uses 's', which is being defined
C:\cygwin64\home\bruno\testdir-all\gltests\test-stdbool-c++.cc(36): note: see 
declaration of 's'
make[4]: *** [Makefile:23346: test-stdbool-c++.obj] Error 2

This patch fixes it:


2022-09-10  Bruno Haible  

stdbool C++ tests: Fix compilation error with MSVC14 (regr. from today).
* tests/test-stdbool-c++.cc (s): Choose field names that are not type
names.

diff --git a/tests/test-stdbool-c++.cc b/tests/test-stdbool-c++.cc
index 8e208dfe23..98358f1ef8 100644
--- a/tests/test-stdbool-c++.cc
+++ b/tests/test-stdbool-c++.cc
@@ -33,7 +33,7 @@
  "error: true is not 1"
 #endif
 
-struct s { bool s: 1; bool t; } s;
+struct s { bool u: 1; bool v; } s;
 
 char a[true == 1 ? 1 : -1];
 char b[false == 0 ? 1 : -1];






Re: bool and C23

2022-09-10 Thread Bruno Haible
Paul Eggert wrote:
> Thanks for catching that doc bug. I installed into Gnulib the stdbool 
> patches with a fix for that

The C++ tests are strangely organized now. I'm committing this patch, so
that both 'stdbool' and 'stdbool-c99' have their respective C++ tests.


2022-09-10  Bruno Haible  

Reorganize C++ tests for stdbool and stdbool-c99.
* tests/test-stdbool-c++.cc: Don't include  if TEST_STDBOOL_H
is not defined. Add a couple of simple tests, from test-stdbool.c.
* tests/test-stdbool-c99-c++.cc: New file.
* modules/stdbool-c99-c++-tests: New file, based on
modules/stdbool-c++-tests.
* modules/stdbool-c99-tests (Depends-on): Add stdbool-c99-c++-tests.
Remove stdbool-c++-tests.
* modules/stdbool-tests (Depends-on): Add stdbool-c++-tests.

diff --git a/modules/stdbool-c99-c++-tests b/modules/stdbool-c99-c++-tests
new file mode 100644
index 00..073ef893c4
--- /dev/null
+++ b/modules/stdbool-c99-c++-tests
@@ -0,0 +1,19 @@
+Files:
+tests/test-stdbool-c99-c++.cc
+tests/test-stdbool-c++.cc
+tests/test-stdbool-c++2.cc
+
+Status:
+c++-test
+
+Depends-on:
+ansi-c++-opt
+
+configure.ac:
+
+Makefile.am:
+if ANSICXX
+TESTS += test-stdbool-c99-c++
+check_PROGRAMS += test-stdbool-c99-c++
+test_stdbool_c99_c___SOURCES = test-stdbool-c99-c++.cc test-stdbool-c++2.cc
+endif
diff --git a/modules/stdbool-c99-tests b/modules/stdbool-c99-tests
index 3ca0ddb217..e507f9493a 100644
--- a/modules/stdbool-c99-tests
+++ b/modules/stdbool-c99-tests
@@ -1,9 +1,9 @@
 Files:
-tests/test-stdbool.c
 tests/test-stdbool-c99.c
+tests/test-stdbool.c
 
 Depends-on:
-stdbool-c++-tests
+stdbool-c99-c++-tests
 
 configure.ac:
 
diff --git a/modules/stdbool-tests b/modules/stdbool-tests
index 6905dfbedc..0f875fbeed 100644
--- a/modules/stdbool-tests
+++ b/modules/stdbool-tests
@@ -2,6 +2,7 @@ Files:
 tests/test-stdbool.c
 
 Depends-on:
+stdbool-c++-tests
 
 configure.ac:
 
diff --git a/tests/test-stdbool-c++.cc b/tests/test-stdbool-c++.cc
index ae4f80b00f..8e208dfe23 100644
--- a/tests/test-stdbool-c++.cc
+++ b/tests/test-stdbool-c++.cc
@@ -19,7 +19,26 @@
 #define GNULIB_NAMESPACE gnulib
 #include 
 
-#include 
+#ifdef TEST_STDBOOL_H
+# include 
+#endif
+
+
+/* These tests are a subset of the C language tests in test-stdbool.c.  */
+
+#if false
+ "error: false is not 0"
+#endif
+#if true != 1
+ "error: true is not 1"
+#endif
+
+struct s { bool s: 1; bool t; } s;
+
+char a[true == 1 ? 1 : -1];
+char b[false == 0 ? 1 : -1];
+char c[(unsigned char) true == 1 ? 1 : -1];
+char d[(unsigned char) false == 0 ? 1 : -1];
 
 
 int
diff --git a/tests/test-stdbool-c99-c++.cc b/tests/test-stdbool-c99-c++.cc
new file mode 100644
index 00..eec9e3b980
--- /dev/null
+++ b/tests/test-stdbool-c99-c++.cc
@@ -0,0 +1,2 @@
+#define TEST_STDBOOL_H
+#include "test-stdbool-c++.cc"






Re: bool and C23

2022-09-10 Thread Paul Eggert
Thanks for catching that doc bug. I installed into Gnulib the stdbool 
patches with a fix for that, and also with one small change to 
tests/test-stdbool.c so that it depends on HAVE_C_BOOL instead of 
__STDC_VERSION__.


After we have more experience with this in Gnulib, we can start thinking 
about updating Autoconf.





Re: bool and C23

2022-09-10 Thread Bruno Haible
On Samstag, 10. September 2022 06:43:06 CEST Paul Eggert wrote:
> On 9/9/22 04:14, Bruno Haible wrote:
> >I would suggest to keep*one*  module, and keep it named 'stdbool'.
> >Its meaning will be "provide bool, true, false according to the 
> > standards".
> >It can invoke AC_HEADER_STDBOOL and AC_C_BOOL under the hood.
> >The important point is that the migration from older to newer ISO 
> > standard
> >versions is transparent (not troublesome) for the Gnulib user.
> 
> OK, attached is a revised Gnulib proposed patchset that does that. It 
> changes stdbool to assume C99 (since that should be safe now), which 
> means stdbool no longer needs to use AC_HEADER_STDBOOL. It moves the old 
> stdbool stuff into a new module 'stdbool-c99' that's already marked 
> obsolescent, in case someone still needs to port to pre-C99 compilers 
> for some reason.

The documentation has a mistake:

$ make gnulib.html 
date -u -r gnulib-readme.texi +"@set UPDATED %F %T" > updated-stamp
env LANG= LC_MESSAGES= LC_ALL= LANGUAGE= makeinfo --no-split 
--reference-limit=2000 --html -o gnulib.html gnulib.texi
gnulib-readme.texi:370: @xref reference to nonexistent node `c-bool'
make: *** [Makefile:24: gnulib.html] Error 1

Fix: s/c-bool/stdbool.h/g

Bruno






Re: bool and C23

2022-09-10 Thread Bruno Haible
Paul Eggert wrote:
> OK, attached is a revised Gnulib proposed patchset that does that.

Looks all good to me. Great work, Paul!

I'm starting portability tests of it now...

Bruno






Re: bool and C23

2022-09-09 Thread Bruno Haible
Paul Eggert wrote:
> To help move ahead on this, I propose the attached patches to Gnulib. 
> They use a simpler version of the Autoconf macro, named gl_C_BOOL to 
> avoid collision with any future improvements to Autoconf. My hope is 
> that gl_C_BOOL can be renamed to AC_C_BOOL, or something like that. The 
> idea is that AC_C_BOOL assumes C99 or later; if you want to port to 
> pre-C99 (which pretty much nobody does these days), you can use the 
> Gnulib stdbool module.
> 
> The first patch adds a Gnulib module c-bool, which acts like the 
> existing Gnulib module stdbool except it supports C23-style bool (no 
> include file) instead of C99-style bool.

I have two objections against this patch:

* A technical one: In
  <https://lists.gnu.org/archive/html/autoconf/2022-08/msg9.html>
  Zack and I agreed that the AH_VERBATIM code should be of the form
 #ifndef __cplusplus
 ...
 #endif

  Also, in <https://lists.gnu.org/archive/html/autoconf/2022-08/msg1.html>
  I suggested to ensure that the '#include ' goes to the end of
  config.h. IIUC, a way to do this is to replace
AH_VERBATIM([bool], [...code...])
  with
AH_VERBATIM([zzbool], [...code...])

* A major design objection: While from the Autoconf perspective, it is natural
  to have two macros AC_HEADER_STDBOOL and AC_C_BOOL, from the Gnulib
  perspective it is not good to have two modules 'stdbool' and 'c-bool'.

  The problems that I'm seeing are:

- How do we explain it to the Gnulib users?
  You have written this in the doc:
"If your code needs to be portable to pre-C99 platforms,
 it needs to also use the @code{stdbool} module."
  So the user needs to think about whether to use 'stdbool',
  or 'c-bool', or both (!).

- So far, we have two different modules when there are two
  conflicting standards. For example, getopt-posix vs. getopt-gnu.
  But it is easy to explain: "If you want getopt to behave like
  specified in POSIX, use getopt-posix. If you want it to behave
  like glibc, use getopt-gnu." But different modules for different
  versions of the same standard? We have avoided this so far.

- Different modules for different ISO C versions also means that
  every package would need to migrate at some point. Namely, swap
  'stdbool' against 'c-bool' in the autogen.sh script / bootstrap.conf /
  local gnulib module dependencies. It would be a disgrace to force
  this on our users.

- We would need to make sure that these two modules don't interfere.
  For example, if there are two gnulib-tool invocations, like in
  
https://www.gnu.org/software/gnulib/manual/html_node/Multiple-instances.html ,
  e.g. 'c-bool' used by a library and 'stdbool' by the program,
  we would need to ensure that things go well.

  I would suggest to keep *one* module, and keep it named 'stdbool'.
  Its meaning will be "provide bool, true, false according to the standards".
  It can invoke AC_HEADER_STDBOOL and AC_C_BOOL under the hood.
  The important point is that the migration from older to newer ISO standard
  versions is transparent (not troublesome) for the Gnulib user.

> The second patch is mostly mechanical: it changes the other Gnulib 
> modules to prefer c-bool to stdbool.

Once this patch is reduced to modifying only lib/ and tests/ — no changes to
modules/ —, I volunteer to test it
  a) on various existing platforms,
  b) on clang 15, which has "false and true first-class language features"
 (see https://releases.llvm.org/15.0.0/tools/clang/docs/ReleaseNotes.html ).

Bruno






Re: bool and C23

2022-08-22 Thread Bruno Haible
Zack Weinberg wrote:
> >   * In C++ mode,
> […]
> > [cstdbool may include] various OS stuff, and should therefore be
> > avoided when possible. Since a compilation unit cannot be ISO C 23
> > and C++ at the same time, it is easy to achieve: Wrap the new
> > config.h additions in
> >   #ifndef __cplusplus
> >   ...
> >   #endif
> 
> Yes, this was already my plan.

Good.

> Do you think it’s worth mentioning
> this issue in Autoconf’s documentation (it already says “stdbool.h
> should not be included from C++” but not why).

Not worth mentioning. The sample code that you have included for the
no-autoheader case already avoids include  in C++ mode.
There's no need to go beyond that.

> >   * In C mode: […] it is OK to #include , since it
> > does not include header files with function declarations, only
> > header files with macro definitions.
> 
> We _could_ still get errors from -Wredundant-decls -Werror or
> equivalent, but I think that’s probably okay to live with.

I agree. Generally options like -Wredundant-decls may spew many more warnings
on non-glibc systems than on glibc systems.

> >   - Determine GL_GENERATE_STDBOOL_H as in gnulib/m4/stdbool.m4,
> 
> It looks like the only thing gl_STDBOOL_H does, that my current draft
> of AC_C_BOOL doesn’t do, is refuse to use an existing  from
> C++ on Solaris.  Given that my current draft _never_ uses 
> from C++, I think we can just scrap that part.

I agree. This part of gnulib/m4/stdbool.m4 has the purpose of providing
an  that works both in C and C++ mode with that particular
Solaris 10. Your goal is a different one: provide a config.h snippet
that defines 'bool', 'false', 'true' according to the standards. You can
therefore ignore that Solaris 10 cc problem.

> Looking at the existing Gnulib code, though, suggests another possible
> reason why we might need the fallback code to `signed char` (or
> Gnulib’s enumeration): allegedly C99-compliant compilers whose Boolean
> implementation is buggy.  My AC_C_BOOL preserves the existing test for
> a buggy Boolean type, from AC_CHECK_HEADER_STDBOOL, so, if we do as
> Paul suggests and make configure error out when there’s no usable
> Boolean, that will hard reject those compilers as well.  I’m fine with
> that.  Are you fine with that?

Given that these compilers are more than 15 years old, I'm fine with it.

Bruno






Re: bool and C23

2022-08-22 Thread Paul Eggert

On 8/22/22 15:58, Zack Weinberg wrote:

There isn’t a bool module right now, are you proposing to add one?


Yes.



I want to get to where _no_ Gnulib module is required for
bool; AC_C_BOOL by itself should be enough.


Yes, that's the long term goal. But in the shorter term Gnulib-using 
code can't yet require Autoconf 2.72+ so it will need to use a new 
module in Gnulib (maybe it should be called c-bool instead of bool). 
This module will merely say "You should use AC_C_BOOL" and will contain 
an implementation of AC_C_BOOL for use in Autoconf 2.71-. The substitute 
implementation should be a copy of what's in Autoconf 2.72.




Sure, but why can't the non-autoheader case define bool, false, and true
instead of defining C_BOOL_DEFINITION? That will keep the code simpler
for these people.

I don’t understand what you are suggesting here.


My idea is that for the non-autoheader case, where #defines are 
implemented via -D options given to the compiler, Autoconf arranges to 
pass '-D bool=_Bool -D true=1 -D false=0' to compilers that don't have 
either bool  or stdbool.h. That way, user code need not ever #define 
bool or true or false; non-autoheader user code can say just this:


  #if defined C_NEED_STDBOOL_H && !defined __cpluplus
  # include 
  #endif

and autoheader user code (the typical case) need not say anything other 
than the usual "#include ".


Admittedly this is only a minor improvement, as I think pretty much 
everybody who uses Autoconf and C also uses Autoheader and config.h.




Looking at the existing Gnulib code, though, suggests another possible
reason why we might need the fallback code to `signed char` (or
Gnulib’s enumeration): allegedly C99-compliant compilers whose Boolean
implementation is buggy.  My AC_C_BOOL preserves the existing test for
a buggy Boolean type, from AC_CHECK_HEADER_STDBOOL, so, if we do as
Paul suggests and make configure error out when there’s no usable
Boolean, that will hard reject those compilers as well.  I’m fine with
that.  Are you fine with that?


That should be OK as far as I know; Bruno may have further thoughts.

One other issue comes to mind: bool bitfield in structs. Although 
Autoconf currently tests that these compile, it doesn't test that bool 
bitfields of width 1 have the same memory layout as unsigned int 
bitfields of width 1. Emacs has this issue and already addresses it 
(look for "bool_bf" in the Emacs source). I don't think Autoconf needs 
to worry about bool bitfield implementation, as (a) the issue comes up 
pretty rarely and (b) neither current Autoconf nor current Gnulib 
addresses or solves the issue. However, the issue might be worth 
documenting in Autoconf.





Re: bool and C23

2022-08-22 Thread Zack Weinberg
Please note consolidated reply to both Paul and Bruno.

On Sun, Aug 21, 2022, at 5:25 PM, Paul Eggert wrote:
> On 8/21/22 07:59, Zack Weinberg wrote:
>> Paul Eggert:
>>> Zack Weinberg:
 @defmac AC_C_BOOL (@ovar{if-required})
>>>
>>> How about if we omit the IF-REQUIRED parameter?
>>
>> Taking out the "optional" mode will mean that regenerating the the
>> configure script of a package that uses the stdbool module, with
>> Autoconf 2.72, will quietly bump its minimum C compiler requirement
>> to C99.  Are we okay with that?
>
> Yes, I think so. I believe Gawk was the last Gnulib-using project that
> wanted portability to C89, and Gawk dropped that requirement a few years
> ago.

OK, I’ll proceed on the assumption this is fine unless we hear
otherwise, and I’ll make sure both Autoconf NEWS and the manual make
the implications clear.

> More precisely, the idea is that in
> 
> we'd change ", assuming the stdbool module is used. See
> stdbool.h." to something like "bool, true, and false (perhaps via
> ); see the bool module." The stdbool module would become
> obsolescent.

There isn’t a bool module right now, are you proposing to add one?
To be clear, I want to get to where _no_ Gnulib module is required for
bool; AC_C_BOOL by itself should be enough.

>> I think we still need C_BOOL_DEFINITION even if we make that change,
>> because apparently there exist(ed?) compilers that provide _Bool but
>> not stdbool.h.
>
> Apparently OS X had that problem as recently as 2018
>  so I guess such a
> workaround would be helpful for some apps. I'm not sure Gnulib will need
> it though.

Again, AC_C_BOOL by itself is supposed to be all you need (in the
common case where autoheader is in use).

> Sure, but why can't the non-autoheader case define bool, false, and true
> instead of defining C_BOOL_DEFINITION? That will keep the code simpler
> for these people.

I don’t understand what you are suggesting here.

> one possibility
> is that 'true' is defined by the system's  which says
> "#define true (!0)". The C standard allows this.

I don’t think it does? N1570 (C11-in-all-but-name) 7.18p3 says “`true`
expands to the integer constant 1” and “`false` expands to the integer
constant 0.”  No leeway at all there.  I don’t have my copy of C99 on
this computer, but I doubt it says anything different.

>> I meant to ask you why the Gnulib stdbool module uses "signed char"
>> as the fallback underlying type for bool.
>
> I don't recall exactly but I can imagine a couple of good reasons.
> First, it makes it more likely you'll get a type clash if you mistakenly
> confuse int for bool in function signature compiled by an older
> compiler. Second, it makes it less likely that there would be a clash if
> some code is compiled with a compiler that has a working bool of size 1
> (the most common implementation I think), whereas other code is compiled
> with Gnulib's substitute for bool.

Hm, OK, I guess.  I’m still worried about undesirable integer
promotions but I guess those happen with _Bool used in arithmetic
expressions too (since it has the lowest possible integer conversion
rank).

On Sun, Aug 21, 2022, at 5:34 PM, Bruno Haible wrote:
>   * In C++ mode,
[…]
> [cstdbool may include] various OS stuff, and should therefore be
> avoided when possible. Since a compilation unit cannot be ISO C 23
> and C++ at the same time, it is easy to achieve: Wrap the new
> config.h additions in
>   #ifndef __cplusplus
>   ...
>   #endif

Yes, this was already my plan.  Do you think it’s worth mentioning
this issue in Autoconf’s documentation (it already says “stdbool.h
should not be included from C++” but not why).

>   * In C mode: […] it is OK to #include , since it
> does not include header files with function declarations, only
> header files with macro definitions.

We _could_ still get errors from -Wredundant-decls -Werror or
equivalent, but I think that’s probably okay to live with.

>   - Determine GL_GENERATE_STDBOOL_H as in gnulib/m4/stdbool.m4,

It looks like the only thing gl_STDBOOL_H does, that my current draft
of AC_C_BOOL doesn’t do, is refuse to use an existing  from
C++ on Solaris.  Given that my current draft _never_ uses 
from C++, I think we can just scrap that part.

Looking at the existing Gnulib code, though, suggests another possible
reason why we might need the fallback code to `signed char` (or
Gnulib’s enumeration): allegedly C99-compliant compilers whose Boolean
implementation is buggy.  My AC_C_BOOL preserves the existing test for
a buggy Boolean type, from AC_CHECK_HEADER_STDBOOL, so, if we do as
Paul suggests and make configure error out when there’s no usable
Boolean, that will hard reject those compilers as well.  I’m fine with
that.  Are you fine with that?

zw



Re: bool and C23

2022-08-21 Thread Tim Rice
On Sun, 21 Aug 2022, Bruno Haible wrote:

> 
> This is the situation on the various platforms:
[snip]
>   * In C mode:  does
> 
> AIX: #include , defines only macros
> FreeBSD: self-contained
> Haiku: self-contained
> HP-UX: #include , defines only macros
> macOS: self-contained
> mingw: self-contained
> Minix: self-contained
> musl: self-contained
> NetBSD: self-contained
> OpenBSD: self-contained
> Solaris 10: #include  -> #include , 
> #include , defines only macros
> Solaris 11: #include 

UnixWare: self-contained

[snip]

-- 
Tim RiceMultitalents
t...@multitalents.net





Re: bool and C23

2022-08-21 Thread Bruno Haible
On Monday I wrote:
> > to exclude other problems, we need to check it on a platform-by-platform
> > basis.

This is the situation on the various platforms:

  * In C++ mode,
- either the C  is used,
- or a C++  exists that
#include 
- or a C++  exists that #include <__config>,
  and the latter does:
Linux: #include 
FreeBSD: #include , #include 
NetBSD: #include 
Windows store apps: #include 
Solaris: #include 
else: #include 

The latter includes various OS stuff, and should therefore be
avoided when possible. Since a compilation unit cannot be ISO C 23
and C++ at the same time, it is easy to achieve: Wrap the new
config.h additions in
  #ifndef __cplusplus
  ...
  #endif

  * In C mode:  does

AIX: #include , defines only macros
FreeBSD: self-contained
Haiku: self-contained
HP-UX: #include , defines only macros
macOS: self-contained
mingw: self-contained
Minix: self-contained
musl: self-contained
NetBSD: self-contained
OpenBSD: self-contained
Solaris 10: #include  -> #include , 
#include , defines only macros
Solaris 11: #include 

So, in this case, it is OK to #include , since it
does not include header files with function declarations, only
header files with macro definitions.

Paul Eggert wrote:
> In the long run this problem will vanish, as in the long run config.h 
> will do nothing (that's all that's needed for C23 and C++).

I agree.

> In the shorter run I think we'll be OK for C17 and earlier if we include 
>  on platforms where bool+true+false don't work out of the 
> box, because (unlike some other .h files) stdbool.h doesn't tend to 
> cause conflicts.

Yes. Based on the analysis above, this should work.

So, IIUC, what we should do, is:

  - Determine GL_GENERATE_STDBOOL_H as in gnulib/m4/stdbool.m4,
  - If it is true, add to  the lines

  #ifndef __cplusplus
  ... current contents of gnulib/m4/stdbool.in.h ...
  #endif

  - Otherwise, test "$ac_cv_header_stdbool_h".
  - If it is != 'yes', add to  the lines

  #ifndef __cplusplus
  #include 
  #endif

Bruno






Re: bool and C23

2022-08-15 Thread Paul Eggert

On 8/15/22 14:39, Bruno Haible wrote:


to exclude other problems, we need to check it on a platform-by-platform
basis.


In the long run this problem will vanish, as in the long run config.h 
will do nothing (that's all that's needed for C23 and C++).


In the shorter run I think we'll be OK for C17 and earlier if we include 
 on platforms where bool+true+false don't work out of the 
box, because (unlike some other .h files) stdbool.h doesn't tend to 
cause conflicts.


If I'm wrong, I expect we'll be able to fix things on a 
platform-by-platform basis. In the worst case I suppose we could put 
something like this into config.h:


  #ifndef HAVE_BUILTIN_BOOL_TRUE_FALSE
  # ifndef HAVE__BOOL
  #  define _Bool signed char
  # endif
  # define bool _Bool
  # define true 1
  # define false 0
  #endif

This doesn't #include any files, and conforms to C99 thru C17 even if 
you #include  later. However, I hope we needn't go to this 
extreme as I expect it would cause some false alarms about 
multiply-defined macros.




Re: bool and C23

2022-08-15 Thread Bruno Haible
Paul Eggert wrote:
> I installed the attached patch into Gnulib, reflecting a patch I 
> recently installed into Autoconf 
> .
> 
> I think we need a new Autoconf macro that obsoletes AC_HEADER_STDBOOL 
> and AC_CHECK_HEADER_STDBOOL. This new macro should arrange for 'bool', 
> 'true' and 'false' to work, without programs having to include 
> stdbool.h. For C23 and C++ the new macro should do nothing. For C99 
> through C17 it should include  in config.h. For pre-C99 it 
> should #define bool, true, and false in config.h.

The requirement "For C99 through C17 it should include  in config.h"
is a problem. In our experience, including OS headers from config.h leads
to issues, namely:
  - other definitions in config.h may not work if OS headers have already been
included,
  - some packages have multiple config.h, and the second one may not work
once the first one has included OS headers,
  - the programmer may have assumed that '#include ' did not include
anything from the OS.

The first of these problems may be resolved by ensuring that the
'#include ' goes to the end of config.h, not to a random place in
the middle.

But to exclude other problems, we need to check it on a platform-by-platform
basis.

As a first step towards this goal, let's "handle" BeOS by dropping the BeOS
support.


2022-08-15  Bruno Haible  

stdbool: Drop old BeOS support that gets in the way of ISO C 23 support.
* lib/stdbool.in.h: Don't include .

diff --git a/lib/stdbool.in.h b/lib/stdbool.in.h
index 03840f10fc..2fa46724b2 100644
--- a/lib/stdbool.in.h
+++ b/lib/stdbool.in.h
@@ -58,27 +58,11 @@
 
 /* 7.16. Boolean type and values */
 
-/* BeOS  already #defines false 0, true 1.  We use the same
-   definitions below, but temporarily we have to #undef them.  */
-#if defined __BEOS__ && !defined __HAIKU__
-# include  /* defines bool but not _Bool */
-# undef false
-# undef true
-#endif
-
 #ifdef __cplusplus
 # define _Bool bool
 # define bool bool
 #else
-# if defined __BEOS__ && !defined __HAIKU__
-  /* A compiler known to have 'bool'.  */
-  /* If the compiler already has both 'bool' and '_Bool', we can assume they
- are the same types.  */
-#  if !@HAVE__BOOL@
-typedef bool _Bool;
-#  endif
-# else
-#  if !defined __GNUC__
+# if !defined __GNUC__
/* If @HAVE__BOOL@:
 Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when
 the built-in _Bool type is used.  See
@@ -98,10 +82,10 @@ typedef bool _Bool;
   "Invalid enumerator. (badenum)" with HP-UX cc on Tru64.
 The only benefit of the enum, debuggability, is not important
 with these compilers.  So use 'signed char' and no enum.  */
-#   define _Bool signed char
-#  else
+#  define _Bool signed char
+# else
/* With this compiler, trust the _Bool type if the compiler has it.  */
-#   if !@HAVE__BOOL@
+#  if !@HAVE__BOOL@
/* For the sake of symbolic names in gdb, define true and false as
   enum constants, not only as macros.
   It is tempting to write
@@ -112,7 +96,6 @@ typedef bool _Bool;
   (see ISO C 99 6.3.1.1.(2)).  So add a negative value to the
   enum; this ensures that '_Bool' promotes to 'int'.  */
 typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
-#   endif
 #  endif
 # endif
 # define bool _Bool






bool and C23

2022-08-13 Thread Paul Eggert
I installed the attached patch into Gnulib, reflecting a patch I 
recently installed into Autoconf 
.


I think we need a new Autoconf macro that obsoletes AC_HEADER_STDBOOL 
and AC_CHECK_HEADER_STDBOOL. This new macro should arrange for 'bool', 
'true' and 'false' to work, without programs having to include 
stdbool.h. For C23 and C++ the new macro should do nothing. For C99 
through C17 it should include  in config.h. For pre-C99 it 
should #define bool, true, and false in config.h.


Eventually Gnulib and other code can stop using AC_*HEADER_CHECKBOOL and 
stop including .


I'm thinking of calling the new macro AC_C_BOOL.  Gnulib can have a new 
c-bool module that implements AC_C_BOOL for platforms running older 
Autoconf.


Comments?From f960bc91cd325cee7e1262944ca6114bfd4d1c1f Mon Sep 17 00:00:00 2001
From: Paul Eggert 
Date: Sat, 13 Aug 2022 20:00:02 -0700
Subject: [PATCH] stdbool: port to C23
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* m4/stdbool.m4 (AC_CHECK_HEADER_STDBOOL): Copy from bleeding-edge
Autoconf.  Don’t define if Autoconf 2.72 or later.
* tests/test-stdbool.c (bool, false, true)
(__bool_true_false_are_defined): Do not require these to be
defined.  C23 still requires __bool_true_false_are_defined but
marks it as obsolescent, and it’s no longer worth testing.
(WORKING_BOOL): New macro, which also tests __STDC_VERSION__.
Use it in tests for working bool.
Test for bool instead of for _Bool, which C23 says is obsolescent.
---
 ChangeLog|  13 ++
 m4/stdbool.m4| 105 ++-
 tests/test-stdbool.c |  41 -
 3 files changed, 84 insertions(+), 75 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index e0bf24fc90..eecf44ba01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2022-08-13  Paul Eggert  
+
+	stdbool: port to C23
+	* m4/stdbool.m4 (AC_CHECK_HEADER_STDBOOL): Copy from bleeding-edge
+	Autoconf.  Don’t define if Autoconf 2.72 or later.
+	* tests/test-stdbool.c (bool, false, true)
+	(__bool_true_false_are_defined): Do not require these to be
+	defined.  C23 still requires __bool_true_false_are_defined but
+	marks it as obsolescent, and it’s no longer worth testing.
+	(WORKING_BOOL): New macro, which also tests __STDC_VERSION__.
+	Use it in tests for working bool.
+	Test for bool instead of for _Bool, which C23 says is obsolescent.
+
 2022-08-13  Bruno Haible  
 
 	gnulib-tool.py: Fix some code generation details.
diff --git a/m4/stdbool.m4 b/m4/stdbool.m4
index 3e6c400546..c67908aa87 100644
--- a/m4/stdbool.m4
+++ b/m4/stdbool.m4
@@ -43,75 +43,76 @@ AC_DEFUN([gl_STDBOOL_H],
   AC_SUBST([HAVE__BOOL])
 ])
 
-# This version of the macro is needed in autoconf <= 2.68.
+m4_version_prereq([2.72], [], [
 
 AC_DEFUN([AC_CHECK_HEADER_STDBOOL],
-  [AC_CACHE_CHECK([for stdbool.h that conforms to C99],
+  [AC_CHECK_TYPES([_Bool])
+   AC_CACHE_CHECK([for stdbool.h that conforms to C99 or later],
  [ac_cv_header_stdbool_h],
  [AC_COMPILE_IFELSE(
 [AC_LANG_PROGRAM(
-   [[
- #include 
-
- #ifdef __cplusplus
-  typedef bool Bool;
- #else
-  typedef _Bool Bool;
-  #ifndef bool
-   "error: bool is not defined"
-  #endif
-  #ifndef false
-   "error: false is not defined"
-  #endif
-  #if false
-   "error: false is not 0"
-  #endif
-  #ifndef true
-   "error: true is not defined"
-  #endif
-  #if true != 1
-   "error: true is not 1"
-  #endif
+   [[#include 
+
+ /* "true" and "false" should be usable in #if expressions and
+integer constant expressions, and "bool" should be a valid
+type name.
+
+Although C 1999 requires bool, true, and false to be macros,
+C 2023 and C++ 2011 overrule that, so do not test for that.
+Although C 1999 requires __bool_true_false_are_defined and
+_Bool, C 2023 says they are obsolescent, so do not require
+them.  */
+
+ #if !true
+   #error "'true' is not true"
+ #endif
+ #if true != 1
+   #error "'true' is not equal to 1"
  #endif
+ char b[true == 1 ? 1 : -1];
+ char c[true];
 
- #ifndef __bool_true_false_are_defined
-  "error: __bool_true_false_are_defined is not defined"
+ #if false
+   #error "'false' is not false"
+ #endif
+ #if false != 0
+   #error "'false' is not equal to 0"
  #endif
+ char d[false == 0 ? 1 : -1];
+
+ enum { e = false, f = true, g