I'm working on making the Clang tests tolerate a default dialect of
C++11 (currently it is C++98). I ran into a funny situation with
test/CodeGenCXX/vtable-layout.cpp, which uses -fdump-vtable-layouts to
look at, well, vtable layouts.
Consider this section of the test:
//////////
namespace Test40 {
struct A {
virtual void foo() = 0;
};
struct B : public A {
virtual void foo();
};
struct C: public B {
virtual int f(int);
virtual int f();
virtual int g(int);
virtual int g();
virtual int h(int);
virtual int h();
virtual int i(int);
virtual int i();
};
class D : C {};
D d;
}
//////////
There is a significant difference in what gets dumped, depending on
the dialect. First let's look at what we get with C++98:
$ clang -cc1 t.cpp -triple=x86_64-apple-darwin10 -emit-llvm-only \
-fdump-vtable-layouts -std=c++98 | grep entries
Vtable for 'Test40::D' (11 entries).
Vtable for 'Test40::C' (11 entries).
VTable indices for 'Test40::C' (8 entries).
Vtable for 'Test40::B' (3 entries).
VTable indices for 'Test40::B' (1 entries).
Vtable for 'Test40::A' (3 entries).
VTable indices for 'Test40::A' (1 entries).
That is, a Vtable for each class, and indices for everything except the
most-derived class.
That is, all of the base-class information is not present.
Is this a "correct" difference between C++98 and C++11?
If so, then I can just skip this test for the C++11 case.
But it seemed like a pretty weird thing to be different.
From: cfe-dev [mailto:cfe-dev-bounces@lists.llvm.org] On Behalf Of
Robinson, Paul via cfe-dev
Sent: Monday, December 19, 2016 4:13 PM
To: cfe-dev@lists.llvm.org
Subject: [cfe-dev] VTables in C++98 versus C++11
I'm working on making the Clang tests tolerate a default dialect of
C++11 (currently it is C++98). I ran into a funny situation with
test/CodeGenCXX/vtable-layout.cpp, which uses -fdump-vtable-layouts to
look at, well, vtable layouts.
Consider this section of the test:
//////////
namespace Test40 {
struct A {
virtual void foo() = 0;
};
struct B : public A {
virtual void foo();
};
struct C: public B {
virtual int f(int);
virtual int f();
virtual int g(int);
virtual int g();
virtual int h(int);
virtual int h();
virtual int i(int);
virtual int i();
};
class D : C {};
D d;
}
//////////
There is a significant difference in what gets dumped, depending on
the dialect. First let's look at what we get with C++98:
$ clang -cc1 t.cpp -triple=x86_64-apple-darwin10 -emit-llvm-only \
-fdump-vtable-layouts -std=c++98 | grep entries
Vtable for 'Test40::D' (11 entries).
Vtable for 'Test40::C' (11 entries).
VTable indices for 'Test40::C' (8 entries).
Vtable for 'Test40::B' (3 entries).
VTable indices for 'Test40::B' (1 entries).
Vtable for 'Test40::A' (3 entries).
VTable indices for 'Test40::A' (1 entries).
That is, a Vtable for each class, and indices for everything except the
most-derived class.
That is, all of the base-class information is not present.
Is this a "correct" difference between C++98 and C++11?
If so, then I can just skip this test for the C++11 case.
But it seemed like a pretty weird thing to be different.
If I define one of C's virtual functions, then we emit the
vtable as expected for C++11 too. I guess I'll go with that.
I think the difference here is that D’s implicit default constructor becomes constexpr by default in C++11, so there’s no dynamic initialization.
In C++98, we would have a dynamic initializer that calls D::D(), which would call C::C(), and so on, referencing all vtables as we go. In C++11, we can statically initialize ‘d’ without calling C::C(), and without referencing C’s vtable at all.