Bug 21326 - C99 functions are not declared for C++11 and later if _GNU_SOURCE is not predefined by g++
Summary: C99 functions are not declared for C++11 and later if _GNU_SOURCE is not pred...
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.23
: P2 normal
Target Milestone: 2.27
Assignee: Jonathan Wakely
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-29 11:34 UTC by Jonathan Wakely
Modified: 2017-10-09 14:20 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2017-03-29 11:34:12 UTC
Whether the following names are declared by glibc depends on __USE_ISOC99, but not __USE_ISOCXX11. They are only declared for C++ programs because g++ unconditionally pre-defines _GNU_SOURCE for all compilations on GNU targets.

I want G++ to move away from predefining _GNU_SOURCE, because causes many problems, e.g. non-standard names such as M_PI are always declared in C++ programs. Before we could do that, glibc would need to ensure all C99 functions that are also part of C++11 would be declared for C++ code, without relying on _GNU_SOURCE.

That could be done by either making many changes like this:

--- a/ctype/ctype.h
+++ b/ctype/ctype.h
@@ -126,7 +126,7 @@ extern int toupper (int __c) __THROW;
 
 
 /* ISO C99 introduced one new function.  */
-#ifdef __USE_ISOC99
+#if defined __USE_ISOC99 || __USE_ISOCXX11
 __exctype (isblank);
 #endif
 
Or simply:

--- a/include/features.h
+++ b/include/features.h
@@ -243,6 +243,7 @@
 #if ((defined __cplusplus && __cplusplus >= 201103L)                         \
      || defined __GXX_EXPERIMENTAL_CXX0X__)
 # define __USE_ISOCXX11        1
+# define __USE_ISOC99  1
 #endif
 
 /* If none of the ANSI/POSIX macros are defined, or if _DEFAULT_SOURCE



The former approach is already used in a very small number of places:

stdlib/stdlib.h:462:#if defined __USE_ISOC11 || defined __USE_ISOCXX11
stdlib/stdlib.h:484:#if defined __USE_ISOC11 || defined __USE_ISOCXX11
wcsmbs/uchar.h:40:#if defined __GNUC__ && !defined __USE_ISOCXX11


I can provide patches if you tell me which direction would be preferred.


The ISO C and ISO C++ names that are not declared by glibc when G++ doesn't predefine _GNU_SOURCE are:

FP_INFINITE
FP_NAN
FP_NORMAL
FP_SUBNORMAL
FP_ZERO
isblank
double_t
float_t
acosh
acoshf
acoshl
asinh
asinhf
asinhl
atanh
atanhf
atanhl
cbrt
cbrtf
cbrtl
copysign
copysignf
copysignl
erf
erff
erfl
erfc
erfcf
erfcl
exp2
exp2f
exp2l
expm1
expm1f
expm1l
fdim
fdimf
fdiml
fma
fmaf
fmal
fmax
fmaxf
fmaxl
fmin
fminf
fminl
hypot
hypotf
hypotl
ilogb
ilogbf
ilogbl
lgamma
lgammaf
lgammal
llrint
llrintf
llrintl
llround
llroundf
llroundl
log1p
log1pf
log1pl
log2
log2f
log2l
logb
logbf
logbl
lrint
lrintf
lrintl
lround
lroundf
lroundl
nan
nanf
nanl
nearbyint
nearbyintf
nearbyintl
nextafter
nextafterf
nextafterl
nexttoward
nexttowardf
nexttowardl
remainder
remainderf
remainderl
remquo
remquof
remquol
rint
rintf
rintl
round
roundf
roundl
scalbln
scalblnf
scalblnl
scalbn
scalbnf
scalbnl
tgamma
tgammaf
tgammal
trunc
truncf
truncl
snprintf
vfscanf
vscanf
vsnprintf
vsscanf
lldiv_t
llabs
lldiv
atoll
strtoll
strtoull
strtof
strtold
fwide
fwprintf
fwscanf
swprintf
swscanf
vfwprintf
vfwscanf
vswprintf
vswscanf
vwprintf
vwscanf
wcstof
wprintf
wscanf
wcstold
wcstoll
wcstoull
iswblank
Comment 1 Jonathan Wakely 2017-03-29 11:54:00 UTC
On a related topic, there is this comment in features.h

/* This is to enable compatibility for ISO C++11.

   So far g++ does not provide a macro.  Check the temporary macro for
   now, too.  */
