Does the standard specify calling conventions?

S

Stuart Redmann

Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

Thanks in advance,
Stuart
 
I

Ian Collins

Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

The latter unfortunately.
 
B

BGB / cr88192

Stuart Redmann said:
Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

technically, it is an implementation detail, as far as any standards are
concerned...

FWIW, that code actually runs on computers is an implementation detail.

however, these calling conventions are generally well accepted, and often
used across language boundaries as well.
 
M

Marcel Müller

Stuart said:
does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions)

No, and it will never. Note that a calling convention that works on
Hardware X may not even exist on Hardware Y, e.g because there are less
registers available or the stack alignment is different.

If you need to rely on calling conventions (most probably for
callbacks), you have to deal with platform specific extensions.


Marcel
 
G

Goran Pusic

Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

The latter. Standard can't possibly specify calling conventions, not
unless it wants to make massive presumptions about the underlying
hardware. Take a look e.g. at i960 CPU (http://en.wikipedia.org/wiki/
Intel_i960#Architecture) and register windows featured by this CPU
(http://en.wikipedia.org/wiki/Register_window). Compiling for this is
wildly different from anything one would want to do on x86. What good
would it be trying to standardize in such a situation? That's why
(among other things) why standard talks about abstract execution
machine or what's it named.

OTOH, calling conventions are hardware- and system- specific, so
system and hardware is what one should be looking at. Tool chains are
in practice obliged to adhere to that, and to the prevailing tool
chain's way of working (e.g. gcc on linux, msc on windows).

Goran.
 
S

Stuart Redmann

Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

Thanks for the quick answer Ian, BGB, Marcel and Goran.
[The answer I received was that the later is the case.]

I stumbled over this when someone in this newsgroup asked about IO
manipulators for his ostream-derived class (see
(e-mail address removed)). I
posted some code that works under MS Visual C, and would be standard-
conformant WRT calling conventions, but still does work on his
machine:
std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
(std::eek:stream&));
cannot be compiled with his version of the STL because it doesn't know
__cdecl.

Am I getting this 100% right: Above definition of IO manipulators is
standard-conformant? Or are IO manipulators not part of the standard?

Thanks,
Stuart
 
I

Ian Collins

Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

Thanks for the quick answer Ian, BGB, Marcel and Goran.
[The answer I received was that the later is the case.]

I stumbled over this when someone in this newsgroup asked about IO
manipulators for his ostream-derived class (see
(e-mail address removed)). I
posted some code that works under MS Visual C, and would be standard-
conformant WRT calling conventions, but still does work on his
machine:
std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
(std::eek:stream&));
cannot be compiled with his version of the STL because it doesn't know
__cdecl.

Am I getting this 100% right: Above definition of IO manipulators is
standard-conformant? Or are IO manipulators not part of the standard?

"__cdecl" is a windows thingy, not used elsewhere.
 
S

Stuart Redmann

Thanks for the quick answer Ian, BGB, Marcel and Goran.
[The answer I received was that the later is the case.]
I stumbled over this when someone in this newsgroup asked about IO
manipulators for his ostream-derived class (see
(e-mail address removed)). I
posted some code that works under MS Visual C, and would be standard-
conformant WRT calling conventions, but still does work on his
machine:
std::eek:stream&  operator<<  (std::eek:stream&  (__cdecl *_F)
(std::eek:stream&));
cannot be compiled with his version of the STL because it doesn't know
__cdecl.
Am I getting this 100% right: Above definition of IO manipulators is
standard-conformant? Or are IO manipulators not part of the standard?


"__cdecl" is a windows thingy, not used elsewhere.

Right. But is it standard-compliant? According to
http://www.cplusplus.com/reference/iostream/ostream/operator<</ I
would say no. However, the answers I got this far give me the
impression that the standard does not disallow the usage of calling
convention modifiers. This would mean that above code would be
standard-conformant.

What I actually want is the clarity that the standard disallows above
code (at best with section number and everything) because else I'll
become a LabView programmer (shudder). Or rather join the forces and
become a Ada95 programmer ;-)

Thanks,
Stuart
 
I

Ian Collins

