Skip to content

Conversation

@t-a-k
Copy link
Contributor

@t-a-k t-a-k commented Sep 20, 2025

Some FreeBSD systems have <stdckdint.h>, but it cannot be compiled with C++ compilers. This patch modifies Configure to check whether ckd_* functions can be compiled, and leave I_STDCKDINT undefined (so that <stdckdint.h> won't be used in build time) if the compilation failed.

Will fix GH #23725.


  • This set of changes does not require a perldelta entry.

Some FreeBSD systems have <stdckdint.h>, but it cannot be compiled
with C++ compilers.  Configure now checks whether `ckd_*` functions
can be compiled, and leave I_STDCKDINT undefined if the compilation
failed.

Will fix GH Perl#23725 (d51aa1a build-time failure with clang++ and g++).
@jkeenan
Copy link
Contributor

jkeenan commented Sep 20, 2025

IIUC, the differences which your patch would effect could be detected simply by running ./Configure, i.e., even before running make.

I decided to use the same FreeBSD machine on which I explored #23725 to test this out. I took my regular configuration command (which by default uses clang in whatever is its current default version), substitute in clang++ (in its current default version, 18):

sh ./Configure -des -Dusedevel \
  -Dcc=clang++ \
  -Duseithreads \
  -Doptimize="-O2 -pipe -fstack-protector-strong -fno-strict-aliasing"

... and use that first on blead, then on the branch in your pull request. I then compared their respective config.sh files. This is what I got:

diff --ignore-matching-lines 'Configuration time:' \
     --ignore-matching-lines 'cf_time=' \
     blead.clang++.config.sh \
     branch.clang++.config.sh

814c814
< i_stdckdint='define'
---
> i_stdckdint='undef'

@t-a-k, is this what you would have expected?

On each of these two builds I then ran make test_prep. In blead, the build failed in the same way as reported in #23725 (comment). In branch, the build succeeded, as did make test_harness.

$ ./perl -Ilib -v | head -2 | tail -1
This is perl 5, version 43, subversion 3 (v5.43.3 (v5.43.2-339-g9f09ee5689)) built for amd64-freebsd-thread-multi

$ ./perl -Ilib -V:config_args
config_args='-des -Dusedevel -Dcc=clang++ -Duseithreads -Doptimize=-O2 -pipe -fstack-protector-strong -fno-strict-aliasing';

This pull request DWIMs for me, but it should also be reviewed by people more familiar with ./Configure than me. @khwilliamson, @Tux, can you take a look?

@t-a-k
Copy link
Contributor Author

t-a-k commented Sep 20, 2025

Thank you for testing!

... and use that first on blead, then on the branch in your pull request. I then compared their respective config.sh files. This is what I got:

diff --ignore-matching-lines 'Configuration time:' \
     --ignore-matching-lines 'cf_time=' \
     blead.clang++.config.sh \
     branch.clang++.config.sh

814c814
< i_stdckdint='define'
---
> i_stdckdint='undef'

@t-a-k, is this what you would have expected?

Yes. In this case <stdckdint.h> is present but fails to compile with specified compiler (probably because it is not compatible with C++), therefore Configure in this branch will set i_stdckdint to undef to indicate <stdckdint.h> is not usable.

@jkeenan jkeenan requested a review from Tux September 20, 2025 17:45
@khwilliamson
Copy link
Contributor

My question is, is there a C++ compatible hdr that would serve instead of this

@khwilliamson
Copy link
Contributor

And the answer to my question is no

@khwilliamson khwilliamson merged commit e6d5a81 into Perl:blead Sep 21, 2025
34 checks passed
@t-a-k
Copy link
Contributor Author

t-a-k commented Sep 21, 2025

Thank you for merging.

My question is, is there a C++ compatible hdr that would serve instead of this

As far as I can see, Clang 19's own stdckdint.h seems to be C++ compatible, and GCC 15's libstdc++ seems to have its own stdckdint.h for C++ programs.

I verified the former on Debian 13 (whose default Clang is v19, and which does not have /usr/include/stdckdint.h) as ./Configure ... -Dcc=clang++ leaves i_stdckdint='define' and perl builds successfully.

@jkeenan
Copy link
Contributor

jkeenan commented Sep 21, 2025

Thank you for merging.

My question is, is there a C++ compatible hdr that would serve instead of this

As far as I can see, Clang 19's own stdckdint.h seems to be C++ compatible, and GCC 15's libstdc++ seems to have its own stdckdint.h for C++ programs.

I verified the former on Debian 13 (whose default Clang is v19, and which does not have /usr/include/stdckdint.h) as ./Configure ... -Dcc=clang++ leaves i_stdckdint='define' and perl builds successfully.

FWIW, here are the different flavors of stdckdint.h I was able to locate on the FreeBSD-14 machine from which I have been reporting:

$ find /usr -type f -name '*stdckdint.h' 2>/dev/null | sort | xargs ls -l
-r--r--r--  1 root wheel 1050 Apr 14 20:28 /usr/include/stdckdint.h
-r--r--r--  1 root wheel 1666 Apr 14 20:28 /usr/lib/clang/18/include/stdckdint.h
-rw-r--r--  1 root wheel 1509 Jul 24 10:51 /usr/local/lib/gcc14/gcc/x86_64-portbld-freebsd14.2/14.3.1/include/stdckdint.h
-rw-r--r--  1 root wheel 1666 Jan 14  2025 /usr/local/llvm19/lib/clang/19/include/stdckdint.h
-rw-r--r--  1 root wheel 1666 Jul  8 23:06 /usr/local/llvm20/lib/clang/20/include/stdckdint.h
-rw-r--r--  1 root wheel 1666 Apr 14 20:47 /usr/src/contrib/llvm-project/clang/lib/Headers/stdckdint.h
-rw-r--r--  1 root wheel 1050 Apr 14 20:47 /usr/src/include/stdckdint.h

Let's see what's different.

$ diff -w /usr/include/stdckdint.h /usr/src/include/stdckdint.h
[ no diffs ]

$ diff -w /usr/lib/clang/18/include/stdckdint.h /usr/local/llvm19/lib/clang/19/include/stdckdint.h
[ no diffs ]

$ diff -w /usr/lib/clang/18/include/stdckdint.h /usr/local/llvm20/lib/clang/20/include/stdckdint.h
[ no diffs ]

$ diff -w /usr/lib/clang/18/include/stdckdint.h /usr/src/contrib/llvm-project/clang/lib/Headers/stdckdint.h
[ no diffs ]

But ...

$ diff -w /usr/include/stdckdint.h /usr/lib/clang/18/include/stdckdint.h
1,2c1
< /*-
<  * Copyright (c) 2023 Dag-Erling Smørgrav
---
> /*===---- stdckdint.h - Standard header for checking integer----------------===
4c3,7
<  * SPDX-License-Identifier: BSD-2-Clause
---
>  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>  * See https://llvm.org/LICENSE.txt for license information.
>  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>  *
>  *===-----------------------------------------------------------------------===
7,8c10,11
< #ifndef __STDC_VERSION_STDCKDINT_H__
< #define __STDC_VERSION_STDCKDINT_H__ 202311L
---
> #ifndef __STDCKDINT_H
> #define __STDCKDINT_H
10c13,20
< #include <sys/cdefs.h>
---
> /* If we're hosted, fall back to the system's stdckdint.h. FreeBSD, for
>  * example, already has a Clang-compatible stdckdint.h header.
>  *
>  * The `stdckdint.h` header requires C 23 or newer.
>  */
> #if __STDC_HOSTED__ && __has_include_next(<stdckdint.h>)
> #include_next <stdckdint.h>
> #else
12c22
< #if __BSD_VISIBLE || __ISO_C_VISIBLE >= 2023
---
> /* C23 7.20.1 Defines several macros for performing checked integer arithmetic*/
14,20c24
< #if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_add_overflow)
< #define ckd_add(result, a, b)						\
< 	(_Bool)__builtin_add_overflow((a), (b), (result))
< #else
< #define ckd_add(result, a, b)						\
< 	_Static_assert(0, "checked addition not supported")
< #endif
---
> #define __STDC_VERSION_STDCKDINT_H__ 202311L
22,28c26,27
< #if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_sub_overflow)
< #define ckd_sub(result, a, b)						\
< 	(_Bool)__builtin_sub_overflow((a), (b), (result))
< #else
< #define ckd_sub(result, a, b)						\
< 	_Static_assert(0, "checked subtraction not supported")
< #endif
---
> // Both A and B shall be any integer type other than "plain" char, bool, a bit-
> // precise integer type, or an enumerated type, and they need not be the same.
30,36c29,32
< #if __GNUC_PREREQ__(5, 1) || __has_builtin(__builtin_mul_overflow)
< #define ckd_mul(result, a, b)						\
< 	(_Bool)__builtin_mul_overflow((a), (b), (result))
< #else
< #define ckd_mul(result, a, b)						\
< 	_Static_assert(0, "checked multiplication not supported")
< #endif
---
> // R shall be a modifiable lvalue of any integer type other than "plain" char,
> // bool, a bit-precise integer type, or an enumerated type. It shouldn't be
> // short type, either. Otherwise, it may be unable to hold two the result of
> // operating two 'int's.
38c34,39
< #endif
---
> // A diagnostic message will be produced if A or B are not suitable integer
> // types, or if R is not a modifiable lvalue of a suitable integer type or R
> // is short type.
> #define ckd_add(R, A, B) __builtin_add_overflow((A), (B), (R))
> #define ckd_sub(R, A, B) __builtin_sub_overflow((A), (B), (R))
> #define ckd_mul(R, A, B) __builtin_mul_overflow((A), (B), (R))
40c41,42
< #endif
---
> #endif /* __STDC_HOSTED__ */
> #endif /* __STDCKDINT_H */

@t-a-k t-a-k deleted the i_stdckdint-fix branch September 25, 2025 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants