diff --git a/source/expressions.tex b/source/expressions.tex index 8a3fab39bf..3962861606 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -7393,7 +7393,11 @@ an \grammarterm{asm-declaration}\iref{dcl.asm}; \item -an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; or +an invocation of the \tcode{va_arg} macro\iref{cstdarg.syn}; + +\item +a non-constant library call\iref{defns.nonconst.libcall}; +or \item a \keyword{goto} statement\iref{stmt.goto}. diff --git a/source/intro.tex b/source/intro.tex index cbee223c7b..4bde4a91a0 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -423,6 +423,12 @@ sequence of one or more bytes representing the code unit sequence for an encoded character of the execution character set +\indexdefn{library call!non-constant}% +\definition{non-constant library call}{defns.nonconst.libcall} +invocation of a library function that, +as part of evaluating any expression \tcode{E}, +prevents \tcode{E} from being a core constant expression + \definition{NTCTS}{defns.ntcts} \defncontext{library} \indexdefn{NTCTS}% diff --git a/source/lib-intro.tex b/source/lib-intro.tex index a4e4fe6889..bf960caa7e 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -136,6 +136,30 @@ ISO C \tcode{restrict} qualifier) are the same unless otherwise stated. +\pnum +A call to a C standard library function is +a non-constant library call\iref{defns.nonconst.libcall} +if it raises a floating-point exception other than \tcode{FE_INEXACT}. +The semantics of a call to a C standard library function +evaluated as a core constant expression +are those specified in Annex F of the C standard +\begin{footnote} +See also ISO/IEC 9899:2018 section 7.6. +\end{footnote} +to the extent applicable to the floating-point types\iref{basic.fundamental} +that are parameter types of the called function. +\begin{note} +Annex F specifies +the conditions under which floating-point exceptions are raised and +the behavior when NaNs and/or infinities are passed as arguments. +\end{note} +\begin{note} +Equivalently, a call to a C standard library function is +a non-constant library call +if \tcode{errno} is set +when \tcode{math_errhandling \& MATH_ERRNO} is \tcode{true}. +\end{note} + \rSec1[description]{Method of description} \rSec2[description.general]{General} diff --git a/source/numerics.tex b/source/numerics.tex index 9448d6a94a..dcb43333ab 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -9538,23 +9538,23 @@ float expm1f(float x); long double expm1l(long double x); - float frexp(float value, int* exp); // see \ref{library.c} - double frexp(double value, int* exp); - long double frexp(long double value, int* exp); // see \ref{library.c} - float frexpf(float value, int* exp); - long double frexpl(long double value, int* exp); - - int ilogb(float x); // see \ref{library.c} - int ilogb(double x); - int ilogb(long double x); // see \ref{library.c} - int ilogbf(float x); - int ilogbl(long double x); - - float ldexp(float x, int exp); // see \ref{library.c} - double ldexp(double x, int exp); - long double ldexp(long double x, int exp); // see \ref{library.c} - float ldexpf(float x, int exp); - long double ldexpl(long double x, int exp); + constexpr float frexp(float value, int* exp); // see \ref{library.c} + constexpr double frexp(double value, int* exp); + constexpr long double frexp(long double value, int* exp); // see \ref{library.c} + constexpr float frexpf(float value, int* exp); + constexpr long double frexpl(long double value, int* exp); + + constexpr int ilogb(float x); // see \ref{library.c} + constexpr int ilogb(double x); + constexpr int ilogb(long double x); // see \ref{library.c} + constexpr int ilogbf(float x); + constexpr int ilogbl(long double x); + + constexpr float ldexp(float x, int exp); // see \ref{library.c} + constexpr double ldexp(double x, int exp); + constexpr long double ldexp(long double x, int exp); // see \ref{library.c} + constexpr float ldexpf(float x, int exp); + constexpr long double ldexpl(long double x, int exp); float log(float x); // see \ref{library.c} double log(double x); @@ -9580,29 +9580,29 @@ float log2f(float x); long double log2l(long double x); - float logb(float x); // see \ref{library.c} - double logb(double x); - long double logb(long double x); // see \ref{library.c} - float logbf(float x); - long double logbl(long double x); - - float modf(float value, float* iptr); // see \ref{library.c} - double modf(double value, double* iptr); - long double modf(long double value, long double* iptr); // see \ref{library.c} - float modff(float value, float* iptr); - long double modfl(long double value, long double* iptr); - - float scalbn(float x, int n); // see \ref{library.c} - double scalbn(double x, int n); - long double scalbn(long double x, int n); // see \ref{library.c} - float scalbnf(float x, int n); - long double scalbnl(long double x, int n); - - float scalbln(float x, long int n); // see \ref{library.c} - double scalbln(double x, long int n); - long double scalbln(long double x, long int n); // see \ref{library.c} - float scalblnf(float x, long int n); - long double scalblnl(long double x, long int n); + constexpr float logb(float x); // see \ref{library.c} + constexpr double logb(double x); + constexpr long double logb(long double x); // see \ref{library.c} + constexpr float logbf(float x); + constexpr long double logbl(long double x); + + constexpr float modf(float value, float* iptr); // see \ref{library.c} + constexpr double modf(double value, double* iptr); + constexpr long double modf(long double value, long double* iptr); // see \ref{library.c} + constexpr float modff(float value, float* iptr); + constexpr long double modfl(long double value, long double* iptr); + + constexpr float scalbn(float x, int n); // see \ref{library.c} + constexpr double scalbn(double x, int n); + constexpr long double scalbn(long double x, int n); // see \ref{library.c} + constexpr float scalbnf(float x, int n); + constexpr long double scalbnl(long double x, int n); + + constexpr float scalbln(float x, long int n); // see \ref{library.c} + constexpr double scalbln(double x, long int n); + constexpr long double scalbln(long double x, long int n); // see \ref{library.c} + constexpr float scalblnf(float x, long int n); + constexpr long double scalblnl(long double x, long int n); float cbrt(float x); // see \ref{library.c} double cbrt(double x); @@ -9611,18 +9611,18 @@ long double cbrtl(long double x); // \ref{c.math.abs}, absolute values - int abs(int j); - long int abs(long int j); - long long int abs(long long int j); - float abs(float j); - double abs(double j); - long double abs(long double j); - - float fabs(float x); // see \ref{library.c} - double fabs(double x); - long double fabs(long double x); // see \ref{library.c} - float fabsf(float x); - long double fabsl(long double x); + constexpr int abs(int j); + constexpr long int abs(long int j); + constexpr long long int abs(long long int j); + constexpr float abs(float j); + constexpr double abs(double j); + constexpr long double abs(long double j); + + constexpr float fabs(float x); // see \ref{library.c} + constexpr double fabs(double x); + constexpr long double fabs(long double x); // see \ref{library.c} + constexpr float fabsf(float x); + constexpr long double fabsl(long double x); float hypot(float x, float y); // see \ref{library.c} double hypot(double x, double y); @@ -9671,17 +9671,17 @@ float tgammaf(float x); long double tgammal(long double x); - float ceil(float x); // see \ref{library.c} - double ceil(double x); - long double ceil(long double x); // see \ref{library.c} - float ceilf(float x); - long double ceill(long double x); + constexpr float ceil(float x); // see \ref{library.c} + constexpr double ceil(double x); + constexpr long double ceil(long double x); // see \ref{library.c} + constexpr float ceilf(float x); + constexpr long double ceill(long double x); - float floor(float x); // see \ref{library.c} - double floor(double x); - long double floor(long double x); // see \ref{library.c} - float floorf(float x); - long double floorl(long double x); + constexpr float floor(float x); // see \ref{library.c} + constexpr double floor(double x); + constexpr long double floor(long double x); // see \ref{library.c} + constexpr float floorf(float x); + constexpr long double floorl(long double x); float nearbyint(float x); // see \ref{library.c} double nearbyint(double x); @@ -9707,93 +9707,93 @@ long long int llrintf(float x); long long int llrintl(long double x); - float round(float x); // see \ref{library.c} - double round(double x); - long double round(long double x); // see \ref{library.c} - float roundf(float x); - long double roundl(long double x); - - long int lround(float x); // see \ref{library.c} - long int lround(double x); - long int lround(long double x); // see \ref{library.c} - long int lroundf(float x); - long int lroundl(long double x); - - long long int llround(float x); // see \ref{library.c} - long long int llround(double x); - long long int llround(long double x); // see \ref{library.c} - long long int llroundf(float x); - long long int llroundl(long double x); - - float trunc(float x); // see \ref{library.c} - double trunc(double x); - long double trunc(long double x); // see \ref{library.c} - float truncf(float x); - long double truncl(long double x); - - float fmod(float x, float y); // see \ref{library.c} - double fmod(double x, double y); - long double fmod(long double x, long double y); // see \ref{library.c} - float fmodf(float x, float y); - long double fmodl(long double x, long double y); - - float remainder(float x, float y); // see \ref{library.c} - double remainder(double x, double y); - long double remainder(long double x, long double y); // see \ref{library.c} - float remainderf(float x, float y); - long double remainderl(long double x, long double y); - - float remquo(float x, float y, int* quo); // see \ref{library.c} - double remquo(double x, double y, int* quo); - long double remquo(long double x, long double y, int* quo); // see \ref{library.c} - float remquof(float x, float y, int* quo); - long double remquol(long double x, long double y, int* quo); - - float copysign(float x, float y); // see \ref{library.c} - double copysign(double x, double y); - long double copysign(long double x, long double y); // see \ref{library.c} - float copysignf(float x, float y); - long double copysignl(long double x, long double y); + constexpr float round(float x); // see \ref{library.c} + constexpr double round(double x); + constexpr long double round(long double x); // see \ref{library.c} + constexpr float roundf(float x); + constexpr long double roundl(long double x); + + constexpr long int lround(float x); // see \ref{library.c} + constexpr long int lround(double x); + constexpr long int lround(long double x); // see \ref{library.c} + constexpr long int lroundf(float x); + constexpr long int lroundl(long double x); + + constexpr long long int llround(float x); // see \ref{library.c} + constexpr long long int llround(double x); + constexpr long long int llround(long double x); // see \ref{library.c} + constexpr long long int llroundf(float x); + constexpr long long int llroundl(long double x); + + constexpr float trunc(float x); // see \ref{library.c} + constexpr double trunc(double x); + constexpr long double trunc(long double x); // see \ref{library.c} + constexpr float truncf(float x); + constexpr long double truncl(long double x); + + constexpr float fmod(float x, float y); // see \ref{library.c} + constexpr double fmod(double x, double y); + constexpr long double fmod(long double x, long double y); // see \ref{library.c} + constexpr float fmodf(float x, float y); + constexpr long double fmodl(long double x, long double y); + + constexpr float remainder(float x, float y); // see \ref{library.c} + constexpr double remainder(double x, double y); + constexpr long double remainder(long double x, long double y); // see \ref{library.c} + constexpr float remainderf(float x, float y); + constexpr long double remainderl(long double x, long double y); + + constexpr float remquo(float x, float y, int* quo); // see \ref{library.c} + constexpr double remquo(double x, double y, int* quo); + constexpr long double remquo(long double x, long double y, int* quo); // see \ref{library.c} + constexpr float remquof(float x, float y, int* quo); + constexpr long double remquol(long double x, long double y, int* quo); + + constexpr float copysign(float x, float y); // see \ref{library.c} + constexpr double copysign(double x, double y); + constexpr long double copysign(long double x, long double y); // see \ref{library.c} + constexpr float copysignf(float x, float y); + constexpr long double copysignl(long double x, long double y); double nan(const char* tagp); float nanf(const char* tagp); long double nanl(const char* tagp); - float nextafter(float x, float y); // see \ref{library.c} - double nextafter(double x, double y); - long double nextafter(long double x, long double y); // see \ref{library.c} - float nextafterf(float x, float y); - long double nextafterl(long double x, long double y); - - float nexttoward(float x, long double y); // see \ref{library.c} - double nexttoward(double x, long double y); - long double nexttoward(long double x, long double y); // see \ref{library.c} - float nexttowardf(float x, long double y); - long double nexttowardl(long double x, long double y); - - float fdim(float x, float y); // see \ref{library.c} - double fdim(double x, double y); - long double fdim(long double x, long double y); // see \ref{library.c} - float fdimf(float x, float y); - long double fdiml(long double x, long double y); - - float fmax(float x, float y); // see \ref{library.c} - double fmax(double x, double y); - long double fmax(long double x, long double y); // see \ref{library.c} - float fmaxf(float x, float y); - long double fmaxl(long double x, long double y); - - float fmin(float x, float y); // see \ref{library.c} - double fmin(double x, double y); - long double fmin(long double x, long double y); // see \ref{library.c} - float fminf(float x, float y); - long double fminl(long double x, long double y); - - float fma(float x, float y, float z); // see \ref{library.c} - double fma(double x, double y, double z); - long double fma(long double x, long double y, long double z); // see \ref{library.c} - float fmaf(float x, float y, float z); - long double fmal(long double x, long double y, long double z); + constexpr float nextafter(float x, float y); // see \ref{library.c} + constexpr double nextafter(double x, double y); + constexpr long double nextafter(long double x, long double y); // see \ref{library.c} + constexpr float nextafterf(float x, float y); + constexpr long double nextafterl(long double x, long double y); + + constexpr float nexttoward(float x, long double y); // see \ref{library.c} + constexpr double nexttoward(double x, long double y); + constexpr long double nexttoward(long double x, long double y); // see \ref{library.c} + constexpr float nexttowardf(float x, long double y); + constexpr long double nexttowardl(long double x, long double y); + + constexpr float fdim(float x, float y); // see \ref{library.c} + constexpr double fdim(double x, double y); + constexpr long double fdim(long double x, long double y); // see \ref{library.c} + constexpr float fdimf(float x, float y); + constexpr long double fdiml(long double x, long double y); + + constexpr float fmax(float x, float y); // see \ref{library.c} + constexpr double fmax(double x, double y); + constexpr long double fmax(long double x, long double y); // see \ref{library.c} + constexpr float fmaxf(float x, float y); + constexpr long double fmaxl(long double x, long double y); + + constexpr float fmin(float x, float y); // see \ref{library.c} + constexpr double fmin(double x, double y); + constexpr long double fmin(long double x, long double y); // see \ref{library.c} + constexpr float fminf(float x, float y); + constexpr long double fminl(long double x, long double y); + + constexpr float fma(float x, float y, float z); // see \ref{library.c} + constexpr double fma(double x, double y, double z); + constexpr long double fma(long double x, long double y, long double z); // see \ref{library.c} + constexpr float fmaf(float x, float y, float z); + constexpr long double fmal(long double x, long double y, long double z); // \ref{c.math.lerp}, linear interpolation constexpr float lerp(float a, float b, float t) noexcept; @@ -9801,53 +9801,53 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept; // \ref{c.math.fpclass}, classification / comparison functions - int fpclassify(float x); - int fpclassify(double x); - int fpclassify(long double x); + constexpr int fpclassify(float x); + constexpr int fpclassify(double x); + constexpr int fpclassify(long double x); - bool isfinite(float x); - bool isfinite(double x); - bool isfinite(long double x); + constexpr bool isfinite(float x); + constexpr bool isfinite(double x); + constexpr bool isfinite(long double x); - bool isinf(float x); - bool isinf(double x); - bool isinf(long double x); + constexpr bool isinf(float x); + constexpr bool isinf(double x); + constexpr bool isinf(long double x); - bool isnan(float x); - bool isnan(double x); - bool isnan(long double x); + constexpr bool isnan(float x); + constexpr bool isnan(double x); + constexpr bool isnan(long double x); - bool isnormal(float x); - bool isnormal(double x); - bool isnormal(long double x); + constexpr bool isnormal(float x); + constexpr bool isnormal(double x); + constexpr bool isnormal(long double x); - bool signbit(float x); - bool signbit(double x); - bool signbit(long double x); + constexpr bool signbit(float x); + constexpr bool signbit(double x); + constexpr bool signbit(long double x); - bool isgreater(float x, float y); - bool isgreater(double x, double y); - bool isgreater(long double x, long double y); + constexpr bool isgreater(float x, float y); + constexpr bool isgreater(double x, double y); + constexpr bool isgreater(long double x, long double y); - bool isgreaterequal(float x, float y); - bool isgreaterequal(double x, double y); - bool isgreaterequal(long double x, long double y); + constexpr bool isgreaterequal(float x, float y); + constexpr bool isgreaterequal(double x, double y); + constexpr bool isgreaterequal(long double x, long double y); - bool isless(float x, float y); - bool isless(double x, double y); - bool isless(long double x, long double y); + constexpr bool isless(float x, float y); + constexpr bool isless(double x, double y); + constexpr bool isless(long double x, long double y); - bool islessequal(float x, float y); - bool islessequal(double x, double y); - bool islessequal(long double x, long double y); + constexpr bool islessequal(float x, float y); + constexpr bool islessequal(double x, double y); + constexpr bool islessequal(long double x, long double y); - bool islessgreater(float x, float y); - bool islessgreater(double x, double y); - bool islessgreater(long double x, long double y); + constexpr bool islessgreater(float x, float y); + constexpr bool islessgreater(double x, double y); + constexpr bool islessgreater(long double x, long double y); - bool isunordered(float x, float y); - bool isunordered(double x, double y); - bool isunordered(long double x, long double y); + constexpr bool isunordered(float x, float y); + constexpr bool isunordered(double x, double y); + constexpr bool isunordered(long double x, long double y); // \ref{sf.cmath}, mathematical special functions @@ -10014,12 +10014,12 @@ \indexlibraryglobal{abs}% \begin{itemdecl} -int abs(int j); -long int abs(long int j); -long long int abs(long long int j); -float abs(float j); -double abs(double j); -long double abs(long double j); +constexpr int abs(int j); +constexpr long int abs(long int j); +constexpr long long int abs(long long int j); +constexpr float abs(float j); +constexpr double abs(double j); +constexpr long double abs(long double j); \end{itemdecl} \begin{itemdescr} diff --git a/source/support.tex b/source/support.tex index e8ccd20800..cbd48c58be 100644 --- a/source/support.tex +++ b/source/support.tex @@ -219,21 +219,21 @@ void srand(unsigned int seed); // \ref{c.math.abs}, absolute values - int abs(int j); - long int abs(long int j); - long long int abs(long long int j); - float abs(float j); - double abs(double j); - long double abs(long double j); - - long int labs(long int j); - long long int llabs(long long int j); - - div_t div(int numer, int denom); - ldiv_t div(long int numer, long int denom); // see \ref{library.c} - lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} - ldiv_t ldiv(long int numer, long int denom); - lldiv_t lldiv(long long int numer, long long int denom); + constexpr int abs(int j); + constexpr long int abs(long int j); + constexpr long long int abs(long long int j); + constexpr float abs(float j); + constexpr double abs(double j); + constexpr long double abs(long double j); + + constexpr long int labs(long int j); + constexpr long long int llabs(long long int j); + + constexpr div_t div(int numer, int denom); + constexpr ldiv_t div(long int numer, long int denom); // see \ref{library.c} + constexpr lldiv_t div(long long int numer, long long int denom); // see \ref{library.c} + constexpr ldiv_t ldiv(long int numer, long int denom); + constexpr lldiv_t lldiv(long long int numer, long long int denom); } \end{codeblock} @@ -589,6 +589,7 @@ #define @\defnlibxname{cpp_lib_complex_udls}@ 201309L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_concepts}@ 202002L // also in \libheader{concepts} #define @\defnlibxname{cpp_lib_constexpr_algorithms}@ 201806L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202202L // also in \libheader{cmath}, \libheader{cstdlib} #define @\defnlibxname{cpp_lib_constexpr_complex}@ 201711L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // also in \libheader{functional}