On 13 Sep., Stuart Redmann wrote:
Hello newsgroup,
does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?
Thanks for the quick answer Ian, BGB, Marcel and Goran.
[The answer I received was that the later is the case.]
I stumbled over this when someone in this newsgroup asked about IO
manipulators for his ostream-derived class (see
(e-mail address removed)). I
posted some code that works under MS Visual C, and would be standard-
conformant WRT calling conventions, but still does work on his
machine:
std::eek:stream& operator<< (std::eek:stream& (__cdecl *_F)
(std::eek:stream&));
cannot be compiled with his version of the STL because it doesn't know
__cdecl.
Am I getting this 100% right: Above definition of IO manipulators is
standard-conformant? Or are IO manipulators not part of the standard?


"__cdecl" is a windows thingy, not used elsewhere.

Right. But is it standard-compliant? According to
http://www.cplusplus.com/reference/iostream/ostream/operator<</ I
would say no. However, the answers I got this far give me the
impression that the standard does not disallow the usage of calling
convention modifiers. This would mean that above code would be
standard-conformant.

The only calling convention modifier cites in the standard is
extern "C". Anything else is a compiler specific extension.
What I actually want is the clarity that the standard disallows above
code (at best with section number and everything) because else I'll
become a LabView programmer (shudder). Or rather join the forces and
become a Ada95 programmer ;-)

It can't disallow something it knows nothing about. As soon as you
start using compiler specific extensions, your code is no longer
standard C++.
 
S

Stuart Redmann

