diff options
| author | ShengYi Hung <aokblast@FreeBSD.org> | 2026-06-04 08:58:28 +0000 |
|---|---|---|
| committer | ShengYi Hung <aokblast@FreeBSD.org> | 2026-06-09 11:25:30 +0000 |
| commit | 9c0489508695fde3bdd742edfd1b4b681aab4d19 (patch) | |
| tree | 63aac3a3ad05b1c40fb801a814457cd0da0d62ac | |
| parent | c0ec8ffb46ab337dcf726fcdf8083f62859d0ae6 (diff) | |
libc: Use slow path in fenv in C++
C++ exposes cfenv functions via using ::func. Our name-mangling
mechanism rewrites all function calls causing symbols such as
std::feclearexcept to be transformed into std::__feclearexcept_int.
Since no such function exists, compilation fails.
The using ::feclearexpect declarations themselves are unaffected because
they are not function calls, which further exposes the mismatch
As a result, enable the fast path only for C and fall back to the slow
path in C++.
Reviewed by: kib
Fixes: 5bc64b7d417d
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D57450
| -rw-r--r-- | lib/msun/aarch64/fenv.h | 10 | ||||
| -rw-r--r-- | lib/msun/arm/fenv.h | 10 | ||||
| -rw-r--r-- | lib/msun/powerpc/fenv.h | 12 | ||||
| -rw-r--r-- | lib/msun/riscv/fenv.h | 12 | ||||
| -rw-r--r-- | lib/msun/x86/fenv.h | 10 |
5 files changed, 54 insertions, 0 deletions
diff --git a/lib/msun/aarch64/fenv.h b/lib/msun/aarch64/fenv.h index 5d47940cf9eb..aebcd99909ce 100644 --- a/lib/msun/aarch64/fenv.h +++ b/lib/msun/aarch64/fenv.h @@ -96,6 +96,15 @@ int feenableexcept(int); int fedisableexcept(int); int fegetexcept(void); +/* + * C permits a standard library function to also be exposed as a function-like + * macro (C23 7.1.4), and msun uses that here to inline the fast path. C++ + * forbids it: <cfenv> imports these names into namespace std (using + * ::feclearexcept; etc.), so std::feclearexcept() and friends must denote the + * actual functions. Expose the inlining macros to C only; C++ uses the real + * extern functions (defined in the matching lib/msun/<arch>/fenv.c). + */ +#ifndef __cplusplus #define feclearexcept(a) __feclearexcept_int(a) #define fegetexceptflag(e, a) __fegetexceptflag_int(e, a) #define fesetexceptflag(e, a) __fesetexceptflag_int(e, a) @@ -110,6 +119,7 @@ int fegetexcept(void); #define feenableexcept(a) __feenableexcept_int(a) #define fedisableexcept(a) __fedisableexcept_int(a) #define fegetexcept() __fegetexcept_int() +#endif /* !__cplusplus */ __fenv_static inline int __feclearexcept_int(int __excepts) diff --git a/lib/msun/arm/fenv.h b/lib/msun/arm/fenv.h index 78ca9ef0f589..6febbf95008d 100644 --- a/lib/msun/arm/fenv.h +++ b/lib/msun/arm/fenv.h @@ -129,6 +129,15 @@ int fedisableexcept(int); int fegetexcept(void); #endif +/* + * C permits a standard library function to also be exposed as a function-like + * macro (C23 7.1.4), and msun uses that here to inline the fast path. C++ + * forbids it: <cfenv> imports these names into namespace std (using + * ::feclearexcept; etc.), so std::feclearexcept() and friends must denote the + * actual functions. Expose the inlining macros to C only; C++ uses the real + * extern functions (defined in the matching lib/msun/<arch>/fenv.c). + */ +#ifndef __cplusplus #define feclearexcept(a) __feclearexcept_int(a) #define fegetexceptflag(e, a) __fegetexceptflag_int(e, a) #define fesetexceptflag(e, a) __fesetexceptflag_int(e, a) @@ -145,6 +154,7 @@ int fegetexcept(void); #define fedisableexcept(a) __fedisableexcept_int(a) #define fegetexcept() __fegetexcept_int() #endif +#endif /* !__cplusplus */ __fenv_static inline int __feclearexcept_int(int __excepts) diff --git a/lib/msun/powerpc/fenv.h b/lib/msun/powerpc/fenv.h index f6fb354470c7..8752be09994c 100644 --- a/lib/msun/powerpc/fenv.h +++ b/lib/msun/powerpc/fenv.h @@ -123,6 +123,15 @@ int feholdexcept(fenv_t *); int fesetenv(const fenv_t *); int feupdateenv(const fenv_t *); +/* + * C permits a standard library function to also be exposed as a function-like + * macro (C23 7.1.4), and msun uses that here to inline the fast path. C++ + * forbids it: <cfenv> imports these names into namespace std (using + * ::feclearexcept; etc.), so std::feclearexcept() and friends must denote the + * actual functions. Expose the inlining macros to C only; C++ uses the real + * extern functions (defined in the matching lib/msun/<arch>/fenv.c). + */ +#ifndef __cplusplus #define feclearexcept(a) __feclearexcept_int(a) #define fegetexceptflag(e, a) __fegetexceptflag_int(e, a) #define fesetexceptflag(e, a) __fesetexceptflag_int(e, a) @@ -134,6 +143,7 @@ int feupdateenv(const fenv_t *); #define feholdexcept(e) __feholdexcept_int(e) #define fesetenv(e) __fesetenv_int(e) #define feupdateenv(e) __feupdateenv_int(e) +#endif /* !__cplusplus */ __fenv_static inline int __feclearexcept_int(int __excepts) @@ -266,8 +276,10 @@ __feupdateenv_int(const fenv_t *__envp) int feenableexcept(int); int fedisableexcept(int); +#ifndef __cplusplus /* see the note above; C++ uses the real functions */ #define feenableexcept(a) __feenableexcept_int(a) #define fedisableexcept(a) __fedisableexcept_int(a) +#endif __fenv_static inline int __feenableexcept_int(int __mask) diff --git a/lib/msun/riscv/fenv.h b/lib/msun/riscv/fenv.h index 1059744941f3..199ca1806684 100644 --- a/lib/msun/riscv/fenv.h +++ b/lib/msun/riscv/fenv.h @@ -91,6 +91,15 @@ int feholdexcept(fenv_t *); int fesetenv(const fenv_t *); int feupdateenv(const fenv_t *); +/* + * C permits a standard library function to also be exposed as a function-like + * macro (C23 7.1.4), and msun uses that here to inline the fast path. C++ + * forbids it: <cfenv> imports these names into namespace std (using + * ::feclearexcept; etc.), so std::feclearexcept() and friends must denote the + * actual functions. Expose the inlining macros to C only; C++ uses the real + * extern functions (defined in the matching lib/msun/<arch>/fenv.c). + */ +#ifndef __cplusplus #define feclearexcept(a) __feclearexcept_int(a) #define fegetexceptflag(e, a) __fegetexceptflag_int(e, a) #define fesetexceptflag(e, a) __fesetexceptflag_int(e, a) @@ -102,6 +111,7 @@ int feupdateenv(const fenv_t *); #define feholdexcept(e) __feholdexcept_int(e) #define fesetenv(e) __fesetenv_int(e) #define feupdateenv(e) __feupdateenv_int(e) +#endif /* !__cplusplus */ __fenv_static inline int __feclearexcept_int(int __excepts) @@ -224,8 +234,10 @@ __feupdateenv_int(const fenv_t *__envp) int feenableexcept(int); int fedisableexcept(int); +#ifndef __cplusplus /* see the note above; C++ uses the real functions */ #define feenableexcept(a) __feenableexcept_int(a) #define fedisableexcept(a) __fedisableexcept_int(a) +#endif __fenv_static inline int __feenableexcept_int(int __mask __unused) diff --git a/lib/msun/x86/fenv.h b/lib/msun/x86/fenv.h index b5da37902083..cb44624a858a 100644 --- a/lib/msun/x86/fenv.h +++ b/lib/msun/x86/fenv.h @@ -150,12 +150,22 @@ int fesetround(int); int fegetround(void); int fesetenv(const fenv_t *); +/* + * C permits a standard library function to also be exposed as a function-like + * macro (C23 7.1.4), and msun uses that here to inline the fast path. C++ + * forbids it: <cfenv> imports these names into namespace std (using + * ::feclearexcept; etc.), so std::feclearexcept() and friends must denote the + * actual functions. Expose the inlining macros to C only; C++ uses the real + * extern functions (defined in the matching lib/msun/<arch>/fenv.c). + */ +#ifndef __cplusplus #define feclearexcept(a) __feclearexcept_int(a) #define fegetexceptflag(e, a) __fegetexceptflag_int(e, a) #define fetestexcept(a) __fetestexcept_int(a) #define fesetround(a) __fesetround_int(a) #define fegetround() __fegetround_int() #define fesetenv(a) __fesetenv_int(a) +#endif /* !__cplusplus */ #ifdef __i386__ |
