Re: Questions about C as used/implemented in practice

2015-04-17 Thread msebor

On 04/17/2015 09:01 AM, Peter Sewell wrote:

On 17 April 2015 at 15:19,   wrote:



On Apr 17, 2015, at 9:14 AM, Peter Sewell  wrote:

Dear gcc list,

we are trying to clarify what behaviour of C implementations is
actually relied upon in modern practice, and what behaviour is
guaranteed by current mainstream implementations (these are quite
different from the ISO standards, and may differ in different
contexts).


I’m not sure what you mean by “guaranteed”.

I suspect what the GCC team will say is guaranteed is “what the standard says”.


If that's really true, that will be interesting, but there may be
areas where (a) current implementation behaviour is stronger than what
the ISO standards require, and (b) important code relies on that
behaviour to such an extent that it becomes pragmatically infeasible
to change it.  Such cases are part of what we're trying to discover
here.  There are also cases where the ISO standards are unclear or
internally inconsistent.


Implementations can and often do provide stronger guarantees than
the standards require. When the do, they must be documented in order
to be safely relied on. This is termed as implementation-defined
behavior in standards.

Standards may be unclear to casual readers but they must be consistent
and unambiguous. When they're not it's a defect that should be raised
against them.




  If by “guaranteed” you mean the behavior that happens to be implemented in a 
particular version of the compiler, that may well be different, as you said.  
But it’s also not particularly meaningful, because it is subject to change at 
any time subject to the constraints of the standard, and is likely to be 
different among different versions, and for that matter among different target 
architectures and of course optimization settings.


Some amount of variation has to be allowed, of course - in fact, what
we'd like to clarify is really the envelope of allowable variation,
and that will have to be parametric on at least some optimisation
settings.


All the questions in the survey that can be are answered are
answered without unambiguity in the C standard (either as well-
defined behavior - 4, 5, 11, 12, 15, unspecified - 1, 13, or
undefined - 2, 3, 7, 8, 9, 10, 14). There are no optimization
options that affect the answers.

Martin




 paul





Re: Is it Okay for GCC to do the following simplifications with "-ffast-math" flag

2015-05-05 Thread msebor

On 05/05/2015 08:27 AM, Renlin Li wrote:

Hi all,

For the following illustrative code,

double f1(int x) { return (double)(float)x; } --> return (double)x;
int f2(double x) { return (int)(float)x; } --> return (int)x;

Is it Okay for the compiler to do the simplifications shown above with
fast-match enabled?


Such a transformation would yield different results
for integers that are exactly representable in double
but not in float. For example, the smallest positive
integer with such a property in IEEE 754, 16,777,217,
converts to 16,777,216 in float. I'm not a math expert
but such a result would seem unexpected even with
-ffast-math.

Martin



Regards,
Renlin Li





Re: Spurious warning for zero-sized array parameters to a function

2022-12-09 Thread msebor--- via Gcc
> On Dec 6, 2022, at 9:22 AM, Alejandro Colomar via Gcc  wrote:
> 
> Hi!
> 
> In the following function, past_end is a pointer to one-past-the-end of the 
> array.  Holding such a pointer is legal in C.  I use it as a sentinel value 
> that helps (1) avoid overrunning the buffer, and (2) detect truncation.  I 
> mark it as having a size of [0], which clearly states that it can't be 
> dereferenced (and as you can see, I don't).
> 
> /*
> * This function copies an unterminated string into a string.
> * -  It never overruns the dest buffer.
> * -  It can be chained, to concatenate strings.
> * -  It detects truncation.
> * -  Truncation only needs to be tested once after all concatenations.
> * -  The name is self-documenting, compared to its alternative: strncat(3).
> */
> char *
> ustr2stpe(char *dst, const char *restrict src, size_t n, char past_end[0])
> {
>bool   trunc;
>char   *end;
>ptrdiff_t  len;
> 
>if (dst == past_end)
>return past_end;
> 
>trunc = false;
>len = strnlen(src, n);
>if (len > past_end - dst - 1) {
>len = past_end - dst - 1;
>trunc = true;
>}
> 
>end = mempcpy(dst, src, len);
>*end = '\0';
> 
>return trunc ? past_end : end;
> }
> 
> 
> If I compile the code above, GCC considers the function definition to be 
> fine. However, at call site, it always warns:
> 
> 
> #define nitems(arr)  (sizeof((arr)) / sizeof((arr)[0]))
> 
> int
> main(void)
> {
>char pre[4] = "pre.";
>char *post = ".post";
>char *src = "some-long-body.post";
>char dest[100];
>char *p, *past_end;
> 
>past_end = dest + nitems(dest);
>p = dest;
>p = ustr2stpe(p, pre, nitems(pre), past_end);
>p = ustr2stpe(p, src, strlen(src) - strlen(post), past_end);
>p = ustr2stpe(p, "", 0, past_end);
>if (p == past_end)
>fprintf(stderr, "truncation\n");
> 
>puts(dest);  // "pre.some-long-body"
> }
> 
> 
> 
> $ cc -Wall -Wextra ustr2stpe.c
> ustr2stpe.c: In function ‘main’:
> ustr2stpe.c:43:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 
> 0 [-Wstringop-overflow=]
>   43 | p = ustr2stpe(p, pre, nitems(pre), past_end);
>  | ^~~~
> ustr2stpe.c:43:13: note: referencing argument 4 of type ‘char[0]’
> ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
>   10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char 
> past_end[0])
>  | ^
> ustr2stpe.c:44:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 
> 0 [-Wstringop-overflow=]
>   44 | p = ustr2stpe(p, src, strlen(src) - strlen(post), past_end);
>  | ^~~
> ustr2stpe.c:44:13: note: referencing argument 4 of type ‘char[0]’
> ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
>   10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char 
> past_end[0])
>  | ^
> ustr2stpe.c:45:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 
> 0 [-Wstringop-overflow=]
>   45 | p = ustr2stpe(p, "", 0, past_end);
>  | ^
> ustr2stpe.c:45:13: note: referencing argument 4 of type ‘char[0]’
> ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
>   10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char 
> past_end[0])
>  | ^
> ustr2stpe.c:43:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 
> 0 [-Wstringop-overflow=]
>   43 | p = ustr2stpe(p, pre, nitems(pre), past_end);
>  | ^~~~
> ustr2stpe.c:43:13: note: referencing argument 4 of type ‘char[0]’
> ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
>   10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char 
> past_end[0])
>  | ^
> ustr2stpe.c:44:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 
> 0 [-Wstringop-overflow=]
>   44 | p = ustr2stpe(p, src, strlen(src) - strlen(post), past_end);
>  | ^~~
> ustr2stpe.c:44:13: note: referencing argument 4 of type ‘char[0]’
> ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
>   10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char 
> past_end[0])
>  | ^
> ustr2stpe.c:45:13: warning: ‘ustr2stpe’ accessing 1 byte in a region of size 
> 0 [-Wstringop-overflow=]
>   45 | p = ustr2stpe(p, "", 0, past_end);
>  | ^
> ustr2stpe.c:45:13: note: referencing argument 4 of type ‘char[0]’
> ustr2stpe.c:10:1: note: in a call to function ‘ustr2stpe’
>   10 | ustr2stpe(char *dst, const char *restrict src, size_t n, char 
> past_end[0])
>  | ^
> 
> 
> The warnings are invalid.  While it's true that I'm referencing a pointer of 
> size 0, it's false that I'm "accessing 1 byte" in that region.  I guess this 
> is all