[snipped original question about calling convention modifiers like
MS's __cdecl in STL code]

The only calling convention modifier cites in the standard is
extern "C".  Anything else is a compiler specific extension.

It can't disallow something it knows nothing about.  As soon as you
start using compiler specific extensions, your code is no longer
standard C++.

Thanks for the clarification. I guess that this is another item on
MS's list where the product is not standard-conformant.

Thanks,
Stuart
 
G

gwowen

Thanks for the clarification. I guess that this is another item on
MS's list where the product is not standard-conformant.

Well, global identifiers that start with an underscore are reserved
for the implementation, so any user code that utilises them is non-
standard compliant. The compiler can decided __cdecl means whatever it
wants it to.
 
R

robertwessel2

[snipped original question about calling convention modifiers like
MS's __cdecl in STL code]

It can't disallow something it knows nothing about.  As soon as you
start using compiler specific extensions, your code is no longer
standard C++.

Thanks for the clarification. I guess that this is another item on
MS's list where the product is not standard-conformant.


No, it's perfectly allowed for MS to add non-standard extensions to
the language, particularly if the keep them in the implementation
namespace, as __cdecl is. GCC, for example, provides similar function
via __attribute__. Neither is part of the standard.

It's not quite clear what the function in question is doing, but it
appears you're trying to define a an insertion operator in a template
that uses a funcion that uses __cdecl calling conventions. Why? What
is being accomplished by that? Inherently this code is doing
something platform specific, and is non-portable.

Where is this coding coming from? What's the context?
 
B

Bo Persson

[snipped original question about calling convention modifiers like
MS's __cdecl in STL code]

It can't disallow something it knows nothing about. As soon as you
start using compiler specific extensions, your code is no longer
standard C++.

Thanks for the clarification. I guess that this is another item on
MS's list where the product is not standard-conformant.


No, it's perfectly allowed for MS to add non-standard extensions to
the language, particularly if the keep them in the implementation
namespace, as __cdecl is. GCC, for example, provides similar
function via __attribute__. Neither is part of the standard.

It's not quite clear what the function in question is doing, but it
appears you're trying to define a an insertion operator in a
template that uses a funcion that uses __cdecl calling conventions.
Why? What is being accomplished by that? Inherently this code is
doing something platform specific, and is non-portable.

Where is this coding coming from? What's the context?

The __cdecl is the default calling convention. It is there in headers
for precompiled library code, just in case the user code is compiled
with some other calling convention.

If you compile with a non-MS compiler, you cannot likely use the same
precompiled library anyway, so a quick

#define __cdecl /*nothing*/

would fix that.


Bo Persson
 
J

Johannes Schaub (litb)

Stuart said:
Hello newsgroup,

does the C++ standard say anything about calling conventions (http://
en.wikipedia.org/wiki/X86_calling_conventions) or is this an
implementation detail?

The only thing the Standard says is that linkage specifications may affect
calling conventions.

Effectively, that has to be done by changing the linkage specification on
the underlying function type:

extern "C" typedef void ccalling();

ccalling f; // c calling convention
void f(); // c++ calling convention

These two have different types: Bases on the type of a function type
expression, the compiler can figure out what calling convention to use.
 
J

James Kanze

On 13 Sep., Ian Collins wrote:
Right. But is it standard-compliant? According
tohttp://www.cplusplus.com/reference/iostream/ostream/operator<</
I would say no. However, the answers I got this far give me
the impression that the standard does not disallow the usage
of calling convention modifiers. This would mean that above
code would be standard-conformant.

It depends on your point of view. The standard says that
identifiers beginning with __ are "undefined behavior". In
other words, an implementation can do whatever it wants when
a program contains one. In this case, the "undefined behavior"
is there precisely to allow compilers to create extensions
without running the risk of breaking standard conformant
code---both VC++ and g++ make extensive use of this feature.
From a compiler implementor's point of view: adding additional
keywords does not render the compiler non compliant, as long as
the keywords start with __. From a user's point of view: if you
have a symbol in your code which starts with __, that code is
not compliant. It is using an implementation defined extension.
What I actually want is the clarity that the standard
disallows above code (at best with section number and
everything) because else I'll become a LabView programmer
(shudder). Or rather join the forces and become a Ada95
programmer ;-)

§17.4.3.1.2: "Each name that contains a double underscore (__)
or begins with an underscore followed by an uppercase letter
(2.11) is reserved to the implementation for any use."
 
R

robertwessel2

[snipped original question about calling convention modifiers like
MS's __cdecl in STL code]
On 13 Sep., Ian Collins wrote:
It can't disallow something it knows nothing about. As soon as you
start using compiler specific extensions, your code is no longer
standard C++.
Thanks for the clarification. I guess that this is another item on
MS's list where the product is not standard-conformant.
No, it's perfectly allowed for MS to add non-standard extensions to
the language, particularly if the keep them in the implementation
namespace, as __cdecl is.  GCC, for example, provides similar
function via __attribute__.  Neither is part of the standard.
It's not quite clear what the function in question is doing, but it
appears you're trying to define a an insertion operator in a
template that uses a funcion that uses __cdecl calling conventions.
Why?  What is being accomplished by that?  Inherently this code is
doing something platform specific, and is non-portable.
Where is this coding coming from?  What's the context?

The __cdecl is the default calling convention. It is there in headers
for precompiled library code, just in case the user code is compiled
with some other calling convention.


For MSVC, for a member function, the default calling conventions is
__thiscall. Basically you cannot pass a this pointer with __cdecl.

If you compile with a non-MS compiler, you cannot likely use the same
precompiled library anyway, so a quick

#define __cdecl  /*nothing*/

would fix that.


It's still unclear where this code is coming from. If the OP is
trying to use a Windows specific header file, the associated library
is unlikely to be available in binary form on other platforms in a
form intended to be used with the Windows specific header. And I'm
still having trouble trying to understand what the function is
supposed to do in practical terms.
 
S

Stuart Redmann

[snipped discussion about whether calling convention modifiers make
STL code non-compliant]

It's still unclear where this code is coming from. If the OP is
trying to use a Windows specific header file, the associated library
is unlikely to be available in binary form on other platforms in a
form intended to be used with the Windows specific header. And I'm
still having trouble trying to understand what the function is
supposed to do in practical terms.

The code in question is from MS's ostream header (in the code I have
posted recently I took the liberty to replace the type _Myt with
std::eek:stream, but it is actually typedef'ed as basic_ostream<_E,
_Tr>):

template<class _E, class _Tr = char_traits<_E> >
class basic_ostream : virtual public basic_ios<_E, _Tr> {
public:
typedef basic_ostream<_E, _Tr> _Myt;

[snip]

_Myt& operator<<(_Myt& (__cdecl *_F)(_Myt&))
{
return ((*_F)(*this));
}
[snip]
};

I understand that above definition adds a definition that is not part
of the standard. So it would be still right to say that MS's iostream
header is not standard-conformant because it lacks the required
operator that takes standard IO manipulators, wouldn't it?

Thanks,
Stuart
 
R

robertwessel2

[snipped discussion about whether calling convention modifiers make
STL code non-compliant]

It's still unclear where this code is coming from.  If the OP is
trying to use a Windows specific header file, the associated library
is unlikely to be available in binary form on other platforms in a
form intended to be used with the Windows specific header.  And I'm
still having trouble trying to understand what the function is
supposed to do in practical terms.

The code in question is from MS's ostream header (in the code I have
posted recently I took the liberty to replace the type _Myt with
std::eek:stream, but it is actually typedef'ed as basic_ostream<_E,
_Tr>):

template<class _E, class _Tr = char_traits<_E> >
        class basic_ostream : virtual public basic_ios<_E, _Tr> {
public:
        typedef basic_ostream<_E, _Tr> _Myt;

[snip]

        _Myt& operator<<(_Myt& (__cdecl *_F)(_Myt&))
        {
                return ((*_F)(*this));
        }
[snip]

};

I understand that above definition adds a definition that is not part
of the standard. So it would be still right to say that MS's iostream
header is not standard-conformant because it lacks the required
operator that takes standard IO manipulators, wouldn't it?


The *contents* of the ostream header (and any other standard header)
should largely be considered totally non-portable. IOW, you cannot
expect MS's ostream for VC++ to do anything, even compile, on another
platform, even another MS platform, or even a different version of VC+
+.

Nor does what you posted look quite like the code in VC++'s headers,
at least the couple of current versions that I took a look at. From
which version are you getting this? In any event, several definitions
of similar form are passing an explicit this pointer to the passed
function.

Is this MSVC 6? Looking back at that it looks like you pulled the
code from the MSVC6 headers. Note that MSVC6 has a number of
significant deviations in its template support from the final C++
standard. MS, along with several other compiler vendors, got hit by a
late, and significant, change in the standard's definition of
templates. Basically MSVC6 was released before the C++98 standard was
finalized. They implemented template support as it was in the draft
standard, and then (along with several other vendors) got hit when the
standard changed. MS's policy is that they try to avoid source-code-
breaking changes *within* a release, so they never "fixed" the
template support in MSVC6. But they did in the next release (MSVC7
aka "Visual C++ .NET 2.0").

But again, where are you going with this? Have you found some flaw in
VC++'s ostream implementation? Remember, *how* ostream (or anything
else) is implemented is implementation specific, just so long as it
does the right thing, as specified by the standard. How is this
(MSVC internal)code with the calling convention attribute impacting
your code? Or at least a problem from a compiler less than a dozen
years old, and from after the C++ standard was finished?
 
