Is the HP/IA64 C++ compiler correct?

2 views
Skip to first unread message

Albert Chin

unread,
Feb 20, 2006, 6:50:21 PM2/20/06
to
We have a piece of code that compiles differently with the HP-UX C++
compiler on IA64. According to HP, their compiler is behaving
correctly, so we're trying to convince other vendors to fix their C++
compiler. Can someone provide a reference in the C++ standard we can
use to determine if the HP C++ is correct?

$ 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! ]

kanze

unread,
Feb 21, 2006, 5:09:18 AM2/21/06
to

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

Richard Corden

unread,
Feb 21, 2006, 4:35:08 PM2/21/06
to
Albert Chin wrote:
> We have a piece of code that compiles differently with the HP-UX C++
> compiler on IA64. According to HP, their compiler is behaving
> correctly, so we're trying to convince other vendors to fix their C++
> compiler. Can someone provide a reference in the C++ standard we can
> use to determine if the HP C++ is correct?

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

Albert Chin

unread,
Feb 22, 2006, 6:25:19 AM2/22/06
to
kanze <ka...@gabi-soft.fr> wrote:

> Albert Chin wrote:
>
>> extern "C" {
>> void xsldbgSetAppFunc (int (*notifyXsldbgAppFunc) (XsldbgMessageEnum type,
>> const void *data));
>> }
>
>> 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
>
> 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.)

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 ]

john...@yahoo.com

unread,
Feb 22, 2006, 8:37:46 PM2/22/06
to
Albert Chin wrote:

> 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(); }

kanze

unread,
Feb 23, 2006, 9:05:48 AM2/23/06
to
Albert Chin wrote:
> kanze <ka...@gabi-soft.fr> wrote:
> > Albert Chin wrote:

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

kanze

unread,
Feb 23, 2006, 9:07:15 AM2/23/06
to
john...@yahoo.com wrote:
> Albert Chin wrote:

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

john...@yahoo.com

unread,
Feb 23, 2006, 1:07:08 PM2/23/06
to
kanze wrote:

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

Reply all
Reply to author
Forward
0 new messages