#if ((defined __cplusplus && __cplusplus >= 201103L)                          \
     || defined __GXX_EXPERIMENTAL_CXX0X__)
# define __USE_ISOCXX11 1
#endif

Should it define some other macro? Isn't __cplusplus the right thing to check?
Comment 2 Jonathan Wakely 2017-03-29 12:01:28 UTC
(In reply to Jonathan Wakely from comment #1)
> On a related topic, there is this comment in features.h
> 
> /* This is to enable compatibility for ISO C++11.
> 
>    So far g++ does not provide a macro.  Check the temporary macro for
>    now, too.  */
> #if ((defined __cplusplus && __cplusplus >= 201103L)                        
> \
>      || defined __GXX_EXPERIMENTAL_CXX0X__)
> # define __USE_ISOCXX11 1
> #endif
> 
> Should it define some other macro? Isn't __cplusplus the right thing to
> check?

If you're expecting something like __STDC_VERSION__ for C++, that's exactly what __cplusplus is, so I don't know what "So far g++ does not provide a macro" means.

However, that reminds me of another alternative solution to the main problem, G++ could predefine __STDC_VERSION__ to 19901L for C++11 and C++14, and to 201112L for C++17. That would cause glibc to declare the C library functions that C++ wants.

The C++ standard says:

"Whether __STDC_VERSION__ is predefined and if so, what its value is, are implementation-defined."


So it would be OK for G++ to do that, as a way of requesting libc to declare the corresponding features.
Comment 3 jsm-csl@polyomino.org.uk 2017-03-29 14:10:41 UTC
I think __USE_ISOC99 and __USE_ISOC11 should be defined for whatever C++ 
versions incorporate the relevant C library versions.
Comment 4 Jonathan Wakely 2017-03-30 10:55:19 UTC
--- a/include/features.h
+++ b/include/features.h
@@ -236,13 +236,18 @@
 # define __USE_ISOC95  1
 #endif
 
+#ifdef __cplusplus
+/* This is to enable compatibility for ISO C++17.  */
+#if (__cplusplus >= 201703L)
+# define __USE_ISOCXX17        1
+# define __USE_ISOC11  1
+#endif
 /* This is to enable compatibility for ISO C++11.
-
-   So far g++ does not provide a macro.  Check the temporary macro for
-   now, too.  */
-#if ((defined __cplusplus && __cplusplus >= 201103L)                         \
-     || defined __GXX_EXPERIMENTAL_CXX0X__)
+   Check the temporary macro for now, too.  */
+#if (__cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__)
 # define __USE_ISOCXX11        1
+# define __USE_ISOC99  1
+#endif
 #endif
 
 /* If none of the ANSI/POSIX macros are defined, or if _DEFAULT_SOURCE
Comment 5 Sourceware Commits 2017-10-09 14:19:26 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  d6c064e914cba3277d852c9fa27db53f0059ff8c (commit)
      from  645ac9aaf89e3311949828546df6334322f48933 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d6c064e914cba3277d852c9fa27db53f0059ff8c

commit d6c064e914cba3277d852c9fa27db53f0059ff8c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Oct 9 14:58:34 2017 +0100

    Ensure C99 and C11 interfaces are available for C++ [BZ #21326]
    
    This patch ensures that the C99 and C11 features required by C++ are
    defined according to the value of the __cplusplus macro, and not just
    because G++ always defines _GNU_SOURCE.  This will allow G++ to stop
    defining _GNU_SOURCE some day, without causing the C99 and C11
    interfaces to disappear for C++ programs.
    
    	[BZ #21326]
    	* include/features.h [__cplusplus >= 201103] (__USE_ISOC99): Define.
    	[__cplusplus >= 201703] (__USE_ISOCXX17, __USE_ISOC11): Define.
    	* math/Makefile (test-math-cxx11): New test.
    	* math/test-math-cxx11.cc: New file.

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog               |    8 +++
 include/features.h      |   17 +++--
 math/Makefile           |    4 +-
 math/test-math-cxx11.cc |  160 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 182 insertions(+), 7 deletions(-)
 create mode 100644 math/test-math-cxx11.cc
Comment 6 Florian Weimer 2017-10-09 14:20:19 UTC
Fixed in 2.27.