You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
-#ifndef _GL_STDCKDINT_H
-#define _GL_STDCKDINT_H
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
-#include "intprops-internal.h"
+#ifndef _@GUARD_PREFIX@_STDCKDINT_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if defined __cplusplus ? @HAVE_CXX_STDCKDINT_H@ : @HAVE_C_STDCKDINT_H@
+# @INCLUDE_NEXT@ @NEXT_STDCKDINT_H@
+#endif
+
+#ifndef _@GUARD_PREFIX@_STDCKDINT_H
+#define _@GUARD_PREFIX@_STDCKDINT_H
+
+/* Do nothing but include the system header if it works properly. */
+# if defined __cplusplus ? !@HAVE_WORKING_CXX_STDCKDINT_H@ : !@HAVE_WORKING_C_STDCKDINT_H@
+
+/* Avoid redefining macros. */
+# undef ckd_add
+# undef ckd_sub
+# undef ckd_mul
+
+# include "intprops-internal.h"
/* Store into *R the low-order bits of A + B, A - B, A * B, respectively.
Return 1 if the result overflows, 0 otherwise.
bit-precise integer type, or an enumeration type.
These are like the standard macros introduced in C23, except that
- arguments should not have side effects. */
+ arguments should not have side effects. The C++26 standard is
+ expected to add this header and it's macros. */
-#define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r))
-#define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r))
-#define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r))
+# define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r))
+# define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r))
+# define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r))
-#endif /* _GL_STDCKDINT_H */
+# endif /* defined __cplusplus ? @HAVE_WORKING_CXX_STDCKDINT_H@ : @HAVE_WORKING_C_STDCKDINT_H@ */
+#endif /* _@GUARD_PREFIX@_STDCKDINT_H */
+#endif /* _@GUARD_PREFIX@_STDCKDINT_H */
--- /dev/null
+# stdckdint_h.m4
+# serial 1
+dnl Copyright 2025 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl This file is offered as-is, without any warranty.
+
+dnl Written by Collin Funk.
+
+AC_DEFUN_ONCE([gl_STDCKDINT_H],
+[
+ gl_CHECK_NEXT_HEADERS([stdckdint.h])
+ if test $ac_cv_header_stdckdint_h = yes; then
+ HAVE_STDCKDINT_H=1
+ else
+ HAVE_STDCKDINT_H=0
+ fi
+ AC_SUBST([HAVE_STDCKDINT_H])
+
+ if test $HAVE_STDCKDINT_H = 1; then
+ AC_CACHE_CHECK([whether stdckdint.h can be included in C],
+ [gl_cv_header_c_stdckdint_h],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <stdckdint.h>
+ ]])],
+ [gl_cv_header_c_stdckdint_h=yes],
+ [gl_cv_header_c_stdckdint_h=no])])
+ if test $gl_cv_header_c_stdckdint_h = yes; then
+ HAVE_C_STDCKDINT_H=1
+ AC_CACHE_CHECK([checking for an ISO C23 compliant stdckdint.h in C],
+ [gl_cv_header_c_stdckdint_h_works],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <stdckdint.h>
+ ]],
+ [[int r;
+ int a = 1;
+ int b = 1;
+ return !!(ckd_add (&r, a, b) || ckd_sub (&r, a, b)
+ || ckd_mul (&r, a, b));
+ ]])],
+ [gl_cv_header_c_stdckdint_h_works=yes],
+ [gl_cv_header_c_stdckdint_h_works=no])])
+ if test $gl_cv_header_c_stdckdint_h_works = yes; then
+ HAVE_WORKING_C_STDCKDINT_H=1
+ else
+ HAVE_WORKING_C_STDCKDINT_H=0
+ fi
+ else
+ HAVE_C_STDCKDINT_H=0
+ HAVE_WORKING_C_STDCKDINT_H=0
+ fi
+ if test "$CXX" != no; then
+ AC_CACHE_CHECK([whether stdckdint.h can be included in C++],
+ [gl_cv_header_cxx_stdckdint_h],
+ [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to
+ dnl an autoconf bug <https://savannah.gnu.org/support/?110294>.
+ cat > conftest.cpp <<\EOF
+#include <stdckdint.h>
+EOF
+ gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp"
+ if AC_TRY_EVAL([gl_command]); then
+ gl_cv_header_cxx_stdckdint_h=yes
+ else
+ gl_cv_header_cxx_stdckdint_h=no
+ fi
+ rm -fr conftest*
+ ])
+ if test $gl_cv_header_cxx_stdckdint_h = yes; then
+ HAVE_CXX_STDCKDINT_H=1
+ AC_CACHE_CHECK([checking for an ISO C++26 compliant stdckdint.h in C++],
+ [gl_cv_header_cxx_stdckdint_h_works],
+ [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to
+ dnl an autoconf bug <https://savannah.gnu.org/support/?110294>.
+ cat > conftest.cpp <<\EOF
+#include <stdckdint.h>
+int
+main (void)
+{
+ int r;
+ int a = 1;
+ int b = 1;
+ return !!(ckd_add (&r, a, b) || ckd_sub (&r, a, b) || ckd_mul (&r, a, b));
+}
+EOF
+ gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp"
+ if AC_TRY_EVAL([gl_command]); then
+ gl_cv_header_cxx_stdckdint_h_works=yes
+ else
+ gl_cv_header_cxx_stdckdint_h_works=no
+ fi
+ rm -fr conftest*
+ ])
+ if test $gl_cv_header_cxx_stdckdint_h_works = yes; then
+ HAVE_WORKING_CXX_STDCKDINT_H=1
+ else
+ HAVE_WORKING_CXX_STDCKDINT_H=0
+ fi
+ else
+ HAVE_CXX_STDCKDINT_H=0
+ HAVE_WORKING_CXX_STDCKDINT_H=0
+ fi
+ fi
+ else
+ HAVE_C_STDCKDINT_H=0
+ HAVE_WORKING_C_STDCKDINT_H=0
+ HAVE_CXX_STDCKDINT_H=0
+ HAVE_WORKING_CXX_STDCKDINT_H=0
+ fi
+ AC_SUBST([HAVE_C_STDCKDINT_H])
+ AC_SUBST([HAVE_WORKING_C_STDCKDINT_H])
+ AC_SUBST([HAVE_CXX_STDCKDINT_H])
+ AC_SUBST([HAVE_WORKING_CXX_STDCKDINT_H])
+
+ if test "$CXX" != no; then
+ dnl We might need the header for C or C++.
+ if test $HAVE_C_STDCKDINT_H = 1 \
+ && test $HAVE_WORKING_C_STDCKDINT_H = 1 \
+ && test $HAVE_CXX_STDCKDINT_H = 1 \
+ && test $HAVE_WORKING_CXX_STDCKDINT_H = 1; then
+ GL_GENERATE_STDCKDINT_H=false
+ else
+ GL_GENERATE_STDCKDINT_H=true
+ fi
+ else
+ dnl We don't care about C++ here.
+ if test $HAVE_C_STDCKDINT_H = 1 \
+ && test $HAVE_WORKING_C_STDCKDINT_H = 1; then
+ GL_GENERATE_STDCKDINT_H=false
+ else
+ GL_GENERATE_STDCKDINT_H=true
+ fi
+ fi
+])
An <stdckdint.h> that is like C23.
Files:
+m4/stdckdint_h.m4
lib/stdckdint.in.h
lib/intprops-internal.h
bool
configure.ac:
-AC_CHECK_HEADERS_ONCE([stdckdint.h])
-if test $ac_cv_header_stdckdint_h = yes; then
- if test -n "$CXX" && test "$CXX" != no; then
- GL_GENERATE_STDCKDINT_H=true
- else
- GL_GENERATE_STDCKDINT_H=false
- fi
-else
- GL_GENERATE_STDCKDINT_H=true
-fi
+gl_STDCKDINT_H
gl_CONDITIONAL_HEADER([stdckdint.h])
AC_PROG_MKDIR_P
stdckdint.h: stdckdint.in.h $(top_builddir)/config.status
@NMD@ $(AM_V_GEN)$(MKDIR_P) '%reldir%'
$(gl_V_at)$(SED_HEADER_STDOUT) \
+ -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_STDCKDINT_H''@|$(NEXT_STDCKDINT_H)|g' \
+ -e 's|@''HAVE_C_STDCKDINT_H''@|$(HAVE_C_STDCKDINT_H)|g' \
+ -e 's|@''HAVE_WORKING_C_STDCKDINT_H''@|$(HAVE_WORKING_C_STDCKDINT_H)|g' \
+ -e 's|@''HAVE_CXX_STDCKDINT_H''@|$(HAVE_CXX_STDCKDINT_H)|g' \
+ -e 's|@''HAVE_WORKING_CXX_STDCKDINT_H''@|$(HAVE_WORKING_CXX_STDCKDINT_H)|g' \
$(srcdir)/stdckdint.in.h > $@-t
$(AM_V_at)mv $@-t $@
else