All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Triplett <josh@freedesktop.org>
To: Al Viro <viro@ftp.linux.org.uk>
Cc: linux-sparse@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>
Subject: Re: fun with ?:
Date: Tue, 22 May 2007 18:03:31 -0700	[thread overview]
Message-ID: <465392E3.3000300@freedesktop.org> (raw)
In-Reply-To: <20070523000234.GJ4095@ftp.linux.org.uk>

[-- Attachment #1: Type: text/plain, Size: 4946 bytes --]

Al Viro wrote:
> On Tue, May 22, 2007 at 04:24:49PM -0700, Josh Triplett wrote:
>> Makes sense, except that in C you can assign a void pointer to an arbitrary *
>> without a warning, so why can't conditional expressions do the equivalent?
> 
> {in sparse it's obviously not true due to address_space, but that hadn't
> affected C standard decisions; the rest applies to standard C}
> 
> For one thing, no, you can't (pointers to functions have every right to
> be unrelated to void *).  For another, you are not guaranteed that
> conversion from void * to int * will not yield undefined behaviour.
> It is OK if the value of void * is properly aligned; then you know
> that conversion back to void * will give the original pointer.  Otherwise
> you are in nasal demon country.  The other way round (int * to void *
> to int *) you are always safe.
> 
> Rationale: systems that have pointers to words and char smaller than word.
> There you can very well have pointers to void and pointers to less-than-word
> objects bigger than pointers to anything word-sized or bigger (e.g. they
> can be represented as word address + bit offset).  Conversion to the latter
> will lose offset and compiler is allowed to throw up on that at runtime.

Go Cray go.

> Moral: void * -> int * may lose parts of value and trigger undefined behaviour;
> int * -> void * loses information about type, is always revertible and always
> safe.  In assignment operator it's your responsibility to make sure that
> void * you are converting to int * is properly aligned (anything that started
> its life as int * will be).  In ?: C could
> 	* lose type information, allowing any values (result is void *); if
> you are sure that it's well-aligned, you can cast void * argument to int *
> or cast the result.
> 	* require the void * argument to be well-aligned, keep the type.
> 
> The former makes more sense...

Fair enough.

>>> Again, null pointer constant is not the same thing as null pointer to void.
>> I see.  I find it very strange that (void *)0 and (void *)(void *)0 have
>> different behavior.  I also find it strange that conditional expressions can't
>> convert void * to an arbitrary pointer as assignment can.
> 
> It would be nicer if C had __null__ as the *only* null pointer constant
> (with flexible type) and could refuse to accept anything else.  Too late
> for that, unfortunately.  As for conversions - see above.

Agreed; that seems far saner.  (Or, as long as we wishfully redefine the
original C spec, just NULL or null, sans underscores.)

>>> BTW, there's another painful area: what do we do to somebody who uses
>>> (void *)(69 + 1 - 70) as null pointer constant?  Currenly sparse doesn't
>>> recognize it as such; C standard does.  IMO the right thing to do is
>>> to add a flag that would switch to full-blown standard rules in that area
>>> ("integer constant expression returning 0" instead of basically "0 in some
>>> layers of ()") and flame to the crisp any wanker caught at actually doing
>>> that.  Any suggestions re sufficiently violent warning messages?
>> I didn't know that the C standard actually *required* constant folding.
>> Interesting.  Would it add excessively to compilation time to apply the usual
>> Sparse constant folding here?  If so, and if you really think this case
>> matters, let's have an option to turn on this constant folding, and warn
>> whenever we see it.
> 
> Usual sparse constant folding is _almost_ OK, provided that we play a bit
> with evaluate_expression() and let it decide if subexpression is an integer
> constant expression.  No prototype changes, we just get a global flag
> and save/restore it around sizeof argument handling and several other
> places.  It's actually pretty easy.  And if we get "it is an integer
> constant expression", well, then caller can call expand stuff.

Sounds reasonable to me.  Possibly better written as some kind of generic
parse-tree-walking operation, but this approach should work fine.

> "Almost" bit above refers to another bit of insanity, fortunately easily
> handled; we need division by zero to raise no error and just yield "the
> entire thing is not an integer constant expression with value 0".  That's
> exactly what longjmp() is for...

$ egrep -r 'setjmp|longjmp' ~/src/sparse/*
$

Let's keep it that way, please. :) Evaluation almost certainly should warn for
a compile-time divide-by-zero regardless, though we don't want to warn twice
for the same expression.  With the global "check for integer constant
expression" flag set, if evaluation encounters a compile-time divide-by-zero,
evaluation could just set a divided_by_zero flag.  Or something like that.

> Speaking of C standard, if you need access to the current one - yell.

I use http://c0x.coding-guidelines.com/ , which has the C99 spec and some
subsequent updates.

- Josh Triplett



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

  parent reply	other threads:[~2007-05-23  1:04 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-19  2:52 fun with ?: Al Viro
2007-05-22 21:40 ` Josh Triplett
2007-05-22 22:46   ` Al Viro
2007-05-22 23:24     ` Josh Triplett
2007-05-23  0:02       ` Al Viro
2007-05-23  0:25         ` Al Viro
2007-05-23  1:05           ` Josh Triplett
2007-05-23  4:53           ` Al Viro
2007-05-23 12:26             ` Morten Welinder
2007-05-23  1:03         ` Josh Triplett [this message]
2007-06-03  1:05           ` Al Viro
2007-05-23 14:25         ` Neil Booth
2007-05-23 14:32           ` Al Viro
2007-05-23 14:47             ` Neil Booth
2007-05-23 15:32               ` Al Viro
2007-05-23 23:01                 ` Neil Booth
2007-05-24  0:10                   ` Derek M Jones
2007-05-24  0:14                   ` Al Viro
2007-05-23 21:16             ` Derek M Jones
2007-05-23 21:59               ` Linus Torvalds
2007-05-23 23:29                 ` Derek M Jones
2007-05-24  0:02                   ` Al Viro
2007-05-24  0:29                   ` Linus Torvalds
2007-05-24  1:36               ` Brett Nash

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=465392E3.3000300@freedesktop.org \
    --to=josh@freedesktop.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@ftp.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.