[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 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 -
-------------------------------------------------------------------------------
- Re: bison-1.875: can abort() et al be user defined?,
Nelson H. F. Beebe <=