User: Password:
|
|
Subscribe / Log in / New account

Declaring it volatile

Declaring it volatile

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

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


(Log in to post comments)

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 © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds