This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: C constant expressions proposals
On Sat, 14 Aug 2004, Gabriel Dos Reis wrote:
> | This looks more in the spirit of C++ than C (since, for example, C does
> | not include const variables in constant expressions).
>
> It is true that C does not include const variables in constant
> expressions, but I believe it should accept const variables with
> either internal linkage or no linkage, initialized with integral
> constant expressions, to be used in constant expressions.
I believe in this matter we should wait to be led by WG14 if they want to
expand the notion of constant expressions in C, as hitherto WG14 has not
chosen (with the example of C++ to hand, and they certainly considered
what C++ features might appropriately be added to C) rather than adding
const variables (which C treats as accessing the value of a (constant)
object rather than as being constants, and in C const does not affect
linkage) to the valid parts of constant expressions. This question isn't
fundamental to the spirit of C; WG14 could choose to change it in future;
but bearing in mind that such extensions don't have much benefit (C
programmers are used to using #define for constants, for all its faults)
and would tend to lead to people writing code with GCC that fails to be
portable to other compilers, I just think we don't need such an extension.
(Without regard to the question of whether such an extension is within the
implementation latitude to add other forms of constant expression.)
In various cases when arithmetic is done on const variables we do
accidentally accept them in constant expressions, depending on
optimization and other random factors; this is bug 5675, plus a regression
since 24 March (for which I haven't filed a separate bug or upgraded that
one, given that sort of regression clearly isn't going to block a
release). One point of giving (and implementing) precise models is to
stop such random variation; it just so happens the C-like way of stopping
it means consistently treating const variables like non-const ones.
Since C has tentative definitions, you'd need the initializer to be
visible before the use in the constant expression. You should also
exclude volatile const variables.
> problem. I formulated the rules pretty much in the spirit of what
> CFront did to inline functions a very long time ago: use of an inline
> function before it is defined is a hard error. That requirement is
That certainly simplifies the use of inline functions! C99 says that a
call to an inline function can use either the definition in that
translation unit (which may be before or after the call), or the
non-inline definition in another translation unit, but not an inline
definition from another translation unit. All these definitions may be
distinct; C99 deliberately (discussed in the Rationale) did not adopt the
ODR.
> For the GNU C part, shouldn't we be more precise about:
>
> g) Built-in functions starting __builtin_ may be used in certain
> circumstances in constant expressions: if the compiler can fold
> them to an integer constant, floating constant or address
> constant then they are treated as an integer constant
> expression, arithmetic constant expression or address constant,
> respectively. The exact circumstances in which they are folded
> are unspecified, may depend on optimisation levels and are
> subject to change.
>
> I would prefer we don't make the "constantness" depend on optimization
> level. The reason is that we should not make a program valid
> depending on the optimization level -- users should be able to switch
> from "-g -O2" to "-g -O0" or vice versa.
The situation is that a precise specification is difficult - some
functions may not result in a constant with constant arguments, while
non-integer arguments may quite legitimately result in integer constants
in some cases. I also suspect real code is using such cases, beyond those
documented, in constant expressions in initializers. Thus I discourage
use in constant expressions, while expressly noting those cases such as
__builtin_nan for which we have made guarantees that they can be used as
such in standard headers. Effectively this leaves a "window onto the
implementation", albeit much smaller than at present, where we have never
specified constancy but some users may reasonably be using it. To make
things more precise we'd either say "never constant, except for this short
list of functions" (and take the user complaints), or else keep updating a
list of precisely which mathematical functions (for example) we fold, and
when (and we fold some only for particular arguments). When folding
arithmetic constant expressions, FENV_ACCESS complicates matters as well
(i.e. except in static initializers we can't fold, but VLA constraints
expect us to, and there was a view in the UK C Panel that the problem
there might be that the expression was still considered constant in the
presence of FENV_ACCESS rather than in the VLA constraints). As the
standard is of course silent on __builtin_ function calls, there's no
great value in arbitrarily annoying users by restricting them.
VLAs in structures form another underspecified case, although there
because I think deprecating them is the right solution; I think their
semantics are full of holes that we don't want to try to fill, and they
don't work reliably as shown by many bug reports past and present.
--
Joseph S. Myers http://www.srcf.ucam.org/~jsm28/gcc/
jsm@polyomino.org.uk (personal mail)
jsm28@gcc.gnu.org (Bugzilla assignments and CCs)