bug-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: bison-1.875: can abort() et al be user defined?


From: Nelson H. F. Beebe
Subject: Re: bison-1.875: can abort() et al be user defined?
Date: Fri, 3 Jan 2003 19:36:06 -0700 (MST)

I wrote earlier today, quoting the ISO C99 Standard (with similar
wording in the C89 Standard, section 4.1.2.1)

     7.1.3 Reserved identifiers

     -- All identifiers with external linkage in any of the following
        subclauses (including the future library directions) are
        always reserved for use as identifiers with external
        linkage.154)
 
Paul Eggert reponded:

>> ...
>> Yes, that's the rule that I was talking about.  A strictly conforming
>> Standard C program cannot define "abort" as an identifier with
>> external linkage.
>> ...

Probing further, I find the Rationale document attached to C89 (and
sadly, absent from C99) on p. 72:

       To give implementors maximum latitude in packing library
       functions into files, all external identifiers defined by the
       library are reserved (in a hosted environment).  This means, in
       effect, that no user supplied external names may match library
       names, <EM>not even if the user function has the same
       specification</EM>. 

Paul and the X3J11 Committee are in agreement here, but the Rationale
is not binding, and it seems to me (and probably other `language
lawyers') that the language of 4.1.2.1 (1989) and 7.1.3 (1999) says
only that if foo() is a library function, then foo() must remain a
function that can be linked externally.  It does not seem to say that
foo() cannot be a user-provided function that is linked externally.  I
read 7.1.3 as saying that "int abort;" is illegal, but "void
abort(){...}" is a legal user redefinition.

In practice, most C compiler writers today seem to agree with me: the
generated code for library routines normally calls them exactly like
any other user code, and thus, library versions can be overridden.

Here is an example:

        % cat redef2.c
        #include <stdio.h>
        #include <stdlib.h>

        int
        main(void)
        {
            abort();
            (void)printf("returned from user-defined abort()\n");
            exit(50);
            (void)printf("returned from user-defined exit()\n");
            return (EXIT_SUCCESS);
        }

        % cat redef2b.c
        #include <stdio.h>

        void 
        abort(void)
        {
            (void)printf("user-defined abort() called...returning 
immediately\n");
        }

        void
        exit(int status)
        {
            (void)printf("user-defined exit(%d) called...returning 
immediately\n", status);
        }

On Sun Solaris, I find:

        % lcc redef2.c redef2b.c && ./a.out ; echo $status
        redef2.c:
        redef2b.c:
        user-defined abort() called...returning immediately
        returned from user-defined abort()
        user-defined exit(50) called...returning immediately
        returned from user-defined exit()
        user-defined exit(0) called...returning immediately
        0

Similar results were obtained with cc, c89, gcc (2.95.3).  With CC and
g++, the library abort() was called instead, producing a core dump.

On GNU/Linux Intel IA-32 with gcc-3.2.1, the library abort() was
called.  With lcc, the code went into an infinite loop.  With the
Portland Group compiler, pgcc, my versions were called, but with their
C++ compiler, pgCC, the library abort() was called.

On Apple Darwin, both gcc and g++ (3.2.1) produced infinite loops.

On GNU/Linux on Alpha, my versions were called with gcc, and the
library version with g++.

On Alpha OSF/1, CC and g++ called the library abort(); lcc, cc, c89,
and gcc (2.95.3) called my versions.

On IBM AIX 4.2, cc called my versions, and CC called the library version.

On SGI IRIX 6.5, g++ (3.2.1) and CC called the library abort(), while
cc, c89, gcc, and lcc called my versions.

The evidence of disagreement among C compiler writers about the meaning
of this language niche is clear.  C++ compilers are mostly in
agreement: call the library version.

The 1998 ISO C++ Standard says that such redefinitions produce
undefined behavior:

>> ...
>>      17.1.17 reserved function [defns.reserved.function]
>>      a function, specified as part of the C++ Standard Library, that
>>      must be defined by the implementation.  If a C++ program provides
>>      a definition for any reserved function, the results are
>>      undefined.
>> 
>>      17.4.3.1 Reserved names [lib.reserved.names]
>> 
>>      It is undefined for a C++ program to add declarations or
>>      definitions to namespace std or namespaces within namespace std
>>      unless otherwise specified.  A program may add template
>>      specializations for any standard library template to namespace
>>      std.  Such a specialization (complete or partial) of a standard
>>      library template results in undefined behavior unless the
>>      declaration depends on a user-defined name of external linkage
>>      and unless the specialization meets the standard library
>>      requirements for the original template.
>> ...

-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- Center for Scientific Computing       FAX: +1 801 581 4148                  -
- University of Utah                    Internet e-mail: address@hidden  -
- Department of Mathematics, 110 LCB        address@hidden  address@hidden -
- 155 S 1400 E RM 233                       address@hidden                    -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe  -
-------------------------------------------------------------------------------




reply via email to

[Prev in Thread] Current Thread [Next in Thread]