Bug 14962 - [3.3/3.4/4.0 regression] g++ ignores #pragma redefine_extname
Summary: [3.3/3.4/4.0 regression] g++ ignores #pragma redefine_extname
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: 3.4.1
Assignee: Eric Botcazou
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-04-15 09:27 UTC by phil
Modified: 2004-10-30 21:11 UTC (History)
1 user (show)

See Also:
Host: sparc-sun-solaris2.8
Target: sparc-sun-solaris2.8
Build: sparc-sun-solaris2.8
Known to work: 2.95.3 3.0.4
Known to fail: 3.1.1 3.2.3 3.3.2 3.3.3 3.4.0 4.0.0
Last reconfirmed: 2004-04-20 12:26:59


Attachments
statfs.c compiled with gcc-3.3.3 (3.78 KB, text/plain)
2004-04-15 09:28 UTC, phil
Details
statfs.c compiled with g++-3.3.3 (4.02 KB, text/plain)
2004-04-15 09:29 UTC, phil
Details
Original C source (183 bytes, text/plain)
2004-04-15 09:30 UTC, phil
Details

Note You need to log in before you can comment on or make changes to this bug.
Description phil 2004-04-15 09:27:15 UTC
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.
Comment 1 phil 2004-04-15 09:28:25 UTC
Created attachment 6083 [details]
statfs.c compiled with gcc-3.3.3
Comment 2 phil 2004-04-15 09:29:58 UTC
Created attachment 6084 [details]
statfs.c compiled with g++-3.3.3
Comment 3 phil 2004-04-15 09:30:23 UTC
Created attachment 6085 [details]
Original C source
Comment 4 phil 2004-04-15 09:55:23 UTC
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
Comment 5 phil 2004-04-15 13:14:50 UTC
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

Comment 6 Eric Botcazou 2004-04-20 12:26:58 UTC
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++.
Comment 7 phil 2004-04-20 12:47:14 UTC
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!
Comment 8 Eric Botcazou 2004-04-20 12:56:12 UTC
> 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++.
Comment 9 phil 2004-04-20 13:14:37 UTC
(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.
Comment 10 Eric Botcazou 2004-04-20 13:35:49 UTC
> 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.
Comment 11 phil 2004-04-20 14:44:49 UTC
Works in 3.0.4 as well, but not 3.2.3

Will try 3.1.1 as soon as it has compiled
Comment 12 phil 2004-04-20 16:10:16 UTC
g++-3.1.1 ignores the pragma as well.
Comment 13 Eric Botcazou 2004-05-04 08:06:27 UTC
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...
Comment 14 Eric Botcazou 2004-05-04 12:14:16 UTC
Fixing.
Comment 15 phil 2004-05-04 14:05:59 UTC
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...

Comment 16 GCC Commits 2004-05-07 06:58:04 UTC
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

Comment 17 GCC Commits 2004-05-07 07:07:47 UTC
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

Comment 18 Eric Botcazou 2004-05-07 07:23:06 UTC
See http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00235.html .
Comment 19 phil 2004-05-12 15:26:01 UTC
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