aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShengYi Hung <aokblast@FreeBSD.org>2026-06-04 08:58:28 +0000
committerShengYi Hung <aokblast@FreeBSD.org>2026-06-09 11:25:30 +0000
commit9c0489508695fde3bdd742edfd1b4b681aab4d19 (patch)
tree63aac3a3ad05b1c40fb801a814457cd0da0d62ac
parentc0ec8ffb46ab337dcf726fcdf8083f62859d0ae6 (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.h10
-rw-r--r--lib/msun/arm/fenv.h10
-rw-r--r--lib/msun/powerpc/fenv.h12
-rw-r--r--lib/msun/riscv/fenv.h12
-rw-r--r--lib/msun/x86/fenv.h10
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__