gcc 2.95.2: attribute((regparm(N))) and function ptr type casts

Fergus Henderson fjh@cs.mu.OZ.AU
Fri Nov 24 01:55:00 GMT 2000


gcc 2.95.2's handling of calling convention attributes in function
pointer types is very nasty: it silently ignores them.  This
behaviour is very counter-intuitive, and not documented.

At very least gcc ought to issue a warning that the attribute is
ignored.  But a much nicer solution would be to make attributes that
affect the calling convention a fully-fledged part of the function type.

The following program demonstrates the problem.

$ cat bug.c
	#define MR_CALL __attribute__((__regparm__(2)))

	int MR_CALL foo(int x, int y, int z, int a) {
		return x + y + z + a;
	}

	int bar(int (MR_CALL *g)(int,int,int,int)) {
	#if 0
		/* This works fine */
		return (*g)(1,2,3,4);
	#else
		/* Adding a superfluous cast to the same type breaks it: */
		/* GCC ignores the MR_CALL in the function pointer type. */
		return (*(int (MR_CALL *)(int,int,int,int))g)(1,2,3,4);
	#endif
	}


	#include <stdio.h>
	int main(void) {
		printf("%d\n", bar(foo));
		return 0;
	}

$ gcc bug.c
$ ./a.out
-1073745592

The following gdb transcript shows that the problem is that
gcc uses the wrong calling convention for the call to `g'

	$ gcc -g bug.c
	$ gdb ./a.out
	(gdb) b main
	Breakpoint 1 at 0x804842e: file bug.c, line 21.
	(gdb) r
	Breakpoint 1, main () at bug.c:21
	21              printf("%d\n", bar(foo));
	(gdb) s
	bar (g=0x80483e0 <foo>) at bug.c:14
	14              return (*(int (MR_CALL *)(int,int,int,int))g)(1,2,3,4);
	(gdb) s
	foo (x=-1073745612, y=1, z=1, a=2) at bug.c:4
	4               return x + y + z + a;
	(gdb)

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: < http://www.cs.mu.oz.au/~fjh >  |     -- the last words of T. S. Garp.


More information about the Gcc-bugs mailing list