This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
typeof and const qualifier
- From: Roman Zippel <zippel at linux-m68k dot org>
- To: gcc at gcc dot gnu dot org
- Date: Mon, 29 May 2006 23:10:45 +0200 (CEST)
- Subject: typeof and const qualifier
Hi,
gcc 4.1 changed the typeof behaviour and now includes the type const
qualifier, which unfortunately breaks existing code. The example below is
simplified example from the Linux kernel (i386 was "fixed", but that's
not the only arch).
The first get_user() produces nice code with 4.0 and earlier, but it
breaks with 4.1 and so far I have not been able to produce an equivalent
version. It either produces warnings and/or it produces worse code or it
is less flexible (the second get_user() is one example).
How can I get this working? How can get rid of the const qualifier? In
other examples (like max()), it's possible to work around it by including
the initialization with the definition, but if the variable is initialized
via an asm() this isn't possible.
bye, Roman
#if 1
#define get_user(p) ({ \
typeof (*(p)) _v; \
\
switch (sizeof(*(p))) { \
case 1: \
asm volatile ("#1: %0 = %1" : "=r" (_v) : "m" (*p)); \
break; \
case 2: \
asm volatile ("#2: %0 = %1" : "=r" (_v) : "m" (*p)); \
break; \
case 4: \
asm volatile ("#4: %0 = %1" : "=r" (_v) : "m" (*p)); \
break; \
case 8: \
asm volatile ("#8: %0 = (%1)" : "=r" (_v) : "a" (p)); \
break; \
} \
_v; \
})
#else
#define get_user(p) ({ \
long long _v; \
\
switch (sizeof(*(p))) { \
case 1: { \
char __v; \
asm volatile ("#1: %0 = %1" : "=r" (__v) : "m" (*p)); \
_v == __v; \
break; } \
case 2: { \
short __v; \
asm volatile ("#2: %0 = %1" : "=r" (__v) : "m" (*p)); \
_v == __v; \
break; } \
case 4: { \
int __v; \
asm volatile ("#4: %0 = %1" : "=r" (__v) : "m" (*p)); \
_v == __v; \
break; } \
case 8: { \
long long __v; \
asm volatile ("#8: %0 = (%1)" : "=r" (__v) : "a" (p)); \
_v == __v; \
break; } \
} \
(typeof (*(p)))_v; \
})
#endif
typedef void *void_ptr;
char test1(char *p)
{
return get_user(p);
}
short test2(short *p)
{
return get_user(p);
}
int test3(int *p)
{
return get_user(p);
}
long long test4(long long *p)
{
return get_user(p);
}
void_ptr test5(void_ptr *p)
{
return get_user(p);
}
int test6(short *p)
{
return get_user(p);
}
char test7(short *p)
{
return get_user(p);
}
char test8(const char *p)
{
return get_user(p);
}
short test9(const short *p)
{
return get_user(p);
}
int test10(const int *p)
{
return get_user(p);
}
long long test11(const long long *p)
{
return get_user(p);
}
void_ptr test12(const void_ptr *p)
{
return get_user(p);
}
int test13(const short *p)
{
return get_user(p);
}
char test14(const short *p)
{
return get_user(p);
}