Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

'class' and 'struct' at link time

52 views
Skip to first unread message

gwowen

unread,
Jun 9, 2015, 6:13:52 AM6/9/15
to
Just hit the following in VS2013


// x.hpp
class Xpimpl;

class X
{
Xpimpl *p;
public:
X(int a_);
void frob();
};

// x.cpp
#include "x.hpp"
struct Xpimpl
{
int a;
};

X::X(int a_)
: p(new Xpimpl) {
p->a = a_;
}

void X::frob()
{
++p->a;
}

/// main.cpp
int main(void)
{
X x(7);
x.frob();
}

This compiles and runs with g++ / Ubuntu but give a linker error in VS2013.

The reason seems to be that Xpimpl is forward declared as a "class" but actually declared as a struct. Change the forward declaration to

struct Xpimpl;

and everything works. So ... compiler bug, or UB due to subtle mismatch in declaration and definition.

Mel

unread,
Jun 9, 2015, 6:28:46 AM6/9/15
to
On Tue, 9 Jun 2015 03:13:33 -0700 (PDT), gwowen <gwo...@gmail.com>
wrote:
I guess that compiler is allowed to mangle class or struct as well.
But this is not logical as one can't define both class and struct
with same name.

--
Press any key to continue or any other to quit

Öö Tiib

unread,
Jun 9, 2015, 7:32:27 AM6/9/15
to
It looks like a compiler bug.

The 'struct' and 'class' mean same thing in context of forward declaration.
I am not sure why such inconsistent usage is permitted but AFAIK it
must compile and run.

Thomas Richter

unread,
Jun 9, 2015, 10:41:02 AM6/9/15
to
On 09.06.2015 13:32, Öö Tiib wrote:
> On Tuesday, 9 June 2015 13:13:52 UTC+3, gwowen wrote:
>> Just hit the following in VS2013
>
>> and everything works. So ... compiler bug, or UB due to subtle mismatch in declaration and definition.
>
> It looks like a compiler bug.
>
> The 'struct' and 'class' mean same thing in context of forward declaration.
> I am not sure why such inconsistent usage is permitted but AFAIK it
> must compile and run.
>

Unfortunately, this bug has a long tradition in VS, it exists at least
since VS6 (ancient, pre-dates ANSI C++). Despite being a bug, I would at
least consider it reasonable to use "class" and "struct" consistently,
and that a compiler would emit a warning in case it is not - even though
C++ allows the mixture.


Greetings,
Thomas

Richard

unread,
Jun 9, 2015, 1:02:07 PM6/9/15
to
[Please do not mail me a copy of your followup]

Thomas Richter <th...@math.tu-berlin.de> spake the secret code
<ml6ttj$10v$1...@news2.informatik.uni-stuttgart.de> thusly:

>On 09.06.2015 13:32, 嘱 Tiib wrote:
>> On Tuesday, 9 June 2015 13:13:52 UTC+3, gwowen wrote:
>>> Just hit the following in VS2013
>>
>>> and everything works. So ... compiler bug, or UB due to subtle
>mismatch in declaration and definition.
>>
>> It looks like a compiler bug.
>>
>> The 'struct' and 'class' mean same thing in context of forward declaration.
>> I am not sure why such inconsistent usage is permitted but AFAIK it
>> must compile and run.
>>
>
>Unfortunately, this bug has a long tradition in VS, it exists at least
>since VS6 (ancient, pre-dates ANSI C++). Despite being a bug, [...]

I don't think it's a bug so much as implementation defined behavior.
The compiler has pretty broad latitude in deciding how to mangle names.

I'd love to know which part of the standard prohibits this behavior or
declares it undefined behavior.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

David Brown

