mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 13:46:07 +00:00

This fixes pr13124. From the discussion at http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-June/022606.html we know that we cannot make funcions in a weak_odr vtable also weak_odr. They should remain linkonce_odr. The side effect is that we cannot emit a available_externally vtable unless we also emit a copy of the function. This also has an issue: If codegen is going to output a function, sema has to mark it used. Given llvm.org/pr9114, it looks like sema cannot be more aggressive at marking functions used because of vtables. This leaves us with a few unpleasant options: * Marking functions in vtables used if possible. This sounds a bit sloppy, so we should avoid it. * Producing available_externally vtables only when all the functions in it are already used or weak_odr. This would cover cases like -------------------- struct foo { virtual ~foo(); }; struct bar : public foo { virtual void zed(); }; void f() { foo *x(new bar); delete x; } void g(bar *x) { x->~bar(); // force the destructor to be used } -------------------------- and ---------------------------------- template<typename T> struct bar { virtual ~bar(); }; template<typename T> bar<T>::~bar() { } // make the destructor weak_odr instead of linkonce_odr extern template class bar<int>; void f() { bar<int> *x(new bar<int>); delete x; } ---------------------------- These look like corner cases, so it is unclear if it is worth it. * And finally: Just nuke this optimization. That is what this patch implements. llvm-svn: 189852
80 lines
903 B
C++
80 lines
903 B
C++
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm-only -O3
|
|
|
|
// Check that we don't assert on this case.
|
|
namespace Test1 {
|
|
|
|
struct Incomplete;
|
|
|
|
struct A {
|
|
virtual void f();
|
|
virtual void g(Incomplete);
|
|
virtual void h();
|
|
virtual void i();
|
|
int a;
|
|
};
|
|
|
|
struct B {
|
|
virtual void f();
|
|
virtual void g(Incomplete);
|
|
virtual void h();
|
|
virtual void i();
|
|
int b;
|
|
};
|
|
|
|
struct C : A, B {
|
|
C();
|
|
|
|
virtual void f();
|
|
virtual void g(Incomplete);
|
|
virtual void h();
|
|
virtual void i();
|
|
};
|
|
|
|
void C::h() { }
|
|
|
|
C::C() { }
|
|
|
|
void C::i() { }
|
|
|
|
}
|
|
|
|
namespace Test2 {
|
|
|
|
struct A {
|
|
virtual void f();
|
|
int a;
|
|
};
|
|
|
|
struct B {
|
|
virtual void f();
|
|
int b;
|
|
};
|
|
|
|
struct C : A, B {
|
|
virtual void f();
|
|
};
|
|
|
|
static void f(B* b) {
|
|
b->f();
|
|
}
|
|
|
|
}
|
|
|
|
// Test that we don't assert.
|
|
namespace Test3 {
|
|
|
|
struct A {
|
|
virtual ~A();
|
|
|
|
int a;
|
|
};
|
|
|
|
struct B : A { };
|
|
struct C : virtual B { };
|
|
|
|
void f() {
|
|
C c;
|
|
}
|
|
|
|
}
|