Topic: atexit() behavior


Author: AllanW@my-dejanews.com
Date: 1998/12/21
Raw View
In article <m7EsCGBuuoe2EwX5@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> In article <367A4859.D1124D1A@physik.tu-muenchen.de>, Christopher
> Eltschka <celtschk@physik.tu-muenchen.de> writes
> >That's the point why even with functions in extern "C" linkage
> >written in C++, EH can be a problem. In the imaginary EH mechanism
> >above, the calling function won't supply the hidden parameter the EH
> >mechanism relies on.
>
> I am not sure where you get this idea for a hidden parameter for EH.
> Perhaps some implementor could explain this because I am completely
> unaware that such a mechanism would be used to support EH (certainly if
> there is no exception specification provided)

When there is no exception specification provided we must support ANY
type of exception. You probably meant "when there is an empty exception
specification provided."

I'm not an implementor, so perhaps I'm not qualified to answer you. But
I think that a certain level of understanding can be reached simply by
trying to play the part of the compiler. This is even more true if you
have any experience with any assembly language, but even if you don't,
it may be true.

Every general-purpose computer language must supply some mechanism to
call a routine. This involves saving the current execution address
somewhere and transferring control to some other routine. When that
routine is finished, it must be able to retrieve the saved address
and transfer control back to the calling routine. Most CPU's today
have a built-in stack for this purpose; those that don't generally
have a way for the operating system and/or language run-time system
to create one. Before this was common, some processors stored the
return address in the first few bytes of the routine itself. This was
quite effective but it did make recursion difficult.

Usually (but not always), the machine architecture provides a
convenient standard mechanism for calling routines, although
details about how to pass arguments may vary quite a bit. For
instance, these days it is very common for CPU's to have a
"stack" architecture. Until recently, EH was not a
consideration in this. But now, modern C++ compilers must deal
with the very real possibility that inside the function, it
may be neccesary to transfer control to someplace OTHER than
the place from which it was called. This might not even be
inside the function that called us, which means (on
stack-oriented machines) that any changes made to the stack
since then must be un-done.

How is the C++ compiler to accomplish this? We can't look at
how it's done in other languages, because no other language
does this (yet).

If mixed-language programming was not a concern, then one way
to accomplish this would be to have each function-call
instruction followed in memory with data used to handle
exceptions. When a routine exits without throwing an
exception, it first increments the return address to skip past
this data. This is a common assembly-language trick for
passing constant arguments, such as a function number for a
call to the operating system. Unfortunately, it is not
compatible with any other computer language.

We could instead put the address of a catch block in some
register which is not normally used by other languages, but IS
normally preserved. This would correspond to Cristopher
Eltschka's "hidden parameter."

A variation on this scheme is to have every function call set
the value of some register to 0 (no exception) or something
else (perhaps the address or type-id of the exception). Every
function call that was NOT marked "throw()" would have to check
this value when the called function returned. Here we have a
"hidden result," which is at least conceptually similar to
Christopher Eltschka's "hidden parameter."

Another way to accomplish this is to create a second stack,
called the exception stack. Whenever a try block is entered,
we push the address of the corresponding catch block, plus the
"normal" stack pointer. Exiting the try block restores these
two items. Throwing an exception requires jumping to the address
on top of the stack, and resetting the "normal" stack from the
saved value.

If the last idea above is used, then the "exception stack"
pointer could be the "hidden parameter" that Christopher
Eltschka spoke of. Alternatively, we could use some hidden
global variable; this might allow us to propogate exceptions
through non-C++ functions.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/22
Raw View
In article <75mfu8$r5m$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
writes
>We could instead put the address of a catch block in some
>register which is not normally used by other languages, but IS
>normally preserved. This would correspond to Cristopher
>Eltschka's "hidden parameter."

There is simply no way that a compiler can determine the address of a
catch block that will handle the exception even when coding a specific
call.  Exceptions are handled dynamically, and just about have to be in
C++.  The exception mechanism must be able to locate the nearest
appropriate catch block at run time bys searching for the information.
Of course this search could be done at the time of call the function but
that would impose the cost of an exception even when (as normal) that
information was not used.

I would go so far as to say that a compiler that evaluated the argument
for such a hidden parameter would not have a market.

If any implementor knows better I would be happy to be corrected.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/12/22
Raw View
Francis Glassborow wrote:
>
> In article <75mfu8$r5m$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
> writes
> >We could instead put the address of a catch block in some
> >register which is not normally used by other languages, but IS
> >normally preserved. This would correspond to Cristopher
> >Eltschka's "hidden parameter."
>
> There is simply no way that a compiler can determine the address of a
> catch block that will handle the exception even when coding a specific
> call.  Exceptions are handled dynamically, and just about have to be in
> C++.  The exception mechanism must be able to locate the nearest
> appropriate catch block at run time bys searching for the information.
> Of course this search could be done at the time of call the function but
> that would impose the cost of an exception even when (as normal) that
> information was not used.

I'm no implementor; however I think the basic principles are
clear enough so that you don't need to be an implementor
to understand them.

Of course, when compiling a function, the comiler cannot know
from wher the function is called. But at the place _where the
function is called_, the compiler trivially knows from where it
is called. If the function itself has to do cleaning up (be it
a try/catch, or just a destructor), it knows so, and therefore
it's IMHO a logical step to tell this to the called function.
The way a calling function tells something to a called function
is parameter passing. In this scheme, if the function doesn't
have to do any cleaning up, it will simply forward it's own
hidden handler parameter.

For example, a compiler might translate the following code

class X { public: X(); ~X(); };
class something {};

extern "C" void c();

void f() { throw something; }

void g()
{
  X x;
  f();
  c();
 }

void h()
{
  try
  {
    g();
  }
  catch(something)
  {
    some code;
  }
  c();
};

into

f:
  create stack frame
; throw something
  allocate memory for something object
  construct the something object
  delete stack frame
  pop return address from stack
    (so the stack pointer now points to the last pushed parameter)
  return (using that parameter as return address)
; normal return sequence optimized away

g:
  create stack frame
; X x;
  construct x
; f()
  push address of _g_exception_return as hidden parameter
  call f (which includes pushing the return address to the stack)
; c()
  call c (no parameters pushed at all before that)
; normal cleanup
  destruct x
  destroy stack frame
  return (using normal address)

_g_exception_return: ; the return after exception goes here
  destruct x
  destroy stack frame
  pop resturn address (so hidden parameter to g becomes top of stack)
  return (using that hidden parameter)

h:
  create stack frame
; try: no code specifically to this; modifies used labels, though
; g()
  push address of _h_catch_block
  call g
_h_after_catch:
; c()
  call c
; cleanup
  destroy stack frame
  return (to normal return address)

_h_catch_block:
  test if exception is of type something
  if not, jump _h_catch_block_2
  (code from catch(something))
  destruct the exception object and free its memory
  jump _h_after_catch ; exception is handled
_h_catch_block_2:
; no further catch block: pass on
  destroy stack frame
  pop return address (so hidden parameter is top of stack)
  return (to hidden parameter)


Note that this gives as overhead in the normal path just one
extra parameter per function call. Moreover, on a machine with enough
registers, one can reserve one register for that hidden parameter,
and therefore reduce the extra parameter passing to one register
load instruction per constructor call or try statement, and
no extra overhead per function call. In this case, of course
the function return address must be replaced instead of popped
in the exception throw case.

Indeed, I cannot imagine any EH mechanism which doesn't rely
on some hidden parameter (which need not necessarily be a
return address, though).
The table lookup method avoids that hidden parameter by
observing that the exception return value is always the same
for the same normal return address. Therefore it uses a
global table to look up that hidden parameter. This of course
has the advantage that the normal path is speeded up at the
cost of the exceptional path (which must find the hidden
parameter in the table, instead of just getting it directly
from the parameters).

>
> I would go so far as to say that a compiler that evaluated the argument
> for such a hidden parameter would not have a market.

If you want to say that only "no-overhead" solutions (that is,
table driven EH) will be the only who survive, maybe. But
otherwise, there will be a hidden parameter. The only
question is if it is passed in a way that non-C++ functions
will have to care (f.ex. an extra exception stack is a way of
parameter passing as well, and so is passing via global variable).

In some sense, the hidden parameter of the table driven EH is
just the return address.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/22
Raw View
In article <jia9kRAT+hf2EwOw@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <01be2c59$1720f560$15dcdcdc@mentor.magnet.at>, Alfred Kellner
><alfkellner@magnet.at> writes
>>17.4.4.8 Restrictions on exception handling
>> None of the functions from the Standard C library shall report an
>> error by throwing an exception, 176) unless it calls a program-
>> supplied function that throws an exception.
>>note 176)
>>       That is, the C library functions all have a
>>       throw() exception-specification. ...
>><quote>
>
>1) Implies that extern "C" functions can have exception specifications
>2) Just as well footnotes are non-normative because that one conflicts
>with the 'unless it calls ...' in the main text.  Clearly functions such
>as qsort() and bsearch() must be able to propagate exceptions if that
>text is to have any meaning.

I believe the intent is to allow, but not require, qsort and bsearch
to propagate exceptions.

The text on qsort makes this clear, except it's only a note
in CD2 25.4/2 and notes are of course non-normative.

Requiring that extern "C"-linkage implies an empty throw-specification
if the exception handling is incompatible with C calling conventions
would IMHO not break this.
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/22
Raw View
In article <m7EsCGBuuoe2EwX5@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <367A4859.D1124D1A@physik.tu-muenchen.de>, Christopher
>Eltschka <celtschk@physik.tu-muenchen.de> writes
>>That's the point why even with functions in extern "C" linkage
>>written in C++, EH can be a problem. In the imaginary EH mechanism
>>above, the calling function won't supply the hidden parameter the EH
>>mechanism relies on.
>
>I am not sure where you get this idea for a hidden parameter for EH.
>Perhaps some implementor could explain this because I am completely
>unaware that such a mechanism would be used to support EH (certainly if
>there is no exception specification provided)

In summary:

Exception handling that using exception tables puts restrictions on
the calling conventions of the C-compiler if we want C-code to
propagate exceptions.

The 'hidden parameter' is the frame-pointer on the sparc.

Details (much longer):

I'm not an implementor, but I tried to understand the problem with
egcs-1.0.3 implementation of exceptions on the sparc (which does not
allow exceptions to propagate through C-code).

Although the documentation is out of date (setjmp-based exceptions are
no longer the default) I found the following:

It has exception tables containing ranges of PC addresses and for each
region it unwinds the exceptions and then basically re-throws the
exception (which finds the address of the next region etc).

I believe this is one of the solutions for exception handling that
is generally recommended if we want low overhead for code that don't
throw exceptions. It is thus not a egcs-specific solution.

The problem with:

extern "C" int compar(const void*a,const void*b) {throw 4;}
...
 qsort(x,sizeof(x)/sizeof(x[0]),sizeof(x[0]),compar);

is that after destroying local variables in compar it has a PC-value
within qsort. Since qsort was compiled with a C-compiler the PC-value
is not found in the exception tables and the program terminates.

If the stack-frames are well-organized (using save/restore on the sparc)
one could in this case search for the caller of qsort (etc.) and then
carry on the stack-unwinding.

I believe Sun's CC (v4.2) uses this technique combined with exception tables,
because it can catch exceptions thrown by C++-functions called
by C-functions compiled by a C-compiler if:
* One uses Sun's C-compiler to compile the C-routine.
* One uses gcc -mno-flat (the default) to compile the C-routine.
This generates save/restore for the frame-pointer.

If qsort was compiled with 'gcc -mflat' and we call qsort
from C++ code compiled by Sun's CC, it crashes (calling abort)
instead of propagating the exception.

This is course not the fault of Sun's compiler, neither a problem
with gnu's c-compiler (although save/restore might be required by Sun's
ABI), but indicates a more general problem: exception propagation
puts requirement on the calling conventions of the C-compiler, unless
we use setjmp-based techniques.

Other architectures might not have as well-organized stack-frames,
and I doubt that the intention of the C++ standard was to require
C compilers to generate frame-pointers.

A possible remedy:

The standard should allow a compiler to treat extern "C" func() {...}
as implying extern "C" func() throw() {...} and thus catching the exceptions
before they generate problems for functions written in C.
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/22
Raw View
In article <01be2c59$1720f560$15dcdcdc@mentor.magnet.at>,
Alfred Kellner <alfkellner@magnet.at> wrote:
>
>Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
>> ><tangent>
>> >Is it legal and meaningful to put a throw() clause on an extern "C"
>> >declaration?:
>> >    extern "C" int   cfunc(int a) throw();
>> ></tangent>
>>
>> I believe so, but how do write a function (with C++-linkage) accepting
>> a pointer to such a function?
>>
>// type: pointer to C-function ... without exception-specification
> extern "C"  typedef void (*PF)();
>// bar has C++linkage and takes a pointer to C-function
> void bar ( PF fp_c ) {  fp_c(); }
>// as above: declaration for C-function + exc.spec
> extern "C"  void cfunc() throw();
>// use it
> void foo() { bar( cfunc ); }

True it satisfies the given constraints, but I meant a function
with C++-linkage that _only_ accepts a function with C-linkage
and empty throw-specification.

The obvious attempt:

void bar(extern "C" void (*PF) throw());

Is illegal because linkage-specifications cannot be used here.
This is generally fixed by using a typedef to declare the linkage.

extern "C" {typedef void (*PF)() throw();}
void bar(PF fp_c);

But this is illegal because exception-specifications are forbidden
in typedefs.

I don't know if there exists a way to actually declare the function bar().

...
> 15.4 Exception specifications
> An exception-specification shall appear only on a function declarator
> in a declaration or definition.
> An exception-specification shall not appear in a typedef declaration.
> Example:
> void (*fp) () throw (int); // OK
> typedef int (*pf) () throw(int); // ill-formed

A change in wording between CD2 and the final standard, but exception
specifications are still forbidden in typedef declarations
(assumedly because they are not part of the type).

>....
>17.4.4.8 Restrictions on exception handling
> None of the functions from the Standard C library shall report an
> error by throwing an exception, 176) unless it calls a program-
> supplied function that throws an exception.
>note 176)
> That is, the C library functions all have a
> throw() exception-specification. ...

This says nothing about other functions with C linkage; besides
the standard is not entirely clear.


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/22
Raw View
In article <367A4859.D1124D1A@physik.tu-muenchen.de>, Christopher
Eltschka <celtschk@physik.tu-muenchen.de> writes
>That's the point why even with functions in extern "C" linkage
>written in C++, EH can be a problem. In the imaginary EH mechanism
>above, the calling function won't supply the hidden parameter the EH
>mechanism relies on.

In article <m7EsCGBuuoe2EwX5@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:>
> I am not sure where you get this idea for a hidden parameter for EH.
> Perhaps some implementor could explain this because I am completely
> unaware that such a mechanism would be used to support EH (certainly if
> there is no exception specification provided)

> In article <75mfu8$r5m$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
> writes
[Several alternative implementations of passing try/catch information,
 including]
>We could instead put the address of a catch block in some
>register which is not normally used by other languages, but IS
>normally preserved. This would correspond to Cristopher
>Eltschka's "hidden parameter."

In article <+uK6nJBT1tf2Ewt8@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> There is simply no way that a compiler can determine the address of a
> catch block that will handle the exception even when coding a specific
> call.

Sorry; I didn't explain because I thought it was obvious. (Also, I
should have said "try block" instead of "catch block".)

Using this technique, at the point of a function call, the address
of the nearest try block may be part of the calling function, in
which case the address is known. In this case, we simply pass in
the address as a parameter (perhaps a register).

If the current function has no active try block, then the nearest
try block is in the function that called this one, or the function
that called that one, or ...  In this case, we already have the
address of the nearest try block in a parameter (perhaps a
register), and we simply pass this value as the hidden parameter
value.

Function main() is a special case, but is not worthy of discussion
here. (Use your imagination.)

You're right, of course; we haven't identified the address of a
catch block that will handle an exception. We've identified the
address of a try block which has catch blocks that MIGHT handle
the exception. If the exception doesn't match a corresponding
catch() block, the try block simply transfers control to the
previous try block, and so on.

> Exceptions are handled dynamically, and just about have to be in
> C++.

Absolutely. And the scheme above *IS* dynamic, in the sense that
different calls to the same function may pass different values for
the hidden parameter.

> The exception mechanism must be able to locate the nearest
> appropriate catch block at run time bys searching for the information.

It doesn't have to be a search. If you have the address of the
nearest try block, and IT has the address of the previous try
block, and so on, then there is nothing to search for.

> Of course this search could be done at the time of call the function but
> that would impose the cost of an exception even when (as normal) that
> information was not used.

No, the "cost of an exception" occurs when an exception is thrown.
We would have to transfer control to the appropriate try block, and
fix up the stack (if there is one).

Every function call would incur the cost of maintaining the address
of the nearest try block. Is this what you meant? But this is hardy
excessive, especially if functions agree to preserve most registers
(the normal way of doing business on most systems). For instance,
systems with a stack already incur the cost of maintaining the
top-of-stack address, which just means that every PUSH is
accompanied by a matching POP. Systems that use an "Argument
Pointer" register incur the cost of maintaining the previous AP
value, which generally means PUSHing it at the beginning of the
routine and POPping it at the end. And so on.

> I would go so far as to say that a compiler that evaluated the argument
> for such a hidden parameter would not have a market.

I'm not certain what you mean by "evaluate the argument" in this
context. Evaluating an expression is a C++ concept, while the
"hidden" parameter we've been discussing is an implementation
detail.

In any case, the hidden parameter is either a copy of the value
passed in, or is the address of a local instruction, and since
it wouldn't be any bigger than a void*, the overhead wouldn't
be extreme.

> If any implementor knows better I would be happy to be corrected.

And so would I.

In fact, as I'm not an implementor, let's assume that I've made
at least one or two design errors. Please feel free to point
them out, and your opinion: does this error invalidate the
entire concept, as I've expressed it here?

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/22
Raw View
In article <75nvc5$jhk$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>I believe the intent is to allow, but not require, qsort and bsearch
>to propagate exceptions.

I know the intent, but if there is a conflict between normative text and
a footnote the normative text wins.  Clearly a strictly standard program
cannot have qsort, bsearch etc. propagate an exception.

I think this is a defect (can the moderators consider logging it as such
for Dublin?)

>
>The text on qsort makes this clear, except it's only a note
>in CD2 25.4/2 and notes are of course non-normative.
>
>Requiring that extern "C"-linkage implies an empty throw-specification
>if the exception handling is incompatible with C calling conventions
>would IMHO not break this.

Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/22
Raw View
My thanks to those who explained the origins and working of a hidden
parameter to deal with exception handling.

My first thoughts were to wonder if it might be possible to take
advantage of the latitude some C implementations allow for passing more
arguments than parameters (the unused ones are just never 'popped' off
the stack, then I realised that this would not work because you could
have sequences with C++-function calling C-function calling C-function
calling C++-function

Therefore I think that the C++ Standard Library needs to overload qsort
etc. with C++ versions that take C++ funct-ptrs as their last parameter.



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: David R Tribble <dtribble@technologist.com>
Date: 1998/12/18
Raw View
AllanW@my-dejanews.com writes
> But the primary issue isn't what happens when some other language
> throws, but what happens with languages such as C, that we know
> do *NOT* implement exceptions. Do these languages propogate
> exceptions that are thrown from C++? For instance, C++ function
> "func1" calls Fortran function "func2", which in turn calls C++
> function "func3". Func3 throws an exception -- what happens?
> Can func1 catch it? Does it jump directly to
> unhandled_exception? Does the program instantly crash? I don't
> believe that the standard says anything about this.

Francis Glassborow wrote:
> I think you are probably correct, OTOH any function declaration that
> lacks a throw specification is supposed to be able to throw anything.
> I think that means that should a C++ function call an extern "C"
> function which in turn calls a C++ function (presumably because the
> body of the extern "C" function has been implemented in C++) then an
> exception can propagate straight through.

Or would it be more correct to say that 'extern "C"' implies a
'throw()' clause, meaning that since it's a C (not C++) function,
that it can't throw anything at all?  If so, then an extern "C" func
that calls another C++ func that throws would be violating the
implied no-throw clause of the extern "C" func.

<tangent>
Is it legal and meaningful to put a throw() clause on an extern "C"
declaration?:
    extern "C" int   cfunc(int a) throw();
</tangent>

-- David R. Tribble, dtribble@technologist.com --


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/18
Raw View
In article <5H2rtGAnhEe2Ew22@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>I think you are probably correct, OTOH any function declaration that
>lacks a throw specification is supposed to be able to throw anything.  I
>think that means that should a C++ function call an extern "C" function
>which in turn calls a C++ function (presumably because the body of the
>extern "C" function has been implemented in C++) then an exception can
>propagate straight through. Note that should the definition of an
>extern "C" function be provided as C++ source code there is no reason
>why it should not throw and catch.
>
>
>Now that leaves the cases where the definition is not in C++, but then
>the rules are outside the scope of C++.  If a Fortran program can call a
>C++ function then it is up to the Fortran implementors to deside what to
>do about exceptions.

Why should the Fortran/C program be aware of it?

Consider:

extern "C" void CRoutine(int f(int&));
extern "C++" int f(int&x) {...}
extern "C" int MyC(int&x) {return f(x);}

{
  ...
  CRoutine(MyC);
  ...
}

The CRoutine is given an alleged C-routine (MyC),
which in contrast to normal C-routines can throw an exception.

This seems like a perfectly legal program, but if the exception handling
is incompatible with C it will create chaos.

That's not nice, and one solution (two posts back in this thread)
would be to interpret:

extern "C" int MyC(int&);

as

extern "C" int MyC(int&) throw();

(And similarly with extern "Fortran") It prevents chaos when sending
pointers to functions to non-C++ code, but it does not allow you to
randomly attach non-C++ linkage to functions.

Since there is little (no?) reason to add non C++ linkage to
functions written in C++, unless when you want to send them
as pointers to functions expecting non C++ functions, I see no harm.

The problem is that the standard is very silent on the matter
of non-C++ functions throwing exceptions, and does not mention
any problems with having non-C++ functions between the catcher
and the thrower. Therefore I would expect that a program
should not crash in this case, and the question is if adding
an empty exception-specifier would be allowed implementation-defined
behaviour.

>Note that not only is extern "C" special in that the compiler is
>required to support it, but it is also special in that the definition
>can be a pure C++ one though the compiler will have to respect the
>implementation specified calling conventions for extern "C" functions.

Where does it say that functions with non C/C++ linkage cannot be
implemented in C++? I thought linkage applied to declarators
and function-definitions are declarators. Where are the special
rules you mention?
(Since you were on the standard committee I would expect you to
know these things also have special knowledge of e.g. late additions
to the standard).

Does the standard even _allow_ a compiler that accepts

extern "Fortran" int f(int&);

to reject

extern "Fortran" int f(int&x) {return x=1;}

>Strictly speaking we can extend this to other linkages.  I can see no
>problems with, and some advantages, to non-MS compilers supporting such
>things as extern "MSC++" to get the right name-mangling etc. for linkage
>to libraries whose object code was produced by VC++.  And it would work
>the other way as well and so suitable callback functions could be
>provided for such libraries.

Great idea for functions in namespaces, but what about
member functions in classes?

I thought the standard specifically required them to have C++-linkage,
and without member functions the idea is of little
practical use for C++-classes.

--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/18
Raw View
In article <MPG.10e1a329eb34f3b2989779@news.rmi.net>,
Jerry Coffin <jcoffin@taeus.com> wrote:
>
>In article <755lm2$c7$1@news.lth.se>,
>Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) says...
>
>[ ... ]
>
>> The question is if C allows you to call a function with different
>> number of argument than it was _defined_ with.
>>
>> There has been some answers stating that definition and calls must
>> have the same number of argumnet, but I couldn't find any replies
>> quoting the current C-standard.
>
>[ ... ]
>
>I hope you'll forgive me if I don't type in the relevant section, as
>it's rather long, but the information is in section 6.5.4.3.

Of course, I could hardly require more.

>It gets
>long because it has to deal with combinations of old-style function
>declarations/definitions, and prototypes and definitions that include
>parameter types, as well as things like struct's that aren't the same,
>but are compatible with each other.  In short, it takes about a page
>and a half to say that the arguments must match in both number and
>type.

Thanks, it was as I expected, and caller popping arguments is thus
not an argument against C and C++ sharing calling conventions.

I'm still hoping that someone could reply to that original question.


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/12/18
Raw View
Francis Glassborow wrote:
>
> In article <758qmo$ovo$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
> writes
> >But the primary issue isn't what happens when some other language
> >throws, but what happens with languages such as C, that we know
> >do *NOT* implement exceptions. Do these languages propogate
> >exceptions that are thrown from C++? For instance, C++ function
> >"func1" calls Fortran function "func2", which in turn calls C++
> >function "func3". Func3 throws an exception -- what happens?
> >Can func1 catch it? Does it jump directly to
> >unhandled_exception? Does the program instantly crash? I don't
> >believe that the standard says anything about this.
>
> I think you are probably correct, OTOH any function declaration that
> lacks a throw specification is supposed to be able to throw anything.  I
> think that means that should a C++ function call an extern "C" function
> which in turn calls a C++ function (presumably because the body of the
> extern "C" function has been implemented in C++) then an exception can
> propagate straight through.  Note that should the definition of an
> extern "C" function be provided as C++ source code there is no reason
> why it should not throw and catch.

I don't think that's true. Some EH mechanisms may rely on extra
parameters pushed onto the stack at a predictable place (say, as
hidden first parameter to the function). The extern "C" functions
will not have that extra parameter, and therefore may fail.
(The extra parameter could f.ex. be an alternative address to
return to if returning with an exception.)

>
> Now that leaves the cases where the definition is not in C++, but then
> the rules are outside the scope of C++.  If a Fortran program can call a
> C++ function then it is up to the Fortran implementors to deside what to
> do about exceptions.

Well, it's not the FORTRAN implementation which defines the
compatibility interface (if we had a fortran with an equivalent to
extern "C++", I'd agree with you). It's the C++ implementation
which provides FORTRAN linkage. Therefore it's up to the C++
implementation to decide how to match to FORTRAN calling conventions.

>
> Note that not only is extern "C" special in that the compiler is
> required to support it, but it is also special in that the definition
> can be a pure C++ one though the compiler will have to respect the
> implementation specified calling conventions for extern "C" functions.

That's the point why even with functions in extern "C" linkage
written in C++, EH can be a problem. In the imaginary EH mechanism
above, the calling function won't supply the hidden parameter the EH
mechanism relies on.

[...]


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/19
Raw View
In article <367A4859.D1124D1A@physik.tu-muenchen.de>, Christopher
Eltschka <celtschk@physik.tu-muenchen.de> writes
>That's the point why even with functions in extern "C" linkage
>written in C++, EH can be a problem. In the imaginary EH mechanism
>above, the calling function won't supply the hidden parameter the EH
>mechanism relies on.

I am not sure where you get this idea for a hidden parameter for EH.
Perhaps some implementor could explain this because I am completely
unaware that such a mechanism would be used to support EH (certainly if
there is no exception specification provided)


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/19
Raw View
In article <75d6pg$sok$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>>Now that leaves the cases where the definition is not in C++, but then
>>the rules are outside the scope of C++.  If a Fortran program can call a
>>C++ function then it is up to the Fortran implementors to deside what to
>>do about exceptions.
>
>Why should the Fortran/C program be aware of it?

because I chose to call a C++ function from somewhere else.

Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/19
Raw View
In article <75d6pg$sok$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>Great idea for functions in namespaces, but what about
>member functions in classes?
>
>I thought the standard specifically required them to have C++-linkage,
>and without member functions the idea is of little
>practical use for C++-classes.

True, but it would be nice to see this provided as an extension by
implementors.  And I do not think we would need endorsement from the
Standard itself.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/19
Raw View
In article <75d6pg$sok$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>Where does it say that functions with non C/C++ linkage cannot be
>implemented in C++? I thought linkage applied to declarators
>and function-definitions are declarators. Where are the special
>rules you mention?

You are, of course right and in addition if I was writing C++ functions
to be used by Fortran etc. I would want to do just that.  The point I
should have made is the often missed one that the linkage specification
applies precisely to declarators and did not change the way the
definition was compiled.  It might look like C, but it would be C++.

>(Since you were on the standard committee I would expect you to
>know these things also have special knowledge of e.g. late additions
>to the standard).

Well there may be a few gifted individuals who are already familiar with
the whole standard but I am not one of them.  Much of the work was done
by sub-groups.  Even though I was directly involved in the problems of
linkage specification (as regards overloading) there are still
ramifications that only get revealed by further analysis.  The throw
specification is a case in point.

Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/19
Raw View
In article <36796BB7.E5FF58D1@technologist.com>,
  David R Tribble <dtribble@technologist.com> wrote:
> [...] would it be more correct to say that 'extern "C"' implies a
> 'throw()' clause, meaning that since it's a C (not C++) function,
> that it can't throw anything at all?  If so, then an extern "C" func
> that calls another C++ func that throws would be violating the
> implied no-throw clause of the extern "C" func.
>
> <tangent>
> Is it legal and meaningful to put a throw() clause on an extern "C"
> declaration?:
>     extern "C" int   cfunc(int a) throw();

Remember that extern "C" implies a calling convention, not an
actual language source. An extern "C" function can be defined in
C++, and this function can be called by both C and C++ functions.

I'm under the impression that nohting in the C++ standard prohibits
a function from throwing an exception, even if it was declared as
extern "C". If I'm right, then a throw() clause on an extern "C"
declaration is both legal and meaningful.

    // Compiled in C++ language
    class assertFailure {};
    extern "C" void assertPositive(int i) throw(assertFailure)
        { if (i<0) throw AssertFailure(); }

But what happens if this function is compiled in C and linked
with the above?
    // Compiled in C language
    void assertPositive(int i);
    int main() { assertPositive(-2); return 0; }

> </tangent>

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/19
Raw View
In article <5H2rtGAnhEe2Ew22@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> In article <758qmo$ovo$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
> writes
> >But the primary issue isn't what happens when some other language
> >throws, but what happens with languages such as C, that we know
> >do *NOT* implement exceptions. Do these languages propogate
> >exceptions that are thrown from C++? For instance, C++ function
> >"func1" calls Fortran function "func2", which in turn calls C++
> >function "func3". Func3 throws an exception -- what happens?
> >Can func1 catch it? Does it jump directly to
> >unhandled_exception? Does the program instantly crash? I don't
> >believe that the standard says anything about this.
>
> I think you are probably correct, OTOH any function declaration that
> lacks a throw specification is supposed to be able to throw anything. I
> think that means that should a C++ function call an extern "C" function
> which in turn calls a C++ function (presumably because the body of the
> extern "C" function has been implemented in C++) then an exception can
> propagate straight through.  Note that should the definition of an
> extern "C" function be provided as C++ source code there is no reason
> why it should not throw and catch.

But does the standard require this? If not, you are making unportable
assumptions.

> Now that leaves the cases where the definition is not in C++, but then
> the rules are outside the scope of C++.  If a Fortran program can call a
> C++ function then it is up to the Fortran implementors to deside what to
> do about exceptions.

Let me point out that when the definition is in C, the rules are
already outside the scope of C++. By the exact same standards, it's
up to the C implementors to decide what to do about exceptions.

I'm not sure, but possibly this problem is bigger than any one
language. In order for a routine in language A to call another
routine in language B, we have to agree on calling conventions. Where
are the arguments? In registers? On the stack? Sometimes the CPU
strongly supports one calling convention, so that more-than-minor
variations are rare. But other CPUs supply little more than a stack
of return addresses, and some don't even supply that. The new factor
in the mix is handling exceptions. How does function2 return control
to function1, but signal that this is an exception instead of a
normal return? One way would be to have every try block leave an
address on a special stack; throwing would look up the next try block.
But another method would be to have a register or some global address
that holds a pointer to the exception value. In that case, every
function call would have to be followed by a check of that value.
One of these allows throws to propgate easily; the other way causes
non-C++ routines to ignore the exception until they return to C++.
But other than that, which way is better for brand-X CPUs? There's
no good answer.

> Note that not only is extern "C" special in that the compiler is
> required to support it, but it is also special in that the definition
> can be a pure C++ one though the compiler will have to respect the
> implementation specified calling conventions for extern "C" functions.

An extern "C" function in C++ can also be called by C programs. What
happens if main() is in C, and some C++ function throws an exception
that is never caught?

> Strictly speaking we can extend this to other linkages.  I can see no
> problems with, and some advantages, to non-MS compilers supporting such
> things as extern "MSC++" to get the right name-mangling etc. for linkage
> to libraries whose object code was produced by VC++.  And it would work
> the other way as well and so suitable callback functions could be
> provided for such libraries.

This is already in the standard. But what is it that we are extending?
Again, the C++ standard does not dictate what happens when a Fortran
program catches a C++ exception, and I'm not sure that it reasonably
*could* specify this.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: bs@research.att.com (Bjarne Stroustrup)
Date: 1998/12/19
Raw View

David R Tribble <dtribble@technologist.com> writes

> Or would it be more correct to say that 'extern "C"' implies a
> 'throw()' clause, meaning that since it's a C (not C++) function,
> that it can't throw anything at all?  If so, then an extern "C" func
> that calls another C++ func that throws would be violating the
> implied no-throw clause of the extern "C" func.
>
> <tangent>
> Is it legal and meaningful to put a throw() clause on an extern "C"
> declaration?:
>     extern "C" int   cfunc(int a) throw();
> </tangent>

Yes.

Note that

 extern "C" int f();

doesn't mean that f() is compiled by a C compiler. It just means that it
obeys C linkage rules. It could be a C++ function acting as an interface
to code written in C.

Thus, we might write:

 extern "C" int f()
 {
  // ...
  X* p = new X; // might throw xalloc
  // ...
 }

A calling C function is unlikely to catch an exception thrown by f().
However, that calling C function might itself be called from a C++ function
that does catch exceptions.

 - Bjarne
Bjarne Stroustrup - http://www.research.att.com/~bs



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/19
Raw View
In article <36796BB7.E5FF58D1@technologist.com>,
David R Tribble  <dtribble@technologist.com> wrote:
>Or would it be more correct to say that 'extern "C"' implies a
>'throw()' clause, meaning that since it's a C (not C++) function,
>that it can't throw anything at all?  If so, then an extern "C" func
>that calls another C++ func that throws would be violating the
>implied no-throw clause of the extern "C" func.

I also think this would be a good idea.

Compilers/tools for analyzing throw-specifications could then also
use this information, and the distinction between extern "C" and
extern "C++" function would be useful on more platforms.

><tangent>
>Is it legal and meaningful to put a throw() clause on an extern "C"
>declaration?:
>    extern "C" int   cfunc(int a) throw();
></tangent>

I believe so, but how do write a function (with C++-linkage) accepting
a pointer to such a function?


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Alfred Kellner" <alfkellner@magnet.at>
Date: 1998/12/21
Raw View
Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
> ><tangent>
> >Is it legal and meaningful to put a throw() clause on an extern "C"
> >declaration?:
> >    extern "C" int   cfunc(int a) throw();
> ></tangent>
>
> I believe so, but how do write a function (with C++-linkage) accepting
> a pointer to such a function?
>
// type: pointer to C-function ... without exception-specification
 extern "C"  typedef void (*PF)();
// bar has C++linkage and takes a pointer to C-function
 void bar ( PF fp_c ) {  fp_c(); }
// as above: declaration for C-function + exc.spec
 extern "C"  void cfunc() throw();
// use it
 void foo() { bar( cfunc ); }

On the grounds that .....
<quote>
 8.3.5 Functions  [dcl.fct]
 (4)...The return type, the parameter type list and the cv-qualifier-seq,
  but not the default arguments (8.3.6) or exception specification (15.4),
  are part of the function type. ...
...
 15.4 Exception specifications
 An exception-specification shall appear only on a function declarator
 in a declaration or definition.
 An exception-specification shall not appear in a typedef declaration.
 Example:
 void (*fp) () throw (int); // OK
 typedef int (*pf) () throw(int); // ill-formed
....
17.4.4.8 Restrictions on exception handling
 None of the functions from the Standard C library shall report an
 error by throwing an exception, 176) unless it calls a program-
 supplied function that throws an exception.
note 176)
 That is, the C library functions all have a
 throw() exception-specification. ...
<quote>
 --ALfred


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/21
Raw View
In article <01be2c59$1720f560$15dcdcdc@mentor.magnet.at>, Alfred Kellner
<alfkellner@magnet.at> writes
>17.4.4.8 Restrictions on exception handling
> None of the functions from the Standard C library shall report an
> error by throwing an exception, 176) unless it calls a program-
> supplied function that throws an exception.
>note 176)
>       That is, the C library functions all have a
>       throw() exception-specification. ...
><quote>

1) Implies that extern "C" functions can have exception specifications
2) Just as well footnotes are non-normative because that one conflicts
with the 'unless it calls ...' in the main text.  Clearly functions such
as qsort() and bsearch() must be able to propagate exceptions if that
text is to have any meaning.

Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/12/21
Raw View
Francis Glassborow wrote:
>
> In article <75d6pg$sok$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
> writes
> >>Now that leaves the cases where the definition is not in C++, but then
> >>the rules are outside the scope of C++.  If a Fortran program can call a
> >>C++ function then it is up to the Fortran implementors to deside what to
> >>do about exceptions.
> >
> >Why should the Fortran/C program be aware of it?
>
> because I chose to call a C++ function from somewhere else.

Really? I'm not aware of an equivalent to extern "C++" in FORTRAN or C.
The code in question may (and probably even will) be written before
you decided to pass a pointer to a C++ function with appropriate
linkage to it. Yes, possibly it's even written (and compiled)
before C++ even existed.
C++ gives you the mechanism to give functions the linkage of other
language. So it's IMHO the job of the C++ implementation to
handle incompatibilities between the languages as good as possible.

However, with exceptions there's a possibility to provide transparent
"throw-through" to every language which does not have destructors,
or any other means of automatically cleaning up on function exit:
Jus longjmp over the code in question. For C, it _must_ work (since
C has longjmp itself), and for other languages I don't see any
real problem.

However, the question is if we _want_ to do that. The intermediate
code will likely not be exception safe (or rather "longjmp-safe").


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/12/16
Raw View
Hans Olsson wrote:
>
> In article <1B5IcJBT+Cc2Ewnq@robinton.demon.co.uk>,
> Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
> >
> >In article <74odtc$kkg$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
> >writes
> >>But it does not crash because of problems in qsort (which is part of
> >>the C++-standard), but because the exception handling is not
> >>compatible with C (and qsort is the old qsort from C).
> >
> >There is a common form of confusion here.  Within C++ there are two
> >allowed forms of function declarator, extern "C++" and extern "C".  The
> >former is supposed to provide internal consistency and whatever the
> >implementation does re varying linking and calling conventions it is
> >deemed to understand itself.
> >
> >The latter (extern "C") is intended to provide an alternative which at a
> >minimum should provide linkage names that are compatible with a notional
> >C compiler (note that I have to say that because there is no such thing
> >as a standard C linkage name any more than there is for C++  -- granted
> >that C linkage names tend to be what you wrote as a programmer but there
> >is no requirement that they should be. )
>
> The problem is that the standard seems to assume that there is a
> standard C linkage.
>
> >Of course we often use extern "C" to help C++ link to C binaries.  If
> >this works fine, but if it does not, tough.
>
> I would agree with you if it weren't for the standard.
>
> The standard (unless revised after CD2) explicitly state:
>
> Linkage between C++ and non-C++ code fragments can be achieved using a
> linkage-specification....
> Every implementation shall provide for linkage to functions written in
> the C programming language, "C",...
>
> In my view this means that extern "C" _must_ let C++ call C binaries,
> and a compiler that does not allow it is not only of less than
> perfect quality but actually non-standard.

At the end of section 7.5, it says "Linkage from C++ to objects defined
in other languages and to objects defined in C++ from other languages is
implementation-defined and language-dependent. Only where the object
layout strategies of the two language implementations are similar enough
can such linkage be achieved."

I think that the only kind of functions with "C" linkage that a C++
implementation is required to link to are those translated as C++ code
by that same implementation.
Most C++ implementations either have closely related C implementations;
many of them ARE C implementations when the right options turned. I
think that market forces can be coounted on to force a useful,
non-trivial implementation of linkage specifications, on any platform
where it matters.

....
> What about extern "Fortran"-functions can they have the limitations
> as extern "C"-functions?

The linkage requirements are general; I think that the "C" linkage is
special mainly in that it is required to exist.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/16
Raw View
In article <755orp$144$1@news.lth.se>,
  Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) wrote:
> Since there exists ways to make exceptions propagate through code
> compiled in other languages (at least C-code) and the standard
> does not seem to define it one way or the other I could imagine
> at least the following cases:
>
> 1. Exceptions must propagate regardless of the language of intermediate
> functions.
>
> 2. Propagating an exception through non-C++ code is
> implementation-defined behaviour.
>
> 3. Throwing an exception is implementation-defined behaviour for
> functions with non-C++-linkage.
>
> 4. Non-C++ linkage specification implies a matching throw-specification,
> i.e. extern "C" f(); might imply extern "C" f() throw();.
>
> The standard does not mention this problem, but since the behaviour
> is not defined as implementation-defined and the try-catch is still
> the most recently entered (even though there's a non-C++ function
> between the catch and throw) it seems as though the standard says 1.

Exceptions are a C++ feature. I wouldn't assume that any other
language can throw; even if I knew that other languages could
throw, I would expect that C was not one of them. If a compiler
suite (i.e. C++ and other languages) implemented exceptions in
other languages, I would accept that as a very useful extension.
Obviously, if this extension is designed to work with C++, it's
going to work with C++. So if it exists at all, there's no issue
over it's use.

But the primary issue isn't what happens when some other language
throws, but what happens with languages such as C, that we know
do *NOT* implement exceptions. Do these languages propogate
exceptions that are thrown from C++? For instance, C++ function
"func1" calls Fortran function "func2", which in turn calls C++
function "func3". Func3 throws an exception -- what happens?
Can func1 catch it? Does it jump directly to
unhandled_exception? Does the program instantly crash? I don't
believe that the standard says anything about this.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/17
Raw View
In article <758qmo$ovo$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
writes
>But the primary issue isn't what happens when some other language
>throws, but what happens with languages such as C, that we know
>do *NOT* implement exceptions. Do these languages propogate
>exceptions that are thrown from C++? For instance, C++ function
>"func1" calls Fortran function "func2", which in turn calls C++
>function "func3". Func3 throws an exception -- what happens?
>Can func1 catch it? Does it jump directly to
>unhandled_exception? Does the program instantly crash? I don't
>believe that the standard says anything about this.

I think you are probably correct, OTOH any function declaration that
lacks a throw specification is supposed to be able to throw anything.  I
think that means that should a C++ function call an extern "C" function
which in turn calls a C++ function (presumably because the body of the
extern "C" function has been implemented in C++) then an exception can
propagate straight through.  Note that should the definition of an
extern "C" function be provided as C++ source code there is no reason
why it should not throw and catch.


Now that leaves the cases where the definition is not in C++, but then
the rules are outside the scope of C++.  If a Fortran program can call a
C++ function then it is up to the Fortran implementors to deside what to
do about exceptions.

Note that not only is extern "C" special in that the compiler is
required to support it, but it is also special in that the definition
can be a pure C++ one though the compiler will have to respect the
implementation specified calling conventions for extern "C" functions.

Strictly speaking we can extend this to other linkages.  I can see no
problems with, and some advantages, to non-MS compilers supporting such
things as extern "MSC++" to get the right name-mangling etc. for linkage
to libraries whose object code was produced by VC++.  And it would work
the other way as well and so suitable callback functions could be
provided for such libraries.



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1998/12/17
Raw View
In article <755lm2$c7$1@news.lth.se>,
Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) says...

[ ... ]

> The question is if C allows you to call a function with different
> number of argument than it was _defined_ with.
>
> There has been some answers stating that definition and calls must
> have the same number of argumnet, but I couldn't find any replies
> quoting the current C-standard.

[ ... ]

I hope you'll forgive me if I don't type in the relevant section, as
it's rather long, but the information is in section 6.5.4.3.  It gets
long because it has to deal with combinations of old-style function
declarations/definitions, and prototypes and definitions that include
parameter types, as well as things like struct's that aren't the same,
but are compatible with each other.  In short, it takes about a page
and a half to say that the arguments must match in both number and
type.



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/17
Raw View
In article <36770648.14937740@wizard.net>,
James Kuyper  <kuyper@wizard.net> wrote:
>
>Hans Olsson wrote:
>> In my view this means that extern "C" _must_ let C++ call C binaries,
>> and a compiler that does not allow it is not only of less than
>> perfect quality but actually non-standard.
>
>At the end of section 7.5, it says "Linkage from C++ to objects defined
>in other languages and to objects defined in C++ from other languages is
>implementation-defined and language-dependent. Only where the object
>layout strategies of the two language implementations are similar enough
>can such linkage be achieved."

Functions are not objects. The phrase must refer to linkage specification
for variables (and layout strategies indicate that it is in mostly about
struct objects). This extends to arguments (and return types) of the
functions (I hope), but this still allows functions taking sufficiently
simply arguments regardless of the compiler (e.g. extern "C" void f();,
and (hopefully) e.g. extern "C" void f(char*);).

>> What about extern "Fortran"-functions can they have the limitations
>> as extern "C"-functions?
>
>The linkage requirements are general; I think that the "C" linkage is
>special mainly in that it is required to exist.

Correct, but the standard explicitly introduce restrictions in
C linkage that is due to the lack of name-mangling, in C, i.e. only
one overloaded function (with the same name) with C linkage and ignoring
namespaces for C linkage.

I would expect a compiler to have the same restrictions for
extern "Fortran", but not for all languages.

My question was if these restrictions were part of allowed implementation-
defined behaviour or not (for other linkages, i.e. not "C" or "C++").



--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/15
Raw View
In article <74p477$aj0@abyss.West.Sun.COM>,
Stanley Friesen [Contractor] <stanley@West.sun.com> wrote:
>
>In article <74o5sq$ikk$1@news.lth.se>,
>Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
>>I did not know that standard C allowed you to call a function
>>with fewer/more arguments (main is sort of a special case).
>
>Fewer is not normally allowed, unless the missing ones are never actually
>used in the function - as in UNIX open, which only requires the mode
>parameter if O_CREAT is set.  More is allowed for functions called without
>a prototype in scope, or for functions with an old-style declaration in
>scope (that is something like "func()"), since an empty param list in
>a non-definition declaration implies "unspecified number of parameters",
>so the compiler cannot check the number passed against the number expected.

Sorry, I was a bit was unspecific:

The question is if C allows you to call a function with different
number of argument than it was _defined_ with.

There has been some answers stating that definition and calls must
have the same number of argumnet, but I couldn't find any replies
quoting the current C-standard.

BTW: Since extern "C" does not turn the declaration into a C-declaration
there must of course be a match between the number of arguments in the
extern "C"-declaration and in the call in C++-code.


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/15
Raw View
In article <1B5IcJBT+Cc2Ewnq@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <74odtc$kkg$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
>writes
>>But it does not crash because of problems in qsort (which is part of
>>the C++-standard), but because the exception handling is not
>>compatible with C (and qsort is the old qsort from C).
>
>There is a common form of confusion here.  Within C++ there are two
>allowed forms of function declarator, extern "C++" and extern "C".  The
>former is supposed to provide internal consistency and whatever the
>implementation does re varying linking and calling conventions it is
>deemed to understand itself.
>
>The latter (extern "C") is intended to provide an alternative which at a
>minimum should provide linkage names that are compatible with a notional
>C compiler (note that I have to say that because there is no such thing
>as a standard C linkage name any more than there is for C++  -- granted
>that C linkage names tend to be what you wrote as a programmer but there
>is no requirement that they should be. )

The problem is that the standard seems to assume that there is a
standard C linkage.

>Of course we often use extern "C" to help C++ link to C binaries.  If
>this works fine, but if it does not, tough.

I would agree with you if it weren't for the standard.

The standard (unless revised after CD2) explicitly state:

Linkage between C++ and non-C++ code fragments can be achieved using a
linkage-specification....
Every implementation shall provide for linkage to functions written in
the C programming language, "C",...

In my view this means that extern "C" _must_ let C++ call C binaries,
and a compiler that does not allow it is not only of less than
perfect quality but actually non-standard.

If it was not required it would be trivial to guarantee that extern "C"
and extern "C++"-functions had the same calling sequence.

The IBM(?) C++ compiler with different calling conventions that
their C compiler could merely state that the extern "C"-functions
were compatible with some imagined C compiler. There would in that
case not have been any need to make pointers to extern "C" and
extern "C++"-functions different.

>Forget the history that helps us understand how we arrived at this
>point, it is just that; history.  C++ has a concept of linkage
>specification that can only be applied to function declarators.

It can also be applied to pointers to functions (or this discussion
would be pointless) and declarators for variables.

>Implementors can have as many of these as they like.  Each one provides
>a set of rules for deriving a function name and calling sequence from
>the function declaration.  The language explicitly requires two versions
>to exist: extern "C++" which is the default for the language and which
>necessarily supports overloading and extern "C" which explicitly does
>not support overloading and has limitations on the scope  in which it is
>deemed to be declared.

What about extern "Fortran"-functions can they have the limitations
as extern "C"-functions?

>It makes no sense that pointers to these two different kinds of function
>should be required to be interchangeable.  Nor does it make any sense to
>expect such things as exceptions to propagate through code written and
>compiled in some other language.  What we can do is provide a mechanism
>for an interface between C++ and another language as well as allow those
>rules to be applied (at least sometimes) to purely C++ code.

Since there exists ways to make exceptions propagate through code
compiled in other languages (at least C-code) and the standard
does not seem to define it one way or the other I could imagine
at least the following cases:

1. Exceptions must propagate regardless of the language of intermediate
functions.

2. Propagating an exception through non-C++ code is
implementation-defined behaviour.

3. Throwing an exception is implementation-defined behaviour for
functions with non-C++-linkage.

4. Non-C++ linkage specification implies a matching throw-specification,
i.e. extern "C" f(); might imply extern "C" f() throw();.

The standard does not mention this problem, but since the behaviour
is not defined as implementation-defined and the try-catch is still
the most recently entered (even though there's a non-C++ function
between the catch and throw) it seems as though the standard says 1.

I say 'seems as though' because I'm not sure how much is implementation-
defined for non-C++ functions.

Your statement is equivalent to 2, but I see no reason to prefer it in
favour of 3.

AFAIK there are compilers consistent with cases 1,2, and 3.

In practice I think 4 or 1 would be the best.

>linkage specifications are about function names not about implementation
>of functions.

The calling sequence (including exception handling) is clearly part of
the implementation of the function and not about its name.
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 1998/12/11
Raw View
David R Tribble wrote:
> As old-style non-prototype function declarations slowly become a
> thing of the past, ISO C compilers will be able to make more use
> of this optimization technique.  A C compiler can do this today,
> in fact, if it determines that all references to a given function
> occur when a prototype declaration of that function is visible.

In Standard C, the compiler *always* knows what a function expects,
except in the presence of incorrect code. A variadic function must
be declared as such before it can be called. Calling a function
which has not been declared allows the compiler to elucidate a type
for it; it returns int, and accepts the number of arguments it is
called with, each of which has the promoted type of the corresponding
parameter. If a subsequent call does not correspond to this, then the
program is in error.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: David R Tribble <david.tribble@noSPAM.central.beasys.com>
Date: 1998/12/11
Raw View
David R Tribble wrote:
> As old-style non-prototype function declarations slowly become a
> thing of the past, ISO C compilers will be able to make more use
> of this optimization technique.  A C compiler can do this today,
> in fact, if it determines that all references to a given function
> occur when a prototype declaration of that function is visible.

Hyman Rosen wrote:
> In Standard C, the compiler *always* knows what a function expects,
> except in the presence of incorrect code. A variadic function must
> be declared as such before it can be called. Calling a function
> which has not been declared allows the compiler to elucidate a type
> for it; it returns int, and accepts the number of arguments it is
> called with, each of which has the promoted type of the corresponding
> parameter. If a subsequent call does not correspond to this, then the
> program is in error.

Not true of Standard C89 nor C9x, which still allows (although it
marks as deprecated) function declarations with no prototype
information.

    extern int   f();        // No calling info, but legal

    i = f(a, b, c);          // Legal but unchecked call
    j = f(d, e);             // Also legal, also unchecked

A real example of this is the Unix open() function, which takes an
optional 3rd parm (the permissions mask to use if the file is newly
created).

Thus the compiler does not always know what a function expects.
It can only know so if a prototype for the function is in scope at
all points in the code where the function is referenced.

-- David R. Tribble, dtribble@technologist.com --


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 1998/12/14
Raw View
David R Tribble wrote:
> Not true of Standard C89 nor C9x, which still allows (although it
> marks as deprecated) function declarations with no prototype
> information.
>...
> A real example of this is the Unix open() function, which takes an
> optional 3rd parm (the permissions mask to use if the file is newly
> created).

No, neither version of C allows this. For example, my copy of n2794
(a C9X draft) says in 6.5.2.2#6:

 [#6] If the expression that denotes the called function
 has a type that does not include a prototype... If the
 number of arguments does not agree with the number of
 parameters, the behavior is undefined. If the function
 is defined with a type that includes a prototype, and
 ... the prototype ends with an ellipsis... the behavior
 is undefined.

Users who omit the third argument to open are relying upon undefined
behavior (or rather, relying on the implementation to do what they
want). Ditto for calling a variadic function without a prototype for
it having been seen.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stanley@West.sun.com (Stanley Friesen [Contractor])
Date: 1998/12/10
Raw View
In article <74o5sq$ikk$1@news.lth.se>,
Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
>>But, since C allows functions to be
>>called with different number of arguments than they are declared with,
>>C cannot, in general, use this instruction, as it requires the subroutine
>>know how much space to pop off the stack for the arguments.
>
>I did not know that standard C allowed you to call a function
>with fewer/more arguments (main is sort of a special case).

Fewer is not normally allowed, unless the missing ones are never actually
used in the function - as in UNIX open, which only requires the mode
parameter if O_CREAT is set.  More is allowed for functions called without
a prototype in scope, or for functions with an old-style declaration in
scope (that is something like "func()"), since an empty param list in
a non-definition declaration implies "unspecified number of parameters",
so the compiler cannot check the number passed against the number expected.

There is a whole *long* paragraph in the standard regarding what is guarenteed
under various combinations of declarations and definitions.  But, if I remember
correctly, what it boils down to is that the only time a function is allowed to
assume with certainty how many parameters it was called with is if a full
prototype is in scope at the point the function is defined.  Thus only under
these conditions can it use the "short" return+pop protocol.

>If the C standard does allow wrong number of arguments you're right
>that a C++ that lets the called function deallocate the arguments
>cannot share calling conventions with the C compiler, but I'm
>not sure if the C standard really allows it.

I will have to double check my copy of the C standard when I get home to
be absolutely sure.  But on this issue, I am fairly certain my memory is
essentially correct.

>I know that standard C and C++ allow variable number of arguments for
>functions (using traling ... and va_-macros defined in stdarg.h),
>but you have to step through all of them so even in this case it is
>safe for the called function to deallocate its arguments.

Well, yes, if the return+pop instruction can take a variable pop size.  I do
not remember if a register reference is allowed for this parameter on
the Sparc. (Sparc's don't allow memory references in normal instructions,
so I know that is not possible).


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/10
Raw View
In article <74odtc$kkg$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>But it does not crash because of problems in qsort (which is part of
>the C++-standard), but because the exception handling is not
>compatible with C (and qsort is the old qsort from C).

There is a common form of confusion here.  Within C++ there are two
allowed forms of function declarator, extern "C++" and extern "C".  The
former is supposed to provide internal consistency and whatever the
implementation does re varying linking and calling conventions it is
deemed to understand itself.

The latter (extern "C") is intended to provide an alternative which at a
minimum should provide linkage names that are compatible with a notional
C compiler (note that I have to say that because there is no such thing
as a standard C linkage name any more than there is for C++  -- granted
that C linkage names tend to be what you wrote as a programmer but there
is no requirement that they should be. )

Now many implementors actually use the same binary libraries for C and
for the part of the C++ library that is inherited from C but there is no
requirement that they do so.

If you take a piece of C source code,  wrap it in an extern "C" block
and then run it through a C++ compiler what you get is C++.  If C and
C++ are in disagreement you will get the C++ form not the C.  If I take
the source code for qsort() and compile it with a C++ compiler I should
get all the exception behaviour that I would expect from C++ source
code.  If your compiler implementor does not do that and as a
consequence your program crashes the fault is theirs, not yours nor the
C++ standards.

Of course we often use extern "C" to help C++ link to C binaries.  If
this works fine, but if it does not, tough.

Forget the history that helps us understand how we arrived at this
point, it is just that; history.  C++ has a concept of linkage
specification that can only be applied to function declarators.
Implementors can have as many of these as they like.  Each one provides
a set of rules for deriving a function name and calling sequence from
the function declaration.  The language explicitly requires two versions
to exist: extern "C++" which is the default for the language and which
necessarily supports overloading and extern "C" which explicitly does
not support overloading and has limitations on the scope  in which it is
deemed to be declared.


It makes no sense that pointers to these two different kinds of function
should be required to be interchangeable.  Nor does it make any sense to
expect such things as exceptions to propagate through code written and
compiled in some other language.  What we can do is provide a mechanism
for an interface between C++ and another language as well as allow those
rules to be applied (at least sometimes) to purely C++ code.

linkage specifications are about function names not about implementation
of functions.



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/10
Raw View
In article <z+c5DAAaqtb2EwtM@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> In article <74lg3k$rev$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
> writes
> >Additionally the text under qsort seem to assume that exceptions are
> >harmlessly propagated in C as though nothing strange could
> >conceivably happen.
>
> I am not sure what you are getting at.  Why should they not so propagate
> (except for the usual problem that we had with all algorithms being
> applied to containers)

Because in most C++ systems, qsort is an extern "C" function, and
C functions do not understand exceptions.

> >The only compiler that I have access to that actually handles
> >exceptions in qsort is Sun's compiler (4.2).
>
> So?  Compiler implementors have their priorities and I doubt that qsort
> is of much relevance to C++ (the STL algorithms are far superior)

Ah, you are the one programmer on this planet that always has time
to use new, superior technologies. I envy you. Everyone else on this
planet at least occasionally has to deal with code that's at least a
few years old.

I did try to explain to my boss that we ought to convert our
home-grown container to a vector, and add namespaces to every single
module of every single program, and so on. We could have finished
this by the fourth quarter of 1999, too, but he has these crazy
ideas about "Y2K certification" and "Features our customers want."
He actually had the gall to suggest that the programs would still
compile okay next year, even though they were written before the
C++ language specification was final.

Naturally, I started explaining the elegance of the new solutions,
and how his maintenance costs would get sooooo low. He said that
there's no point spending lots and lots of money right now, just
to make our costs go down a little bit later! Have you ever heard
anything so silly?

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/10
Raw View
In article <74pdm7$25u$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
writes
>Ah, you are the one programmer on this planet that always has time
>to use new, superior technologies. I envy you. Everyone else on this
>planet at least occasionally has to deal with code that's at least a
>few years old.


I don't have the time not to.  And as I point out in an earlier posting,
qsort compiled by a C++ compiler should not cause the problems you
mention.  If you try to link object code from two sources then they need
to be compatible and in the cases you mention this was clearly not so.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/10
Raw View
In article <74pdm7$25u$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
writes
>Naturally, I started explaining the elegance of the new solutions,
>and how his maintenance costs would get sooooo low. He said that
>there's no point spending lots and lots of money right now, just
>to make our costs go down a little bit later! Have you ever heard
>anything so silly?

But if the result is that your code crashes I do not see what he is
getting.  Perhaps the fix for now is to get a full C++ Standard Library
(i.e. one where all the object code has been produced by a C++ compiler)
after all if you are writing C++ (which you must be if you have
exceptions to worry about) you should be using C++ libraries.  If your
boss does not understand that it is time to move.



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: David R Tribble <dtribble@technologist.com>
Date: 1998/12/10
Raw View
Reference:  <74mf1s$la1@abyss.West.Sun.COM>

Hans Olsson <mailto:Hans.Olsson@dna.lth.se> wrote:
> I don't think so. And even if it was sufficient reason it wouldn't
> hurt to explain why the vendor had to use different calling
> conventions.

Stanley Friesen [Contractor] wrote:
> Well, "had to" may be a bit strong, but on the Sparc architecture,
> C++ can use a more efficient calling convention than C, due to
> stronger requirements on allowed usage.  In particular, the Sparc
> has a special return instruction that can pop the *arguments* to
> the subroutine off the stack as well as the local variables.  This
> saves at least one instruction per call.  But, since C allows
> functions to be called with different number of arguments than they
> are declared with, C cannot, in general, use this instruction, as it
> requires the subroutine know how much space to pop off the stack for
> the arguments.  [Actually, in ANSI C *some* subroutines can
> theoretically use this mechanism, but doing that adds complexity to
> the compiler to determine when it is safe to use it]

Pascal calling conventions typically allow such an optimization.
(Indeed, Microsoft compilers call this the '__stdcall' convention,
as opposed to the C/C++ '__cdecl' convention.)  But then Pascal
routines have always been required to be declared with argument
prototypes.

As old-style non-prototype function declarations slowly become a
thing of the past, ISO C compilers will be able to make more use
of this optimization technique.  A C compiler can do this today,
in fact, if it determines that all references to a given function
occur when a prototype declaration of that function is visible.

The problem, though, is backward compatibility with existing code
and libraries, which more than likely do not use (could not use)
such an optimized calling scheme.  C++ compilers/linkers could
very well suffer from this as well, since the early C++ compilers
(and most of the existing ones today) tried to be call-compatible
with C as much as they could.  You can't change your function
calling scheme overnight without causing exiting object code to
break.  Which is another way of saying that once you choose a
scheme, you're stuck with it for a while (unless you use nonstandard
extensions such as '__cdecl' to migrate from the old to the new).

Also don't forget that C++ allows variadic functions, too.

-- David R. Tribble, dtribble@technologist.com --



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/12/11
Raw View
Hans Olsson wrote:
>
> In article <74mf1s$la1@abyss.West.Sun.COM>,
> Stanley Friesen [Contractor] <stanley@West.sun.com> wrote:
> >
> >In article <74lg3k$rev$1@news.lth.se>,
> >Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
> >>
> >>I don't think so. And even if it was sufficient reason it wouldn't hurt
> >>to explain why the vendor had to use different calling conventions.
> >
> >Well, "had to" may be a bit strong, but on the Sparc architecture,
> >C++ can use a more efficient calling convention than C, due to
> >stronger requirements on allowed usage.  In particular, the Sparc
> >has a special return instruction that can pop the *arguments* to
> >the subroutine off the stack as well as the local variables.
>
> I've already mentioned a similar instruction on the 68k (rtd#),
> and stated that both C and C++ compilers can use it (gcc at least).
>
> >This saves
> >at least one instruction per call.
>
> Not always. I believe some compilers can call several functions
> and then deallocate the arguments for all of them at once.
>
> >But, since C allows functions to be
> >called with different number of arguments than they are declared with,
> >C cannot, in general, use this instruction, as it requires the subroutine
> >know how much space to pop off the stack for the arguments.
>
> I did not know that standard C allowed you to call a function
> with fewer/more arguments (main is sort of a special case).

Well, I doubt that C allows you to call a function with _less_
arguments. However, if you declare the following in C:

void f()

then you did indeed _not_ specify how many parameters f takes.
The real deinition could contain an ellipsis, and therefore
the compiler must not make any assumptions that all parameters
are popped from stack, or how many of them are.
Since the same function may be declared as complete prototype
in another translation unit, the compiler can't take
advantage of the extra knowledge, since the calling convention
must be the same.

>
> If the C standard does allow wrong number of arguments you're right
> that a C++ that lets the called function deallocate the arguments
> cannot share calling conventions with the C compiler, but I'm
> not sure if the C standard really allows it.

It does not really allow it AFAIK, but due to the fact that
full prototypes are not required, the compiler must behave
as if there may be. Indeed, I doubt that you find a C compiler
where too many arguments hurt (too few can possibly be dangerous,
though).

>
> I know that standard C and C++ allow variable number of arguments for
> functions (using traling ... and va_-macros defined in stdarg.h),
> but you have to step through all of them so even in this case it is
> safe for the called function to deallocate its arguments.

It may be safe, but at least the 80x86 does not give support for
popping a variable number of arguments (except if you write
self-modifying code - I don't think you'd like your compiler to
do that). So unless you _know_ the number of arguments at
compile time, you can't easily pop them (indeed it's much harder
than from the caller). And since in C the caller might not know
if there are variadic arguments, it will have to clean up
itself anyway.

It is just not possible that functions supporting variadic arguments
and not demanding function prototypes use the efficient argument
popping return.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stanley@West.sun.com (Stanley Friesen [Contractor])
Date: 1998/12/09
Raw View
In article <74lg3k$rev$1@news.lth.se>,
Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
>
>I don't think so. And even if it was sufficient reason it wouldn't hurt
>to explain why the vendor had to use different calling conventions.

Well, "had to" may be a bit strong, but on the Sparc architecture,
C++ can use a more efficient calling convention than C, due to
stronger requirements on allowed usage.  In particular, the Sparc
has a special return instruction that can pop the *arguments* to
the subroutine off the stack as well as the local variables.  This saves
at least one instruction per call.  But, since C allows functions to be
called with different number of arguments than they are declared with,
C cannot, in general, use this instruction, as it requires the subroutine
know how much space to pop off the stack for the arguments.  [Actually,
in ANSI C *some* subroutines can theoretically use this mechanism, but
doing that adds complexity to the compiler to determine when it is safe
to use it]


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/09
Raw View
In article <74lg3k$rev$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>Additionally the text under qsort seem to assume that exceptions are
>harmlessly propagated in C as though nothing strange could
>conceivably happen.

I am not sure what you are getting at.  Why should they not so propagate
(except for the usual problem that we had with all algorithms being
applied to containers)

>This is not the case in egcs-1.0 (that crashes instead of propagating
>an exception through qsort) and Visual C++ 5.0 (that crashes
>already when an extern "C"-function throws an exception).

It would rather depend on the nature of the crash.

>Since the standard was revised because of one compiler I find it
>strange that it wasn't changed because of two compilers
>(or was this changed between CD2 and the final standard?)

Remarkably the Standards Committees can only discuss and tackle problems
that are brought to their attention.  Actually the problem with linkage
specifications and calling conventions had been a long standing one and
there had been several attempts to formulate an acceptable solution.

The existence of a specific pair of compilers in which the problem
manifested only made the problem one that was more than some language
lawyers problem to a real life one.


>The only compiler that I have access to that actually handles
>exceptions in qsort is Sun's compiler (4.2).

So?  Compiler implementors have their priorities and I doubt that qsort
is of much relevance to C++ (the STL algorithms are far superior)




Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/10
Raw View
In article <74mf1s$la1@abyss.West.Sun.COM>,
Stanley Friesen [Contractor] <stanley@West.sun.com> wrote:
>
>In article <74lg3k$rev$1@news.lth.se>,
>Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
>>
>>I don't think so. And even if it was sufficient reason it wouldn't hurt
>>to explain why the vendor had to use different calling conventions.
>
>Well, "had to" may be a bit strong, but on the Sparc architecture,
>C++ can use a more efficient calling convention than C, due to
>stronger requirements on allowed usage.  In particular, the Sparc
>has a special return instruction that can pop the *arguments* to
>the subroutine off the stack as well as the local variables.

I've already mentioned a similar instruction on the 68k (rtd#),
and stated that both C and C++ compilers can use it (gcc at least).

>This saves
>at least one instruction per call.

Not always. I believe some compilers can call several functions
and then deallocate the arguments for all of them at once.

>But, since C allows functions to be
>called with different number of arguments than they are declared with,
>C cannot, in general, use this instruction, as it requires the subroutine
>know how much space to pop off the stack for the arguments.

I did not know that standard C allowed you to call a function
with fewer/more arguments (main is sort of a special case).

If the C standard does allow wrong number of arguments you're right
that a C++ that lets the called function deallocate the arguments
cannot share calling conventions with the C compiler, but I'm
not sure if the C standard really allows it.

I know that standard C and C++ allow variable number of arguments for
functions (using traling ... and va_-macros defined in stdarg.h),
but you have to step through all of them so even in this case it is
safe for the called function to deallocate its arguments.


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/10
Raw View
In article <74lg3k$rev$1@news.lth.se>,
Hans Olsson <Email_To::.Hans.Olsson@dna.lth.se> wrote:
>I agree that this program should either work or generate a diagnostic.
>
>You seem to think that different calling conventions for makes this fail,
>but I have already suggested a way to make this work regardless of
>calling conventions: automatically generate forwarding functions
>(if necessary), i.e:

Sorry to reply to my own post, but I finally figured out why
neither a compiler nor a programmer can easily generate
a forwarding function for different calling conventions.

The problem is functions taking pointers to functions, i.e.:

extern "C" int f1(int inner(int));

The forwarding function would in this case correspond to:

int my_f1(int inner(int)) {
  extern "C" int my_inner(int x) {return inner(x);}
  return f1(my_inner);
};

but the neccessary local function (my_inner) is not legal.
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/10
Raw View
In article <z+c5DAAaqtb2EwtM@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <74lg3k$rev$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
>writes
>>Additionally the text under qsort seem to assume that exceptions are
>>harmlessly propagated in C as though nothing strange could
>>conceivably happen.
>
>I am not sure what you are getting at.  Why should they not so propagate
>(except for the usual problem that we had with all algorithms being
>applied to containers)

Because the exception propagating mechanism is part of the calling
convention, and C/Fortran compilers are not always compatible with
this part of the calling convention.

Some exception handling mechanisms (setjmp-based) do not require
special calling conventions to propagate exceptions,
but might have other disadvantages.

>>This is not the case in egcs-1.0 (that crashes instead of propagating
>>an exception through qsort) and Visual C++ 5.0 (that crashes
>>already when an extern "C"-function throws an exception).
>
>It would rather depend on the nature of the crash.

egcs-1.0 had throw call __terminate that through some steps called
abort (it did not pass through unexpected()).

>>Since the standard was revised because of one compiler I find it
>>strange that it wasn't changed because of two compilers
>>(or was this changed between CD2 and the final standard?)
>
>Remarkably the Standards Committees can only discuss and tackle problems
>that are brought to their attention.  Actually the problem with linkage
>specifications and calling conventions had been a long standing one and
>there had been several attempts to formulate an acceptable solution.

Yes, but the standard contains words about qsort propagating exceptions.
The Standards Committee was thus aware that the compar-function in qsort
could throw exceptions, but didn't realize that this might cause problems.

Some compilers (e.g. egcs-1.0) also specify that when compiling
C code you do (as default) not get exception handling code, but no-one
seemed to have put the two together.

I admit that I should have tried the examples before the standard
was final and brought it to the attention of the Standards Committee.
I assume that the members of the C++ Standards Committee now are aware
of the problem, but I don't know how much can be fixed now.

>>The only compiler that I have access to that actually handles
>>exceptions in qsort is Sun's compiler (4.2).
>
>So?  Compiler implementors have their priorities and I doubt that qsort
>is of much relevance to C++ (the STL algorithms are far superior)

In general one should use STL-instead (and since the STL-algorithms
have more general iterators they cannot be implemented in terms of qsort).

But it does not crash because of problems in qsort (which is part of
the C++-standard), but because the exception handling is not
compatible with C (and qsort is the old qsort from C).

I assume that requiring the exception handling to be compatible with
all other calling conventions on the given platform might have
other disadvantages (e.g. in terms of speed); otherwise it would seem
unlikely that two independent compilers had similar problems.

But I haven't implemented exception handling and I don't have a clue
about how Sun's compiler handles the situation and if there are
disadvantages with it (looking at the assembler code did not help).

--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/09
Raw View
In article <749ddr$5ti$1@engnews2.Eng.Sun.COM>,
Steve Clamage <stephen.clamage@sun.com> wrote:
>
>Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) writes:
>>That two products (C and C++-compiler) from the same vendor used
>>(and maybe uses) different calling conventions is not in itself
>>sufficient, especially considering that some compilers can all by
>>themselves generate code with different calling conventions
>>(and name mangling, exception handling, etc.).
>
>It is a sufficient reason.

I don't think so. And even if it was sufficient reason it wouldn't hurt
to explain why the vendor had to use different calling conventions.

>When you call a function directly, the declared language linkage
>tells the compiler which calling convention to use.
>
>Originally, pointers to functions did not carry any language
>linkage information. The compiler cannot tell from the use
>of the pointer what calling convention to use. Example:
>
>extern "C"       int f1(int);
>extern "Fortran" int f2(int);
>extern "C++"     int f3(int);
>
>typedef int (*fp)(int); // using old C++ rules
>
>int foo( fp f, int i ) { return f(i); }
>
>int main()
>{
>    foo(f1);
>    foo(f2);
>    foo(f3);
>}
>
>Suppose the calling conventions for C, C++, and Fortran are different.
>
>Under the old rules there is no way that this program can work, and
>no help from the compiler to tell you what is wrong.

I agree that this program should either work or generate a diagnostic.

You seem to think that different calling conventions for makes this fail,
but I have already suggested a way to make this work regardless of
calling conventions: automatically generate forwarding functions
(if necessary), i.e:

the compiler would be required to replace:

extern "Fortran" int f2(int);
foo(f2);

by:

extern "Fortran" int f2(int);
int my_f2(int x) {return f2(x);}
...
foo(my_f2);

behind the back of the programmer. The my_f2-function can of course
by inlined out of existence when we directly call the f2-function.

>Under the new rules, fp has a language linkage associated with
>it, and cannot point to a function declared with a different
>language linkage. The compiler tells you about any problems,
>and also will automatically use the correct linkage to call
>a function through a pointer.

But at the cost of not allowing the call of a C-function through
a pointer to a C++-function even when this is perfectly harmless.

The new rules breaks C-code (you can no longer easily construct a
table of functions from math.h), and puts the burden of programmers
instead of on compiler writers. I think that's a bad decision,
and I need a good reason to reconsider.

Furthermore there is much more to calling conventions, and
it seems as though the standard committee missed the other
(IMO more important) issue:

What if the calling conventions do no allow the types for
arguments, return values or exceptions? For example:
 pass-by-value of integers to Fortran,
 unsigned integers in Fortran,
 zero-terminated character arrays in Fortran,
 references in C,
 pointers in Fortran,
 throwing any kind of exception in C/Fortran.

In some of these cases we can treat them as another type
(e.g. references are basically pointers), but at least in CD2
I couldn't find anything that allows a compiler to stop
with an error message because the type is not compatible with
a non-C++ calling-conventions.

Additionally the text under qsort seem to assume that exceptions are
harmlessly propagated in C as though nothing strange could
conceivably happen.

This is not the case in egcs-1.0 (that crashes instead of propagating
an exception through qsort) and Visual C++ 5.0 (that crashes
already when an extern "C"-function throws an exception).

Since the standard was revised because of one compiler I find it
strange that it wasn't changed because of two compilers
(or was this changed between CD2 and the final standard?)

The only compiler that I have access to that actually handles
exceptions in qsort is Sun's compiler (4.2).


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/04
Raw View
In article <t1N83$AcKsZ2Ewu2@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <7461nq$ia$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
>writes
>>I understand that it's too late for changing the standard, and
>>there is a simple work-around, but I think it would have been better
>>to consider extern "C" and extern "C++" as identical types (or
>>automatically generate forwarding functions when constructing
>>pointers to functions with non-C++ language linkage specifiers).
>
>And one reason the change was made was exactly that an implementation of
>C and C++ from the same source with incompatible function pointers
>existed (and I believe there were good reasons for the incompatibility)

So I've been told, but since you've said that you were responsible for
the change I was hoping that you could explain those reasons, i.e.
why the pointers to C++-functions and C-functions had to differ.

That two products (C and C++-compiler) from the same vendor used
(and maybe uses) different calling conventions is not in itself
sufficient, especially considering that some compilers can all by
themselves generate code with different calling conventions
(and name mangling, exception handling, etc.).

You've also indicated that you don't think most compiler vendors will
enforce this except in strict standard mode. I find that somewhat
odd considering that you lobbied for the change.
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/12/04
Raw View
Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) writes:

>In article <t1N83$AcKsZ2Ewu2@robinton.demon.co.uk>,
>Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>>
>>In article <7461nq$ia$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se> writes
>>
>>And one reason the change was made was exactly that an implementation of
>>C and C++ from the same source with incompatible function pointers
>>existed (and I believe there were good reasons for the incompatibility)

>So I've been told, but since you've said that you were responsible for
>the change I was hoping that you could explain those reasons, i.e.
>why the pointers to C++-functions and C-functions had to differ.

>That two products (C and C++-compiler) from the same vendor used
>(and maybe uses) different calling conventions is not in itself
>sufficient, especially considering that some compilers can all by
>themselves generate code with different calling conventions
>(and name mangling, exception handling, etc.).

It is a sufficient reason.

When you call a function directly, the declared language linkage
tells the compiler which calling convention to use.

Originally, pointers to functions did not carry any language
linkage information. The compiler cannot tell from the use
of the pointer what calling convention to use. Example:

extern "C"       int f1(int);
extern "Fortran" int f2(int);
extern "C++"     int f3(int);

typedef int (*fp)(int); // using old C++ rules

int foo( fp f, int i ) { return f(i); }

int main()
{
    foo(f1);
    foo(f2);
    foo(f3);
}

Suppose the calling conventions for C, C++, and Fortran are different.

Under the old rules there is no way that this program can work, and
no help from the compiler to tell you what is wrong.

Under the new rules, fp has a language linkage associated with
it, and cannot point to a function declared with a different
language linkage. The compiler tells you about any problems,
and also will automatically use the correct linkage to call
a function through a pointer.

When one vendor supplies compilers for all supported languages,
the calling conventions are likely to be compatible. But it is
common to find incompatible C compilers (for example) on the
same system. A third-party C++ vendor can't be compatible
with both of them, and might choose to define different
language linkages to let C++ programs work with either of the
C compilers.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/04
Raw View
In article <748o1q$ibf$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>You've also indicated that you don't think most compiler vendors will
>enforce this except in strict standard mode. I find that somewhat
>odd considering that you lobbied for the change.

I lobbied (actually supported IBM's representatives) for the change
because it was about the minimum fix left to deal with the problem of
allowing implementors to support linkage to other languages.  Without
this change such things as extern "fortran" remained largely of academic
interest unless the C++ and other language shared calling conventions.

IMO something had to be done to provide some utility for pointers to
functions with extern linkage specifications.

That it mattered to an existing implementor is relevant because
standards are not supposed to be deliberately antagonistic to the needs
of implementors.  (That is why we still have language support for such
things as 1's complement integers)

The reason that I believe most implementors will ignore it for extern
"C" and extern "C++" except in strict mode is because most of them have
identical calling conventions for their C & C++ compilers.



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/03
Raw View
In article <744503$kdb$1@engnews2.Eng.Sun.COM>,
Steve Clamage <stephen.clamage@sun.com> wrote:
>
>Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) writes:
>
>>If the intention with extern "<language>" was to allow for different
>>calling protols and name-manglings it should not only specify
>>the name of the language, but more (not only compilers, but allowing
>>e.g. extern "C-rtd","C++-rtd" on m68k would have been a possibility).
>
>That isn't feasible.

I'm not sure what you mean with 'not feasible.'

I only meant to imply that a compiler should be allowed to further
specify the calling protocols (e.g. the callee and not the caller
deallocates the parameters using rtd#), but not that every language linkage
specification should be a complete specification of the name-mangling,
calling protocols, etc.

Since the 'language linkage' is as you say open-ended there is nothing
illegal with supporting e.g. extern "C-rtd" as in my example
(except that 'language linkage' is a bit of a misnomer in that case).

>C++ implementations have many degrees of
>freedom, and even when calling conventions match, it is unlikely
>that that other things (like class layout and vtables in particular)
>would match. The C++ standard can't both allow this freedom and
>attempt to specify ways to indicate a particular set of
>implementation choices.

Exception handling, and memory management (mixing new/delete between
different compilers is not wise) also come to my mind.

I mention exception handling because this is already a problem when
calling C-functions, and e.g. egcs-1.0.3 does not handle the following
(it aborts instead of reporting "Caught exception"):

extern "C" int compar(const void *a,const void *b) {
  throw 4;
};
int main() {
  int x[4]={4,1,2,3};
  try {
    qsort(x,sizeof(x)/sizeof(x[0]),sizeof(x[0]),compar);
    cerr<<"No exception"<<endl;
  } catch (const int&) {
    cerr<<"Caught exception"<<endl;
  };
  return 0;
};

>The solution is an ABI (Application Binary Interface) for a
>platform (cpu + OS) that specifies the complete binary interface
>of a C++ program. Compilers that conform to the ABI can use
>code compiled by other conforming compilers directly. It is
>normally the job of the OS vendor (or owner of the OS trademark)
>to define such ABIs.

That would be a nice idea, but I think it will take awhile.
(At least until other vendors support the same ABI).

>The definition of language linkage in the C++ standard assumes no
>more than that a compatible C implemention exists.

But if we already assume that there exists a compatible C implementation
(in terms of struct layout etc.) I wouldn't think it excessive
to also suppose that the C implementation have the same calling
conventions (as in true in almost all cases). This would have allowed
pointers to extern "C" and extern "C++" functions to be identical.

I understand that it's too late for changing the standard, and
there is a simple work-around, but I think it would have been better
to consider extern "C" and extern "C++" as identical types (or
automatically generate forwarding functions when constructing
pointers to functions with non-C++ language linkage specifiers).

--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/12/03
Raw View
Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) writes:

>In article <744503$kdb$1@engnews2.Eng.Sun.COM>,
>Steve Clamage <stephen.clamage@sun.com> wrote:
>>
>>Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) writes:
>>
>>>If the intention with extern "<language>" was to allow for different
>>>calling protols and name-manglings it should not only specify
>>>the name of the language, but more (not only compilers, but allowing
>>>e.g. extern "C-rtd","C++-rtd" on m68k would have been a possibility).
>>
>>That isn't feasible.

>I'm not sure what you mean with 'not feasible.'

It sounded like you were saying the standard should require
language linkage to specify more than the name of the language.
That isn't feasible.

>I only meant to imply that a compiler should be allowed to further
>specify the calling protocols (e.g. the callee and not the caller
>deallocates the parameters using rtd#), but not that every language linkage
>specification should be a complete specification of the name-mangling,
>calling protocols, etc.

It is allowed. An implementation can define any additional linkage
strings it wants, with any semantics it wants.

...

>>The solution is an ABI (Application Binary Interface) for a
>>platform (cpu + OS) that specifies the complete binary interface
>>of a C++ program. Compilers that conform to the ABI can use
>>code compiled by other conforming compilers directly. It is
>>normally the job of the OS vendor (or owner of the OS trademark)
>>to define such ABIs.

>That would be a nice idea, but I think it will take awhile.

ABIs exist for many platforms. Sun, for example, has always
published the Solaris ABI, which defines the C interface.  Each
major release of C++ has been accompanied by an ABI supplement
for that release. (Each major release has included major new
language features that could not have been supported by the
previous ABI.)

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/03
Raw View
In article <743g9k$ame$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>If the intention with extern "<language>" was to allow for different
>calling protols and name-manglings it should not only specify
>the name of the language, but more (not only compilers, but allowing
>e.g. extern "C-rtd","C++-rtd" on m68k would have been a possibility).

And it is.  All the standard requires is support for extern "C" and
extern "C++".  It allows implementations to support any other linkage
specifications they choose to.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/03
Raw View
In article <7461nq$ia$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>I understand that it's too late for changing the standard, and
>there is a simple work-around, but I think it would have been better
>to consider extern "C" and extern "C++" as identical types (or
>automatically generate forwarding functions when constructing
>pointers to functions with non-C++ language linkage specifiers).

And one reason the change was made was exactly that an implementation of
C and C++ from the same source with incompatible function pointers
existed (and I believe there were good reasons for the incompatibility)



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: comeau@panix.com (Greg Comeau)
Date: 1998/12/04
Raw View
In article <t1N83$AcKsZ2Ewu2@robinton.demon.co.uk> Francis Glassborow <francisG@robinton.demon.co.uk> writes:

>In article <7461nq$ia$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
>writes
>>I understand that it's too late for changing the standard, and
>>there is a simple work-around, but I think it would have been better
>>to consider extern "C" and extern "C++" as identical types (or
>>automatically generate forwarding functions when constructing
>>pointers to functions with non-C++ language linkage specifiers).

>And one reason the change was made was exactly that an implementation of
>C and C++ from the same source with incompatible function pointers
>existed (and I believe there were good reasons for the incompatibility)

If what's being discussed is what I think it is, a number of compilers
can support a backward compatibility option whereas the two are considered
the same (of course in a non-strict mode).

- Greg
--
       Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
     Producers of Comeau C/C++ 4.2.38 -- New Release!  We now do Windows too.
    Email: comeau@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
                *** WEB: http://www.comeaucomputing.com ***


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/02
Raw View
In article <TRYBIpACACZ2EwL2@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <740cd2$g6h$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
>writes
>>Four question about the difference between pointers to functions
>>with different extern-specifiers:
>>
>>* Why does the standard differentiate between pointers to C and C++
>>functions?
>
>
>Because there is more to linkage specification than name-mangling.
>There is no reason why the calling protocols for C and C++ should be the
>same (and for different implementors this is even more the case)

There is no guarantee that the calling protols for C and C or for
that matter C++ and C++ should be the same (the name-mangling between
C++ and C++ will also differ).

AFAIK there are no extra difficulties introduced by the difference between
C and C++, compared to differencies between compilers for C/C++ in general.

If the intention with extern "<language>" was to allow for different
calling protols and name-manglings it should not only specify
the name of the language, but more (not only compilers, but allowing
e.g. extern "C-rtd","C++-rtd" on m68k would have been a possibility).

>>I assume there could exist a compiler that treat calls to C functions
>>differently from calls to C++ functions, but those compilers could have
>>dealt with it in other ways.
>Only with great difficulty.

Automatically constructing a forwarding function is not _that_ difficult
(if programmers can do it compilers can also do it).

There would of course be an overhead, but only for those who use
pointers to non-C++ functions on those compilers and machines.

If we now try to cure this problem by manually constructing forwarding
functions we have introduced the cost for all compilers and machines
(it cannot be optimized away because the addresses of the functions
should not compare equal).
--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/12/02
Raw View
Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) writes:

>If the intention with extern "<language>" was to allow for different
>calling protols and name-manglings it should not only specify
>the name of the language, but more (not only compilers, but allowing
>e.g. extern "C-rtd","C++-rtd" on m68k would have been a possibility).

That isn't feasible. C++ implementations have many degrees of
freedom, and even when calling conventions match, it is unlikely
that that other things (like class layout and vtables in particular)
would match. The C++ standard can't both allow this freedom and
attempt to specify ways to indicate a particular set of
implementation choices.

The solution is an ABI (Application Binary Interface) for a
platform (cpu + OS) that specifies the complete binary interface
of a C++ program. Compilers that conform to the ABI can use
code compiled by other conforming compilers directly. It is
normally the job of the OS vendor (or owner of the OS trademark)
to define such ABIs.

The definition of language linkage in the C++ standard assumes no
more than that a compatible C implemention exists.  OTOH, the
language linkage specification is open-ended.

An implementation can support any other languages or versions it
wants. For example, a compiler implementor on Wintel platforms could
choose to add "C++ Borland", "C++ MS", "C++ ecgs", and so on,
possibly further qualifying them further with version numbers.
(Apologies to the many other vendors I didn't mention.)

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/02
Raw View
In article <741s2u$1ql$1@engnews2.Eng.Sun.COM>,
  stephen.clamage@sun.com (Steve Clamage) wrote:
>
> AllanW@my-dejanews.com writes:
>
> >> >I think they have different signatures because the parameters are:
> >> >
> >> >pointer to extern "C" function
> >> >and
> >> >pointer to extern "C++" function
> >> >
> >> >and these types are differentiable.
>
> >Perhaps that's what was meant, but it isn't there.
> >    extern "C" int atexit(void (*f)(void))
> >    extern "C++" int atexit(void (*f)(void))
>
> A linkage directive on a function applies to the parameters.
> The parameters of the two atexit functions have different
> types, because the linkage is part of the type. Refer to
> 7.5 paragraph 4 in the standard, which includes an example
> like this.

Wow. I guess I hadn't noticed this before. This struck me as
counter-intuitive, because I expected the two tokens
    extern "C"
to somehow magically apply to the next identifier only, the
same way that int or static would. But the syntax is
    extern string-literal declaration
and 7.5 p4 does say that the "linkage applies to the function
types of all function declarators, function names, and variable
names introduced by the declaration(s)."

So, how do we create a function that has C++ linkage, but
accepts a parameter which points to a function with C linkage?
7.5 p4 also says "A linkage-specification shall occur only in
namespace scope." So my "intuitive" version:
    extern "C++" int plus_func(extern "C" void(*c_func)());
would seem to be illegal.

I know we can do this with a typedef, here's a variation on
an example in that paragraph:
    extern "C" typedef void FUNC_c();
    extern "C++" int plus_func(FUNC_c*c_func);
Is this possible without a typedef?

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/01
Raw View
In article <740cd2$g6h$1@news.lth.se>, Email_To <?.Olsson@dna.lth.se>
writes
>Four question about the difference between pointers to functions
>with different extern-specifiers:
>
>* Why does the standard differentiate between pointers to C and C++
>functions?


Because there is more to linkage specification than name-mangling.
There is no reason why the calling protocols for C and C++ should be the
same (and for different implementors this is even more the case) Where
an implementor is providing both as part of a development package they
migh elect to have different argument passing mechanisms for C and C++
(this is not purely academic, it used to be the case for IBM though I do
not know if it is still the case)  Therefore it was decided to recognise
this by allowing an implementor to use different call protocols for
different linkage specified functions (C, C++ etc)

>I assume there could exist a compiler that treat calls to C functions
>differently from calls to C++ functions, but those compilers could have
>dealt with it in other ways.
Only with great difficulty.

> Was there another reason (such as
>decreasing the use of extern "C"-functions)?

No, this was never even considered (I can say that with certainty
because I was one of those responsible for the change -- so you know who
to blame)

>* Does any compilers fully implement this feature?

I have know idea, the change was relatively late.

>* What is specified about math-functions (in <cmath>).
>In CD2 it is implementation-defined if they are extern "C" or extern "C++"
>and constructing a table of pointers to them is thus not possible.

Well if it matters, it is just as well that we can distinguish and when
it does not implementors are free to provide a conversion.

>Since atexit was changed this might also have changed.

atexit was only changed to allow both types of linkage specification
(and any others an implementor chose to support)

>* What about functions with different linkage as arguments to
>templates (e.g. functor-objects)?
>Will the template mechanism tell them apart?

The problem here is not whether the template mechanism can tell them
apart, but how to avoid code bloat when the particular implementation
has no need to distinguish (i.e. the function pointers for the
respective linkage specification are interconvertable.)

BTW the problem of linkage specifiers doing two things (linkage names
and argument passing protocols) has been a long standing problem.  In
the very beginning C++ was 'compiled' with CFront which simply
translated C++ to C.  The extern "C" simply said, in effect, this one
does not need translation.  The appearance of native C++ compilers threw
up the problem of argument passing protocols.


Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/01
Raw View

> >In article <73vc1v$5oe$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
> >writes
> >>Are these supposed to be overloaded functions, violating the rule
> >>that overloaded functions may not have identical signatures? Or is
> >>this supposed to be a list of alternatives, explaining that the
> >>implementors may choose to use either prototype? If it's the latter
> >>there should have been some note to that effect. (Or did I miss it?
> >>I don't see anything else like that in the standard...)


> >I think they have different signatures because the parameters are:
> >
> >pointer to extern "C" function
> >and
> >pointer to extern "C++" function
> >
> >and these types are differentiable.

Perhaps that's what was meant, but it isn't there.
    extern "C" int atexit(void (*f)(void))
    extern "C++" int atexit(void (*f)(void))
Perhaps these SHOULD read:
    extern "C" int atexit(extern "C" void (*f)(void))
    extern "C++" int atexit(extern "C++" void (*f)(void))




In article <740cd2$g6h$1@news.lth.se>,
  Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson) wrote:

> Four question about the difference between pointers to functions
> with different extern-specifiers:
>
> * Why does the standard differentiate between pointers to C and C++
> functions?
>
> I assume there could exist a compiler that treat calls to C functions
> differently from calls to C++ functions, but those compilers could have
> dealt with it in other ways. Was there another reason (such as
> decreasing the use of extern "C"-functions)?

Could you please give an example of one of those "other ways?" I
think that they would take up extra space and/or slow down calls
made through these pointers.

> * Does any compilers fully implement this feature?

Microsoft Visual C++ does, I think -- but I haven't tested it.

> * What is specified about math-functions (in <cmath>).
> In CD2 it is implementation-defined if they are extern "C" or extern "C++"
> and constructing a table of pointers to them is thus not possible.
>
> Since atexit was changed this might also have changed.

The standard says that C++ has all the math functions in <cmath>,
but also has additional functions which have the same name, but
are overloaded. Instead of a double, these functions take a float
or a long double. The standard even shows the prototypes for
these new functions. The prototypes shown do not include an
extern qualifier.

I imagine then, that this is still unspecified. Otherwise,
I can't find it.

> * What about functions with different linkage as arguments to
> templates (e.g. functor-objects)?
> Will the template mechanism tell them apart?

This happens when the template is expanded. There will normally
not be a problem with templates.

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/12/01
Raw View
AllanW@my-dejanews.com writes:

>> >I think they have different signatures because the parameters are:
>> >
>> >pointer to extern "C" function
>> >and
>> >pointer to extern "C++" function
>> >
>> >and these types are differentiable.

>Perhaps that's what was meant, but it isn't there.
>    extern "C" int atexit(void (*f)(void))
>    extern "C++" int atexit(void (*f)(void))

A linkage directive on a function applies to the parameters.
The parameters of the two atexit functions have different
types, because the linkage is part of the type. Refer to
7.5 paragraph 4 in the standard, which includes an example
like this.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: AllanW@my-dejanews.com
Date: 1998/12/01
Raw View
In article <365f3482.0@10.1.1.65>,
  "Andrei Alexandrescu" <alexandrescua@micromodeling.com> wrote:
>
> The question is: say I register function
>
> void foo();
>
> to be called by atexit. From within foo(), I call atexit() again and
> register the function:
>
> void bar();
>
> to be called. Will be bar() called?

Wow, good question. My first instinct told me that this was
implementation-defined; depending on details of how the implementor
wrote atexit(), it might or might never be called.

But I looked in the standard. It says that functions registered
with atexit() WILL be called. It lists several specific exceptions
to that rule, such as calling abort() or letting an exception call
terminate(). There is nothing that says that functions cannot be
registered after exit() has been called.

I would say that the program MUST execute bar() during a normal
termination.



I also have another question. 18.3 paragraph 4 lists two different
prototypes for the atexit() function. These prototypes are identical
except for the calling mechanism (one is extern "C" and the other is
extern "C++").

Are these supposed to be overloaded functions, violating the rule
that overloaded functions may not have identical signatures? Or is
this supposed to be a list of alternatives, explaining that the
implementors may choose to use either prototype? If it's the latter
there should have been some note to that effect. (Or did I miss it?
I don't see anything else like that in the standard...)

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/12/01
Raw View
AllanW@my-dejanews.com writes:

>In article <365f3482.0@10.1.1.65>,
>  "Andrei Alexandrescu" <alexandrescua@micromodeling.com> wrote:
>>
>> The question is: say I register function
>>
>> void foo();
>>
>> to be called by atexit. From within foo(), I call atexit() again and
>> register the function:
>>
>> void bar();
>>
>> to be called. Will be bar() called?

> ... I would say that the program MUST execute bar() during a normal
>termination.

The standard is self-contradictory on what must happen. On the
one hand, it doesn't forbid the code. On the other hand, it
requires that the last-registered function be called first. Thus,
bar must be called before foo, which is impossible.


>I also have another question. 18.3 paragraph 4 lists two different
>prototypes for the atexit() function. These prototypes are identical
>except for the calling mechanism (one is extern "C" and the other is
>extern "C++").

You missed the rule about linkage being part of the type of a
function and of a pointer-to-function. The first prototype
declares an atexit as a C-linkage function taking a pointer to
a C function. The second prototype declares an atexit to be
a C++-linkage function taking a pointer to a C++ function. The
parameter types are different, and these are overloaded functions.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/12/01
Raw View
In article <73vc1v$5oe$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
writes
>Are these supposed to be overloaded functions, violating the rule
>that overloaded functions may not have identical signatures? Or is
>this supposed to be a list of alternatives, explaining that the
>implementors may choose to use either prototype? If it's the latter
>there should have been some note to that effect. (Or did I miss it?
>I don't see anything else like that in the standard...)

I think they have different signatures because the parameters are:

pointer to extern "C" function
and
pointer to extern "C++" function

and these types are differentiable.



Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/12/01
Raw View
In article <fneilYAeA0Y2Ewh7@robinton.demon.co.uk>,
Francis Glassborow  <francisG@robinton.demon.co.uk> wrote:
>
>In article <73vc1v$5oe$1@nnrp1.dejanews.com>, AllanW@my-dejanews.com
>writes
>>Are these supposed to be overloaded functions, violating the rule
>>that overloaded functions may not have identical signatures? Or is
>>this supposed to be a list of alternatives, explaining that the
>>implementors may choose to use either prototype? If it's the latter
>>there should have been some note to that effect. (Or did I miss it?
>>I don't see anything else like that in the standard...)
>
>I think they have different signatures because the parameters are:
>
>pointer to extern "C" function
>and
>pointer to extern "C++" function
>
>and these types are differentiable.

Four question about the difference between pointers to functions
with different extern-specifiers:

* Why does the standard differentiate between pointers to C and C++
functions?

I assume there could exist a compiler that treat calls to C functions
differently from calls to C++ functions, but those compilers could have
dealt with it in other ways. Was there another reason (such as
decreasing the use of extern "C"-functions)?

* Does any compilers fully implement this feature?

* What is specified about math-functions (in <cmath>).
In CD2 it is implementation-defined if they are extern "C" or extern "C++"
and constructing a table of pointers to them is thus not possible.

Since atexit was changed this might also have changed.

* What about functions with different linkage as arguments to
templates (e.g. functor-objects)?
Will the template mechanism tell them apart?



--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/12/01
Raw View
AllanW@my-dejanews.com wrote:
....
> I also have another question. 18.3 paragraph 4 lists two different
> prototypes for the atexit() function. These prototypes are identical
> except for the calling mechanism (one is extern "C" and the other is
> extern "C++").
>
 Are these supposed to be overloaded functions, violating the rule
> that overloaded functions may not have identical signatures? Or is
> this supposed to be a list of alternatives, explaining that the
> implementors may choose to use either prototype? If it's the latter
> there should have been some note to that effect. (Or did I miss it?
> I don't see anything else like that in the standard...)

Paragraph 4 refers to the "atexit() functions", so apparantly there are
two of them. I don't understand how.



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: stephen.clamage@sun.com (Steve Clamage)
Date: 1998/11/30
Raw View
"Andrei Alexandrescu" <alexandrescua@micromodeling.com> writes:

>The question is: say I register function

>void foo();

>to be called by atexit. From within foo(), I call atexit() again and
>register the function:

>void bar();

>to be called. Will be bar() called?

Neither the C nor the C++ standards define what happens
after you register bar(). In fact, each is self-contradictory
on the matter!

The question was put to the C committee at their meeting last
month, and I have been told informally that the next C
standard will make the result undefined.

The C++ committee has the question on their list of potential
Defect Reports, and has yet to make a decision (on this or on
any other DR -- it's too soon to consider them). I expect
the C++ committee to declare the behavior to be undefined.

In the mean time, I know of at least one implementation that
crashes if you attempt to register a function with atexit
once exit processing has begun. So don't do it.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Andrei Alexandrescu" <alexandrescua@micromodeling.com>
Date: 1998/11/28
Raw View
Hello,

Someone told me that a similar thread existed once, but I haven't
found it.
The question is: say I register function

void foo();

to be called by atexit. From within foo(), I call atexit() again and
register the function:

void bar();

to be called. Will be bar() called?

Source code:

#include <iostream>
#include <stdlib.h>
using namespace std;

void bar()
{
    cout << "bar() called" << endl;
}

void foo()
{
    cout << "foo() called" << endl;
    atexit(bar);
}

int main()
{
    atexit(foo);
}

Thanks,

Andrei



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]