g++-3.3.3 seems to be ignoring #pragma redirect_extname Attached to this bug are two preprocessor output files & the original source which they were created from. The .i has been created with gcc -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -E while the .ii has been created with g++ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -E I've then edited both files to comment out the definitions of statvfs and fstatvfs. This should make no difference to the compilation, since these names have been redifined by the pragma immediately preceeding them to statvfs64 and fstatvfs64 (due to the -D options I added to the compiler flags) When I compile the .i with gcc, it works fine -- I get a binary which contains a weak symbol for statvfs64() as expected. When I compile with g++ I get an error about undefined statvfs. If I don't comment out the definition of statvfs and compile the .ii with g++, then I get a weak symbol for statvfs() instead of the expected statvfs64() Given that defining -D_FILE_OFFSET_BITS=64 has resulted in off_t being defined to be 64 bits, linking the binary against statvfs() instead of statvfs64() results in junk being placed in the ouput.
Created attachment 6083 [details] statfs.c compiled with gcc-3.3.3
Created attachment 6084 [details] statfs.c compiled with g++-3.3.3
Created attachment 6085 [details] Original C source
As an extra bonus, gcc-3.2.3 on solaris (same machine) appears to be fubared when it comes to largefile support as well. Even if you don't define anything on the command line, gcc -v reveals that it defines both -D_LARGEFILE_SOURCE=1 and -D_LARGEFILE64_SOURCE=1 which completely breaks largefile support if you just want _LARGEFILE_SOURCE and not _LARGEFILE64_SOURCE, you can't have it. gcc-3.3.3 at least avoids this issue. (This is why it's a bit pointless to test with gcc-3.2 -- the extra define drops the #pragmas from the output anyway) $ /usr/local/gcc-3.2/bin/g++ -v statfs.c -o statfs Reading specs from /usr/local/gcc-3.2.3/lib/gcc-lib/sparc-sun-solaris2.8/3.2.3/specs Configured with: /home/phil/scratch/gcc/gcc-3.2.3/configure --prefix=/usr/local/gcc-3.2.3 --disable-shared Thread model: posix gcc version 3.2.3 /usr/local/gcc-3.2.3/lib/gcc-lib/sparc-sun-solaris2.8/3.2.3/cc1plus -v -D__GNUC__=3 -D__GNUC_MINOR__=2 -D__GNUC_PATCHLEVEL__=3 -D__GXX_ABI_VERSION=102 -Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME -D__sparc -D__sun -D__unix -Asystem=unix -Asystem=svr4 -D__NO_INLINE__ -D__STDC_HOSTED__=1 -D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 -D__EXTENSIONS__ -D__SIZE_TYPE__=unsigned int -D__PTRDIFF_TYPE__=int -D__WCHAR_TYPE__=long int -D__WINT_TYPE__=long int -D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc statfs.cpp -D__GNUG__=3 -D__DEPRECATED -D__EXCEPTIONS -quiet -dumpbase statfs.cpp -version -o /var/tmp//ccnWa0aD.s
The same problem occurs with 3.4 (CVS checkout of gcc-3_4-branch, as of 20040415): turing$ /usr/local/gcc-3.4/bin/gcc -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE statfs.c -o statfs turing$ nm -g statfs | grep statvfs [71] | 133364| 0|FUNC |GLOB |0 |UNDEF |statvfs64 turing$ /usr/local/gcc-3.4/bin/g++ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE statfs.c -o statfs turing$ nm -g statfs | grep statvfs [59] | 133516| 0|FUNC |GLOB |0 |UNDEF |statvfs
Confirmed with GCC 3.3 and GCC 3.4 However, such a kind of pragma is documented as available only in C and Objective-C; nothing is guaranteed for C++.
Normally, I might agree that this makes it technically 'not really a bug'. However, it's being used in the processed system headers that g++ is including, so it either a) ought to work or b) shouldn't be being used in those headers at all. (You imply that all the pragmas defined in the docs C-extensions part of the docs only apply to the C compiler and not the C++ compiler. Is this really the case?) #pragma redefine_extname is used in both stdio.h and rpc/svc.h in the processed gcc includes. The idea that stdio.h should behave differently depending on whether you're using gcc or g++ is, um, surprising at best I think!
> Normally, I might agree that this makes it technically 'not really a bug'. > However, it's being used in the processed system headers that g++ is > including, so it either a) ought to work or b) shouldn't be being used in > those headers at all. Yes, it ideally should work. It certainly works with the Sun C++ compiler. > (You imply that all the pragmas defined in the docs C-extensions part of the > docs only apply to the C compiler and not the C++ compiler. Is this really the > case?) I think so. They are implemented in c-pragma.c, which AFAICS is not linked in the C++ compiler. > #pragma redefine_extname is used in both stdio.h and rpc/svc.h in the > processed gcc includes. The idea that stdio.h should behave differently > depending on whether you're using gcc or g++ is, um, surprising at best I > think! The problem is, this pragma stuff is a C hack and I don't know how much work would be required to make it work with C++.
(In reply to comment #8) > I think so. They are implemented in c-pragma.c, which AFAICS is not linked > in the C++ compiler. I believe it is linked into the C++ compiler -- it's pulled in by gcc/gcc/cp/config-lang.in I think. $ strings cc1plus | grep redefine_extname malformed #pragma redefine_extname, ignored junk at end of #pragma redefine_extname #pragma redefine_extname conflicts with declaration redefine_extname looks conclusive. > > #pragma redefine_extname is used in both stdio.h and rpc/svc.h in the > > processed gcc includes. The idea that stdio.h should behave differently > > depending on whether you're using gcc or g++ is, um, surprising at best I > > think! > > The problem is, this pragma stuff is a C hack and I don't know how much work > would be required to make it work with C++. Would replacing it with #define X Y be sufficient? The sun c-compiler docs say: -------- #pragma redefine_extname old_extname new_extname The pragma causes every externally defined occurrence of the name "old_extname" in the object code to be "new_extname". Such that, at link time only the name "new_extname" is seen by the loader. If pragma redefine_extname is encountered after the first use of "old_extname", as a function definition, an initializer, or an expression, the effect is undefined. (Not supported in -Xs and -Xc modes.) -------- This looks to me like you could replace it with #define (in system headers at least) without any semantic change in the code as a result. Better if it could be fixed of course.
> I believe it is linked into the C++ compiler -- it's pulled in by > gcc/gcc/cp/config-lang.in I think. Indeed, thanks for the correction. And it turns out that it worked at some point (at least GCC 2.95.3): gax% g++295 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -o pr14962 pr14962.c gax% elfdump pr14962 | grep statvfs [13] 0x00020870 0x00000000 FUNC GLOB D 0 UNDEF statvfs64 [69] 0x00020870 0x00000000 FUNC GLOB D 0 UNDEF statvfs64 so we have a regression.
Works in 3.0.4 as well, but not 3.2.3 Will try 3.1.1 as soon as it has compiled
g++-3.1.1 ignores the pragma as well.
I think you slightly misunderstood the semantics of #pragma redefine_extname when you said: "I've then edited both files to comment out the definitions of statvfs and fstatvfs. This should make no difference to the compilation, since these names have been redifined by the pragma immediately preceeding them to statvfs64 and fstatvfs64 (due to the -D options I added to the compiler flags)". This does make a difference: the pragma redefines the *external* name only, not the internal name used within the compilation unit. You didn't see the problem with the C compiler but passing -Wall would have given: statfs_test.c:10: warning: implicit declaration of function `statvfs' Of course this is a hard error with the C++ compiler. So you can't comment out the declaration of the functions, even if they have been "pragma-ized". A good news is that the mechanism is not that broken in the C++ compiler. For example, it works for the following code: #pragma redefine_extname old_name1 new_name1 extern "C" int old_name1(void); extern "C" int old_name2(void) asm("new_name2"); int foo1(void) { return old_name1(); } int foo2(void) { return old_name2(); } The assembly contains new_name1 and new_name2 only. The mechanism doesn't work with your testcase because of an identifier overloading problem. We have: typedef struct statvfs { unsigned long f_bsize; unsigned long f_frsize; fsblkcnt_t f_blocks; fsblkcnt_t f_bfree; fsblkcnt_t f_bavail; fsfilcnt_t f_files; fsfilcnt_t f_ffree; fsfilcnt_t f_favail; unsigned long f_fsid; char f_basetype[16]; unsigned long f_flag; unsigned long f_namemax; char f_fstr[32]; unsigned long f_filler[16]; } statvfs_t; pragma redefine_extname statvfs statvfs64 int statvfs(const char *, statvfs_t *); If you change "statvfs" to anything else in "struct statvfs", "statvfs64" will be emitted in the assembly output instead of "statvfs" for the function call. Now we have to devise a fix...
Fixing.
You're quite right. I thought I'd tested it with g++, but obviously I hadn't. Should have kept a table of all the combinations of code and compiler I'd tried...
Subject: Bug 14962 CVSROOT: /cvs/gcc Module name: gcc Changes by: ebotcazou@gcc.gnu.org 2004-05-07 06:58:00 Modified files: gcc : ChangeLog c-pragma.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/other: pragma-re-2.C Log message: PR c++/14962 * c-pragma.c (handle_pragma_redefine_extname): Only change the assembler name of FUNCTION_DECLs and VAR_DECLs. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.3597&r2=2.3598 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-pragma.c.diff?cvsroot=gcc&r1=1.67&r2=1.68 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3726&r2=1.3727 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/other/pragma-re-2.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 14962 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: ebotcazou@gcc.gnu.org 2004-05-07 07:07:37 Modified files: gcc : ChangeLog c-pragma.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/other: pragma-re-2.C Log message: PR c++/14962 * c-pragma.c (handle_pragma_redefine_extname): Only change the assembler name of FUNCTION_DECLs and VAR_DECLs. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.436&r2=2.2326.2.437 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/c-pragma.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.66.2.1&r2=1.66.2.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.174&r2=1.3389.2.175 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/other/pragma-re-2.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1
See http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00235.html .
Subject: Re: [3.3/3.4/3.5 regression] g++ ignores #pragma redefine_extname On Fri, May 07, 2004 at 07:23:10AM -0000, ebotcazou at gcc dot gnu dot org wrote: > ------- Additional Comments From ebotcazou at gcc dot gnu dot org 2004-05-07 07:23 ------- > See http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00235.html . Excellent; many thanks for your efforts, Phil