[Top][All Lists]

[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

     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
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

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 (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>

            (void)printf("returned from user-defined abort()\n");
            (void)printf("returned from user-defined exit()\n");
            return (EXIT_SUCCESS);

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

            (void)printf("user-defined abort() called...returning 

        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
        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

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.
>> 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]