unread,
Jun 9, 2015, 2:15:43 PM6/9/15
to
On 09/06/15 19:01, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Thomas Richter <th...@math.tu-berlin.de> spake the secret code
> <ml6ttj$10v$1...@news2.informatik.uni-stuttgart.de> thusly:
>
>> On 09.06.2015 13:32, 嘱 Tiib wrote:
>>> On Tuesday, 9 June 2015 13:13:52 UTC+3, gwowen wrote:
>>>> Just hit the following in VS2013
>>>
>>>> and everything works. So ... compiler bug, or UB due to subtle
>> mismatch in declaration and definition.
>>>
>>> It looks like a compiler bug.
>>>
>>> The 'struct' and 'class' mean same thing in context of forward declaration.
>>> I am not sure why such inconsistent usage is permitted but AFAIK it
>>> must compile and run.
>>>
>>
>> Unfortunately, this bug has a long tradition in VS, it exists at least
>> since VS6 (ancient, pre-dates ANSI C++). Despite being a bug, [...]
>
> I don't think it's a bug so much as implementation defined behavior.
> The compiler has pretty broad latitude in deciding how to mangle names.
>
> I'd love to know which part of the standard prohibits this behavior or
> declares it undefined behavior.
>

The nearest I found is in section 7.1.6.3 of N3797 (C++14 standards),
under "Elaborated type specifiers" :


The class-key or enum keyword present in the elaborated-type-specifier
shall agree in kind with the declaration to which the name in the
elaborated-type-specifier refers. This rule also applies to the form of
elaborated-type-specifier that declares a class-name or friend class
since it can be construed as referring to the definition of the class.
Thus, in any elaborated-type-specifier, the enum keyword shall be used
to refer to an enumeration (7.2), the union class-key shall be used to
refer to a union (Clause 9), and either the class or struct class-key
shall be used to refer to a class (Clause 9) declared using the class or
struct class-key.


That doesn't seem precise enough wording to decide the rule.


Bo Persson

unread,
Jun 9, 2015, 2:27:12 PM6/9/15
to
On 2015-06-09 20:15, David Brown wrote:
> On 09/06/15 19:01, Richard wrote:
>> [Please do not mail me a copy of your followup]
>>
>> Thomas Richter <th...@math.tu-berlin.de> spake the secret code
>> <ml6ttj$10v$1...@news2.informatik.uni-stuttgart.de> thusly:
>>
We have to know that a 'class' is declared using a 'class-key', which is
one of class, struct, or union.

The intention is that

"either the class or struct class-key shall be used to refer to a class
(Clause 9) declared using the class or struct class-key. "

should tell us that, unlike enum and union, "either [...] class or
struct" can be used to refer to a non-union class.



Bo Persson

Chris Vine

unread,
Jun 9, 2015, 3:52:38 PM6/9/15
to
I have come across this outside VS when specializing std::hash for a
type which might be used as the key for an unordered container. The
standard does not specify whether the std::hash<T> class template type
is defined using the 'class' or 'struct' keyword. §20.8.12 of the C++11
standard uses the 'struct' keyword when specifying the specializations
required by the standard, but only requires that any given
specialization must comprise a 'class template'.

clang exhibits the annoying behaviour of emitting a bogus warning if
you provide a hash specialization using a different keyword from the
one which happens to be used by the C++ standard library in question
for std::hash<T>, which means that if you use clang with a recent
version of libstdc++ you get the warning when using the 'struct' keyword
instead of the 'class' keyword for a specialization. I am glad to say
that gcc does not do this.

Chris



Lőrinczy Zsigmond

unread,
Jun 10, 2015, 3:56:06 AM6/10/15
to
> Change the forward declaration to
>
> struct Xpimpl;
>
> and everything works. So ...
> compiler bug, or UB due to subtle mismatch
> in declaration and definition.

Typical case of PEBKAC.
True, g++ should have omitted a warning.

gwowen

unread,
Jun 10, 2015, 4:42:02 AM6/10/15
to
On Wednesday, June 10, 2015 at 8:56:06 AM UTC+1, Lőrinczy Zsigmond wrote:
> > Change the forward declaration to
> >
> > struct Xpimpl;
> >
> > and everything works. So ...
> > compiler bug, or UB due to subtle mismatch
> > in declaration and definition.
>
> Typical case of PEBKAC.

Well, clearly. Never suggested otherwise. Fixed it long before posting

But thanks for the input. Very helpful. I bow before your obvious superiority. (This is what you want, right? Can't see any other possible motivation for your followup).

(shakes head sadly)

Lőrinczy Zsigmond

unread,
Jun 10, 2015, 6:06:09 AM6/10/15
to
No reason to be sad;)