B

Bo Persson

Stuart said:
[snipped discussion about whether calling convention modifiers make
STL code non-compliant]

It's still unclear where this code is coming from. If the OP is
trying to use a Windows specific header file, the associated
library is unlikely to be available in binary form on other
platforms in a form intended to be used with the Windows specific
header. And I'm still having trouble trying to understand what
the function is supposed to do in practical terms.

The code in question is from MS's ostream header (in the code I have
posted recently I took the liberty to replace the type _Myt with
std::eek:stream, but it is actually typedef'ed as basic_ostream<_E,
_Tr>):

template<class _E, class _Tr = char_traits<_E> >
class basic_ostream : virtual public basic_ios<_E, _Tr> {
public:
typedef basic_ostream<_E, _Tr> _Myt;

[snip]

_Myt& operator<<(_Myt& (__cdecl *_F)(_Myt&))
{
return ((*_F)(*this));
}
[snip]
};

I understand that above definition adds a definition that is not
part of the standard. So it would be still right to say that MS's
iostream header is not standard-conformant because it lacks the
required operator that takes standard IO manipulators, wouldn't it?

No, __cdecl is the default calling convention, so if you provide a
function with a stream reference parameter and return value, it will
be usable as a stream manipulator (inserting the function into the
stream, calls the function with the stream as a parameter).


Bo Persson
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top