linux-sparse.vger.kernel.org archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).