Just try not to provoke the compiler with dubious code,
if you don't want error messages.

Nonetheless, if you want to stress-test your compiler,
it is perfectly okay.

gwowen

unread,
Jun 10, 2015, 7:05:02 AM6/10/15
to
On Wednesday, June 10, 2015 at 11:06:09 AM UTC+1, Lőrinczy Zsigmond wrote:
> No reason to be sad;)
>
> Just try not to provoke the compiler with dubious code,
> if you don't want error messages.

I didn't do this intentionally.
In fact, no single person did it at all, which is how it happened.

Öö Tiib

unread,
Jun 10, 2015, 8:17:46 AM6/10/15
to
Actually it is because that 'class' and 'struct' class-keys are usable
interchangeably. I do not see any benefit from it so it is not clear
why it was made that way.

> clang exhibits the annoying behaviour of emitting a bogus warning if
> you provide a hash specialization using a different keyword from the
> one which happens to be used by the C++ standard library in question
> for std::hash<T>, which means that if you use clang with a recent
> version of libstdc++ you get the warning when using the 'struct' keyword
> instead of the 'class' keyword for a specialization. I am glad to say
> that gcc does not do this.

It seems 'std::hash' is a 'struct' in libstdc++ so consistent would be to
specialize it also as 'struct' (not 'class')?

Still it is merely about a warning or lack of one. What is strange
is the OP's linking error. What can be a reason to make even the
ABI different for 'struct' and 'class' (or for respective pointers)?

Chris Vine

unread,
Jun 10, 2015, 9:58:57 AM6/10/15
to
On Wed, 10 Jun 2015 05:17:32 -0700 (PDT)
Öö Tiib <oot...@hot.ee> wrote:
> On Tuesday, 9 June 2015 22:52:38 UTC+3, Chris Vine wrote:
[snip]
> > I have come across this outside VS when specializing std::hash for a
> > type which might be used as the key for an unordered container. The
> > standard does not specify whether the std::hash<T> class template
> > type is defined using the 'class' or 'struct' keyword. §20.8.12 of
> > the C++11 standard uses the 'struct' keyword when specifying the
> > specializations required by the standard, but only requires that
> > any given specialization must comprise a 'class template'.
>
> Actually it is because that 'class' and 'struct' class-keys are usable
> interchangeably. I do not see any benefit from it so it is not clear
> why it was made that way.

Indeed. The standard only requires a class template for std::hash,
which can be declared with either keyword. The only difference between
the keywords (as far as I am aware) is the default access to members and
default inheritance.

> > clang exhibits the annoying behaviour of emitting a bogus warning if
> > you provide a hash specialization using a different keyword from the
> > one which happens to be used by the C++ standard library in question
> > for std::hash<T>, which means that if you use clang with a recent
> > version of libstdc++ you get the warning when using the 'struct'
> > keyword instead of the 'class' keyword for a specialization. I am
> > glad to say that gcc does not do this.
>
> It seems 'std::hash' is a 'struct' in libstdc++ so consistent would
> be to specialize it also as 'struct' (not 'class')?

With the version of libstdc++ that comes with my current version of gcc
(5.1.0), that indeed seems to be right. Maybe I am misremembering and
the user code provoking this warning used the class keyword rather than
the struct keyword when specializing std::hash, but I notice that there
is some inconsistency within libstdc++ headers - some classes declare
std::hash as a friend using the class keyword. Maybe that was what was
triggering the warning when using clang. Anyway, I cannot reproduce it
now if the struct keyword is used.

> Still it is merely about a warning or lack of one. What is strange
> is the OP's linking error. What can be a reason to make even the
> ABI different for 'struct' and 'class' (or for respective pointers)?

Yes, clang still compiles code with mismatching keywords on
specialization so it is not from that point view a bug, but it is
annoying to have bogus warnings: I prefer warnings which are actually
worth warning about (and this particular one can be switched off with
-Wno-mismatched-tags compiler flag). On the other hand, the failure to
link correctly where there are mismatching keywords appears to be a
real bug on VS's part.

Chris

Louis Krupp

unread,
Jun 10, 2015, 11:22:47 AM6/10/15
to
Did you mean "emitted"?

Louis
0 new messages