Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Jan 2021 18:44:19 +0100
From:      Walter von Entferndt <walter.von.entferndt@posteo.net>
To:        freebsd-hackers@freebsd.org
Subject:   Implicit assuptions (was: Re: Some fun with -O2)
Message-ID:  <12075361.5MqMfjp4zD@t450s.local.lan>
In-Reply-To: <mailman.29.1610625600.45116.freebsd-hackers@freebsd.org>
References:  <mailman.29.1610625600.45116.freebsd-hackers@freebsd.org>

index | next in thread | previous in thread | raw e-mail

At Donnerstag, 14. Januar 2021, 13:00:00 CET, Konstantin Belousov wrote:
> The time_t type is signed, then the loop
>   for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
>        continue;
> 
> intent is to get signed overflow, which is UB.  Modern compilers prefer to
> shoot into your foot instead of following common sense.
> 
The next line in the program is: time_t_max--;

The problem here is one of the most common in programming: to rely on an /
implicit assumption/ (e.g. how the compiler (or the CPU,...) handles some 
expression).  Obviously, the above loop condition (0 < time_t_max) is 
(mathematically) always true and thus can be optimized right away to an 
infinite loop.  Isn't that common sense, too? How should the compiler (or the 
CPU) know that this was /not/ intended?

> Workaround is to add -fwrapv compiler switch.
>
And the correct solution is: Do not rely on implicit assumptions.  Instead, 
write down /explicitely/ what you intend to do or get as result.  If that's 
not possible (or too complicated), at least add a comment explaining your 
intention.

Since the behaviour on signed overflow is undefined in C, the above statement 
must be rewritten completely.  For the case above, it's obvious (also from the 
name of the variable) that the author wants to have time_t_max  = the largest 
possible positive number of type time_t (all bits 1 except the sign bit).  OK, 
then write that instead:

[add	#include <stdlib.h>]
add	#include <limits.h>
change	static time_t time_t_max;
to	static const time_t time_t_max = LONG_MAX;
[because time_t equals long int]
del	for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
del		continue;
del	time_t_max--;

You may also
add	#include <stdio.h>
add	printf ("time_t_max = %ld\n", time_t_max);

in main() to verify that's giving you what you want.
-- 
=|o)	"Stell' Dir vor es geht und keiner kriegt's hin." (Wolfgang Neuss)
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?12075361.5MqMfjp4zD>