On Thu, 4 Dec 2014, Richard Biener wrote:

> Currently even when I prototype
> 
> double exp10 (double);
> 
> this function is not available to optimizers for code generation if
> they just check for builtin_decl_implicit (BUILT_IN_EXP10).
> Curiously though the function is identified as BUILT_IN_EXP10 when
> used though, thus the middle-end assumes it has expected exp10
> semantics.  I see we already cheat with stpcpy and make it available
> to optimizers by marking it implicit when we've seen a prototype.
> 
> The following patch proposed to do that for all builtins.
> 
> At least I can't see how interpreting exp10 as exp10 but then
> not being allowed to use it as exp10 is sensible.
> 
> Now one could argue that declaring exp10 doesn't mean there is
> an implementation available at link time (after all declaring
> exp10 doesn't mean I use exp10 anywhere).  But that's true
> for implicit decls as well - I might declare 'pow', not use
> it and not link against libm.  So if the compiler now emits
> a call to pow my link will break:

Logically I think the following should apply (no doubt there are various 
existing bugs in this area; at least, PR 46926 for sincos calls being 
generated in circumstances when that name is not reserved):

* If a function is assumed to have particular semantics, it can also be 
assumed to be available for code generation, *except* that implicitly 
introducing references to functions that may not be in libc is unsafe 
unless the user's program explicitly used a function from the containing 
library.  (Libraries for things that may not be in libc are as listed at 
<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html>; only 
libm for <math.h>, <complex.h> and <fenv.h> functions is likely to be 
relevant to GCC.  "explicitly used" is as in C11 6.9#5: "used in an 
expression (other than as part of the operand of a sizeof or _Alignof 
operator whose result is an integer constant)" (appropriately extended to 
cover GNU C extensions, such as typeof with non-variably-modified 
arguments).)

I don't think there's any existing infrastructure to avoid introducing 
e.g. calls to pow (in the absence of explicit calls to some libm function) 
in cases such as you suggest (and of course pow is an ISO C90 function so 
its semantics can always be assumed - the question is just whether libm 
will be used).

* If __builtin_foo (a built-in function where there is a corresponding 
function foo, standard or otherwise) is explicitly used, except maybe for 
calls with constant arguments expected to be optimized, the function foo 
may be assumed to be available and to have the expected semantics.  This 
applies regardless of what library foo is expected to be in, and 
regardless of whether foo is defined by any standard selected with -std, 
and regardless of any target-specific configuration information about what 
functions the target libraries provide (e.g. __builtin_sincos calls can be 
expanded to sincos whether or not the target has such a function).  
Furthermore, an explicit use of __builtin_foo for a libm function can be 
taken as meaning that libm will be linked in, except maybe for calls with 
constant arguments expected to be optimized.

(The point of the constant arguments exception is that calls to 
__builtin_nan (""), for example, are OK in static initializers, and maybe 
shouldn't be taken as meaning the nan library function is available or 
libm will be linked in.  The built-in functions for generating NaNs may be 
the only case for which this needs to apply.)

* As documented for -nostdlib, memcmp, memset, memcpy and memmove may 
always be assumed to be available, even with -ffreestanding, regardless of 
what explicit calls are or are not present.

* Built-in functions enabled by the selected -std (which in the default 
mode should mean all of them, but in modes such as -std=c11 is a smaller 
set) may always be assumed to be available in libraries linked in and to 
have the expected semantics, subject to (a) any target-specific 
configuration (targetm.libc_has_function) and (b) whether there are any 
explicit calls to functions in the relevant library (not generating calls 
to pow in the absence of any explicit libm function calls).

* Built-in functions reserved but not enabled by the selected -std (e.g. 
float and long double functions for -std=c90) may be treated the same as 
those enabled by the selected -std: it's never valid for the user to use 
them with any other semantics, and targetm.libc_has_function determines 
whether the function is available to generate calls to it (together with 
the presence of any explicit calls to libm functions).

* Built-in functions not reserved or enabled by the selected -std may be 
assumed to be available and to have the expected semantics (subject to 
some functions from the relevant library being explicitly called, in the 
case of libm functions) if declared *in a system header*.  So if you use 
-std=c11 -D_GNU_SOURCE and then include a header declaring exp10 or 
stpcpy, that implies you are using the _GNU_SOURCE library interface and 
so will not use those names for some other purpose.  Indeed, if you use 
_GNU_SOURCE before including any system header anywhere in your program 
you're arguably using the _GNU_SOURCE library interface and so reserving 
those names.  But if you only ever use system headers with feature test 
macros that don't reserve a given name, then you can use that name for 
some other incompatible purpose (so e.g. a strict ISO C program can use 
the exp10 or stpcpy names for its own purposes).

-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to