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...)
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]