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