[PATCH] Mark explicit decls as implicit when we've seen a prototype
Joseph Myers
joseph@codesourcery.com
Thu Dec 4 15:05:00 GMT 2014
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
joseph@codesourcery.com
More information about the Gcc-patches
mailing list