This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: handling ISO C feature test macros


On Fri, 27 May 2016, Roland McGrath wrote:

> The original intent of features.h was that it and only it would ever
> need to know the complex interdependencies between feature-test sets.
> Each conditional around an actual declaration can have a very simple
> #if test on exactly one fine-grained set.  In the early days, this was
> actually completely true (modulo some __FAVOR_BSD complexities).  We
> have drifted away from the ideal over the years and now have over 300
> cases of "#if defined __USE_THIS || defined __USE_THAT" and the like.

I don't think "defined __USE_THIS || defined __USE_THAT" is a matter of 
"complex interdependencies between feature-test sets" in the wrong place.  
Rather, it accurately reflects the overlapping nature of the APIs in 
different sources, "this API was added as XSI in POSIX version A, then 
entered non-XSI POSIX in version B" etc.

> from the de facto API.  The upshot here is that new stuff should avoid
> friendly-seeming header file names like <features-iso.h> and instead do
> something that is very hard to misconstrue as anything other than
> internal implementation details that nobody outside libc's own headers
> should ever be using.

Well, you could do e.g.

#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
#include <bits/glibc-header-start.h>

where <bits/glibc-header-start.h> gives an error if 
__GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION is not defined, then 
undefines it.

> Fortunately for the "test exactly one set" principle, the new ISO C
> feature-test sets seem to come in small, fine-grained, non-overlapping
> sets to begin with.  This should make it easy to use something like:
> 
> #if __GLIBC_USE (IEC_60559_BFP_EXT)
>  declare issignaling
> #endif

That gets more complicated when you involve TS 18661-3 and TS 18661-4.

TS 18661-4 involves defining new functions (such as exp10, which glibc 
already has) if __STDC_WANT_IEC_60559_FUNCS_EXT__.  That's for the 
existing C types of float, double, long double.  For new types such as 
_Float128 from TS 18661-3, both __STDC_WANT_IEC_60559_TYPES_EXT__ (the 
macro from TS 18661-3) and __STDC_WANT_IEC_60559_FUNCS_EXT__ need to be 
defined.

That's fairly conveniently orthogonal - the __GLIBC_USE 
(IEC_60559_TYPES_EXT) conditional would go in math.h, so that it would 
only ever include <bits/mathcalls.h> for _Float128 in the 
__STDC_WANT_IEC_60559_TYPES_EXT__ case (like the existing __USE_ISOC99 
conditional for declaring float and long double), while <bits/mathcalls.h> 
would contain the __GLIBC_USE (IEC_60559_FUNCS_EXT) call around the exp10 
declaration.  But now bring in TS 18661-1.  If 
__STDC_WANT_IEC_60559_TYPES_EXT__ is defined, new-type versions of both 
C11 functions *and* TS 18661-1 functions should be declared, even without 
__STDC_WANT_IEC_60559_BFP_EXT__ being defined.  So bits/mathcalls.h would 
declare TS 18661-1 functions in either of the cases (__GLIBC_USE 
(IEC_60559_BFP_EXT), *or* the type used in a new one) - similar to the 
existing conditionals __MATH_DECLARING_DOUBLE in there to reflect how e.g. 
POSIX does not have the float and long double versions of the Bessel 
functions.

What would __GLIBC_USE look like for other cases where there are multiple 
versions of a standard (e.g. POSIX)?  Might it make sense to have e.g. 
__GLIBC_USE_XSI_POSIX (version1, version2) for XSI functions added in one 
version then moved to base POSIX in a later version, or similar 
multi-argument macros for functions added in one version then obsoleted 
later?

> Fortunately for generally minimizing the complexity of it all, since the
> demise of __FAVOR_BSD, I think _GNU_SOURCE really does now mean
> absolutely everything, the superset of all feature-test sets.

It certainly doesn't include gets (except for C++).  There may be other 
deprecated functions (supported because they're in older standard versions 
that we support) that aren't in _GNU_SOURCE.  (And there may be more 
deprecated functions like that that are currently in _GNU_SOURCE but 
*shouldn't* be, in that we agree with the deprecation in the context of 
the GNU system and so want to discourage use of those APIs.  Some POSIX 
deprecations however are because of e.g. portability issues where we may 
think the function is still appropriate for the GNU API.)

Also, there are plenty of other cases where feature test macros select 
between function versions.  E.g. _FILE_OFFSET_BITS=64 remapping functions, 
or choice between GNU and POSIX versions of some functions, or of some 
function prototypes, or C99 scanf conflicting with the older GNU scanf 
%as.

> testing our internal macros.  So we'd do our users a great service by
> providing a first-class, supported API to solve these problems.  Perhaps
> we can design something for ourselves that can be easily extended later
> to provide a good user API with marginal additional work.
> 
> For a user API it seems pretty clear that the only thing simple enough
> to use is a predicate for exactly what the user wants to know:
> 
> #if LIBC_HAS (foobar)
> ... we can use foobar! ...
> #endif

I don't think users want this only for libc.  I think that if someone 
doesn't want to use autoconf but still want to condition on availability 
of library features, they may want such a feature covering other libraries 
as well.  And so if we wish to support such a feature in the GNU system, 
to me that suggests something at the compiler level.

For availability of headers that would presumably be Clang-compatible 
__has_include.  For other features, it would need to be something at the 
compiler syntax level (testing "is this declared right now") rather than 
the preprocessor level, including a way to condition sections of code so 
they aren't parsed beyond matching {}()[] if the condition is false.

> * generate header files (be it one or many) used in the implementation
>   details of __glibc_has

That would seem to mean adding a huge pile of macros (that __glibc_has 
expands to using) that get defined whenever a glibc header is included.  
I'm not convinced that the compile-time impact (for the common case where 
headers are much bigger than the main code being compiled) is a good idea.  
And cases such as <bits/mathcalls.h> where a declaration may declare 
multiple functions depending on other macros would be more complicated to 
fit into such a scheme (and I don't think it would really be helpful for a 
separate source of truth to have to repeat similar information for all the 
the double, float, long double, _Float16, _Float32, _Float32x, _Float64, 
_Float64x, _Float128 versions of a function, when the present system 
avoids such repetitiveness).

> * generate or cross-check that information in the manual (and make it
>   easy to do the same for linux man pages, though that is not directly
>   our problem)

The manual doesn't have such information in any systematic form at all at 
present.

* Various functions say in free-text form where they came from.

* There are the "@comment stdio.h", "@comment ISO" etc. before definitions 
in the manual, used to generate summary.texi.  There is no actual defined 
list of standard names used in those comments, and they sometimes e.g. 
distinguish "BSD" and "SVID", a distinction no longer made in the headers.

Might the following be a desired state for the manual?  The @comment 
entries are replaced by macros like those used for safety information.  
Those expand to a statement of what standards the function is in / headers 
and feature test macros are required to use it.  The standards mentioned 
are limited to those relevant to feature test macros, so MISC or DEFAULT 
in place of BSD / SVID for __USE_MISC functions.  Those entries could be 
verified automatically based on including the headers with different 
macros defined - given information about which standards are relevant with 
which headers (as declarations are unconditional in a header if they are 
present for all standards with that header, even if not all standards 
supported by glibc).  (There would of course be complications for 
declarations only present for some systems, but the manual ought to 
indicate such cases anyway.)  Free-form text about standards for 
individual functions could be removed if felt not to add anything useful 
to the macro calls, but that would be a separate cleanup.

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]