LWN.net Logo

Declaring it volatile

Declaring it volatile

Posted Aug 7, 2012 5:52 UTC (Tue) by viro (subscriber, #7872)
In reply to: Declaring it volatile by PaulMcKenney
Parent article: ACCESS_ONCE()

Have fun deciding how its semantics should look like for variably-modified types. Gets *really* interesting when combined with another gccism, of course - ({...}). In effect, that allows something that looked like local in one scope to leak outside; gcc used to ICE on fairly simple combinations.
IIRC, there had been other places where it didn't play well with very unexpected parts of standard (e.g. bitfield signedness; does special treatment of signed int in there extend to e.g. typeof(signed int)? Taken a few steps further it can, unless you are very careful, extend the distinction between int and signed int through all the type system...)


(Log in to post comments)

Declaring it volatile

Posted Aug 7, 2012 15:24 UTC (Tue) by PaulMcKenney (subscriber, #9624) [Link]

I must admit that I have never used "typeof(({ printf("From typeof()\n"); j; })) k = 1;" to declare a variable "k" of the same type as "j", but gcc appears quite happy with it.

And yes, gcc also seems quite happy to leak types from "({...})":

#include <stdio.h>

int main(int argc, char *argv[])
{
	int i = argc;
	signed int j = i;
	typeof(({ struct foo { int a; } q = { 1 }; printf("From typeof()\n"); q; })) k = { 2 };

	printf("i = %d, j = %d, k.a = %d\n", i, j, k.a);
	return 0;
}

Yow!!!

Fortunately for me, ACCESS_ONCE() does not depend on the semantics of typeof() applied to either "({...})"; or bitfields, although only because it is illegal to take the address of either of them. ;-)

Declaring it volatile

Posted Aug 7, 2012 15:35 UTC (Tue) by nybble41 (subscriber, #55106) [Link]

> Fortunately for me, ACCESS_ONCE() does not depend on the semantics of typeof() applied to either "({...})"; or bitfields, although only because it is illegal to take the address of either of them. ;-)

Are you sure about the first case? It seemed to work for me in GCC 4.5.1, at least in the case where the result of the "({...})" is a non-local l-value:

int x;
int *f(void)
{
return &({ x; });
}

Declaring it volatile

Posted Aug 7, 2012 15:57 UTC (Tue) by PaulMcKenney (subscriber, #9624) [Link]

I am using gcc 4.6.1, and the following emits a compiler error complaining that an lvalue is needed:
#include <stdio.h>

#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))

int q = 3;

int main(int argc, char *argv[])
{
	int i = argc;

	i = ACCESS_ONCE(({ printk("foo"); q; }));
	printk("i = %d\n", i);
}

Declaring it volatile

Posted Aug 7, 2012 18:35 UTC (Tue) by nybble41 (subscriber, #55106) [Link]

Interesting... it seems to work only if the variable is the only expression inside the statement expression. "&({ x; })" and "&({ ; x; })" are accepted, but "&({ x; x; })" and "&({ (void)0; x; })" both fail as you described. Perhaps the compiler is reducing the trivial one-expression form to a normal expression before performing the l-value check. It would make more sense to me to either fail both cases or move the "&" operator inside the brackets, i.e. "&({ ...; x; })" internally becomes "({ ...; &x; })".

Is there any particular reason the statement expression can't be an l-value, provided the final form is an l-value, or was that case simply considered too error-prone?

Declaring it volatile

Posted Aug 7, 2012 21:12 UTC (Tue) by paulj (subscriber, #341) [Link]

I have to ask, what is this ({…}) GCCism? I've searched the manual and online for it and "variably modified type" but not found anything useful.

Declaring it volatile

Posted Aug 7, 2012 21:26 UTC (Tue) by PaulMcKenney (subscriber, #9624) [Link]

Here is the URL you are looking for: http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds