$ aCC -V
aCC: HP aC++/ANSI C B3910B A.06.06 [Nov 7 2005]
$ cat mangle-1.cc
typedef enum {
XSLDBG_MSG_THREAD_NOTUSED,
XSLDBG_MSG_THREAD_INIT
} XsldbgMessageEnum;
extern "C" {
void xsldbgSetAppFunc (int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type,
const void *data));
}
static int (*notifyXsldbgAppFuncPtr) (XsldbgMessageEnum type,
const void *data) = 0;
void xsldbgSetAppFunc (int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type,
const void *data)) {
notifyXsldbgAppFuncPtr = notifyXsldbgAppFunc;
}
$ aCC -c mangle-1.cc
$ nm mangle-1.o | grep -i xsldbg
[9] | 0| 48|FUNC |GLOB |0| .text|_Z16xsldbgSetAppFuncPFi17XsldbgMessageEnumPKvE
$ cat mangle-2.cc
typedef enum {
XSLDBG_MSG_THREAD_NOTUSED,
XSLDBG_MSG_THREAD_INIT
} XsldbgMessageEnum;
typedef int (*notifyXsldbgAppFuncType) (XsldbgMessageEnum type,
const void *data);
extern "C" {
void xsldbgSetAppFunc (notifyXsldbgAppFuncType notifyXsldbgAppFunc);
}
static notifyXsldbgAppFuncType notifyXsldbgAppFuncPtr = 0;
void xsldbgSetAppFunc (notifyXsldbgAppFuncType notifyXsldbgAppFunc) {
notifyXsldbgAppFuncPtr = notifyXsldbgAppFunc;
}
$ aCC -c mangle-2.cc
$ nm mangle-2.o | grep -i xsldbg
[9] | 0| 48|FUNC |GLOB |0| .text|_Z16xsldbgSetAppFuncPFi17XsldbgMessageEnumPKvE
[9] | 0| 48|FUNC |GLOB |0| .text|xsldbgSetAppFunc
Based on feedback from HP, mangle-1.cc has two xsldbgSetAppFunc()
functions with different types. The linkage of a parameter that is a
function is considered in its type.
--
albert chin (china @at@ thewrittenword .dot. com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Forget the mangling. It's a well known restriction:
#include <pthread.h>
void* thread( void* ) ;
// ...
pthread_create( &threadId, NULL, thread, NULL ) ;
shouldn't compile, because pthread_create takes a function with
extern "C" linkage, where as thread has extern "C++". (The
problem typically manifests itself in that someone wants to pass
pthread_create a static member function. And there is no way to
declare a static member function with "C" linkage.) Sun CC, in
fact, gives a warning:
"xc.cc", line 10: Warning (Anachronism): Formal argument 3 of type
extern "C" void*(*)(void*) in call to pthread_create(unsigned*, const
_pthread_attr*, extern "C" void*(*)(void*), void*) is being passed
void*(*)(void*).
If you think about what language linkage means, it's obvious.
There is no requirement that C and C++ use the same calling
conventions -- in fact, I've used compilers (the original
Zortech, under MS-DOS, for example) where they didn't.
With regards to the standard, §7.5/1: "[...] Two function types
with different language linkage are distinct types even if they
are otherwise identical." Because it is a violation of the type
rules, a compiler is required to issue a diagnostic. Beyond
that, it may support the operation as an extension, but if it
doesn't issue at least a warning, the compiler is not conform.
(Note, however, that most compilers are not strictly conformant
by default. You typically need extra options to turn off
extensions.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
7.5/1: All function types, function names and variable names have
language linkage.
Here's an example you can use to test your compilers:
extern "C"
{
typedef void (*cLink)();
void cFunc ();
}
typedef void (*cppLink) ();
void bar (cLink);
void bar (cppLink);
void foo ()
{
bar (foo); // calls 'bar(cppLink)'
bar (cFunc); // calls 'bar(cLink)'
}
If the compiler says they're ambiguous then it is not treating the
function types correctly.
Regards,
Richard
--
Richard Corden
How do I prove that xsldbgSetAppFunc() has C++ linkage? The person
assigned to the case from the IBM compiler group believes
xsldbgSetAppFunc() has C linkage because of the declaration in extern
"C". They've used 7.5/5 to back this up but I don't see how it applies
to this case at all. 7.5/1 is useful if I can prove that the
xsldbgSetAppFunc() definition has C++ linkage but I still don't see
how to do that.
--
albert chin (china @at@ thewrittenword .dot. com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
> How do I prove that xsldbgSetAppFunc() has C++ linkage? The person
> assigned to the case from the IBM compiler group believes
> xsldbgSetAppFunc() has C linkage because of the declaration in extern
> "C". They've used 7.5/5 to back this up but I don't see how it applies
> to this case at all.
It looks to me like the IBM-er is correct. What 7.5/5 means is that
once a function declaration with an explicit language linkage specifier
has been seen within a translation unit, a subsequent declaration or
definition with no explicit language linkage specifier has the language
linkage explicitly specified earlier.
The following should compile:
extern "C" { void foo(); }
void foo();
because the second line re-declares foo() with the same language
linkage ("C").
The following will not compile:
extern "C" { void foo(); }
extern "C++" { void foo(); }
> >> extern "C" {
> >> void xsldbgSetAppFunc (int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type,
> >> const void *data));
> >> }
> >> void xsldbgSetAppFunc (int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type,
> >> const void *data)) {
> >> notifyXsldbgAppFuncPtr = notifyXsldbgAppFunc;
> >> }
[...]
> How do I prove that xsldbgSetAppFunc() has C++ linkage? The
> person assigned to the case from the IBM compiler group
> believes xsldbgSetAppFunc() has C linkage because of the
> declaration in extern "C".
What's to prove? You have two different overloaded functions,
one with C linkage, and the other with C++ linkage.
> They've used 7.5/5 to back this up but I don't see how it
> applies to this case at all.
Well, it is a bit wishy-washy. I don't see how you can get two
declarations of the same function with different
linkage-specifications, at least where "C" and "C++" are
concerned. The standard leaves a lot more leeway with regards
to other linkages, and presumably, something like:
extern "C" void f() ;
extern "Fortran" void f() ;
would be either an error requiring a diagnostic (if in the same
translation unit) or undefined behavior (if they are in
different translation units).
But §7.5/1 clearly states that you have two different functions
here.
> 7.5/1 is useful if I can prove that the xsldbgSetAppFunc()
> definition has C++ linkage but I still don't see how to do
> that.
It has no linkage declaration. The default is linkage is C++.
That would seem to be conclusive. §7.5/1 makes it quite clear
that 'extern "C" void f()' and 'void f()' have two different
types. It even has examples of it in the library, e.g. atexit
in §18.3/3. Do they claim that the library requires something
forbidden by §7.5/5?
(Actually, I suppose one could argue the question if the
function didn't take a pointer to a function as a parameter,
although I think the standard is clear enough. I don't think
that there is any way of claiming that the type of
notifyXsldbgAppFunc in your two functions is the same, however
-- in one function, it is a pointer to an 'extern "C"' function,
and in the other, it is a pointer to an 'extern "C++"' function.
And when two functions are declared to take different types as
parameters, they are different functions. Always.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
> > How do I prove that xsldbgSetAppFunc() has C++ linkage? The
> > person assigned to the case from the IBM compiler group
> > believes xsldbgSetAppFunc() has C linkage because of the
> > declaration in extern "C". They've used 7.5/5 to back this
> > up but I don't see how it applies to this case at all.
> It looks to me like the IBM-er is correct. What 7.5/5 means
> is that once a function declaration with an explicit language
> linkage specifier has been seen within a translation unit, a
> subsequent declaration or definition with no explicit language
> linkage specifier has the language linkage explicitly
> specified earlier.
Yes. I didn't read the paragraph fully in my previous reply.
However, this doesn't apply to his example.
> The following should compile:
> extern "C" { void foo(); }
> void foo();
> because the second line re-declares foo() with the same language
> linkage ("C").
> The following will not compile:
> extern "C" { void foo(); }
> extern "C++" { void foo(); }
One could argue that we have an overloaded function foo, because
the two functions have different types. On the other hand, I
don't see how overload resolution could ever choose between
them, so I doubt that this is really the intent.
On the other hand:
extern "C" { void foo( int ) ; }
void foo( double ) ;
Definitly declares two different functions. And in his example,
we have the equivalent of:
extern "C" {
void foo ( int (*)() ) ;
// Function foo taking a parameter of type
// extern "C" int (*)()
}
void foo( int (*)() ) ;
// Function foo taking a parameter of type
// extern "C++" int (*)()
The parameters are of different types, just as in the case where
one is an int, and the other a double.
As I mentionned in my earlier posting, there is an example of
this in the library: the standard requires atexit to be
overloaded exactly like his code is.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
> However, this doesn't apply to his example.
Right, I see that now. Pesky function pointer parameter!
Looking back at the OP's original code, it looks like mangle-1.cc does
the following:
(1) declares a function with C linkage taking a pointer to a function
with C linkage, and
(2) declares & defines a function with C++ linkage taking a pointer
to a function with C++ linkage
while mangle-2.cc:
(3) declares & defines a function with C linkage taking a pointer to
a function with C++ linkage
Or am I still missing something?