parent
4569f69558
commit
f2c79b6b9c
|
@ -724,7 +724,13 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
|
|||
// function.
|
||||
if (RD->getTemplateSpecializationKind() != TSK_Undeclared)
|
||||
return 0;
|
||||
|
||||
|
||||
// A class inside an anonymous namespace doesn't have a key function. (Or
|
||||
// at least, there's no point to assigning a key function to such a class;
|
||||
// this doesn't affect the ABI.)
|
||||
if (RD->isInAnonymousNamespace())
|
||||
return 0;
|
||||
|
||||
for (CXXRecordDecl::method_iterator I = RD->method_begin(),
|
||||
E = RD->method_end(); I != E; ++I) {
|
||||
const CXXMethodDecl *MD = *I;
|
||||
|
@ -734,6 +740,9 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
|
|||
|
||||
if (MD->isPure())
|
||||
continue;
|
||||
|
||||
if (MD->isInlineSpecified())
|
||||
continue;
|
||||
|
||||
// Ignore implicit member functions, they are always marked as inline, but
|
||||
// they don't have a body until they're defined.
|
||||
|
|
|
@ -522,6 +522,16 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
|
|||
FD->hasAttr<DestructorAttr>())
|
||||
return false;
|
||||
|
||||
// The key function for a class must never be deferred.
|
||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Global)) {
|
||||
const CXXRecordDecl *RD = MD->getParent();
|
||||
if (MD->isOutOfLine() && RD->isDynamicClass()) {
|
||||
const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD);
|
||||
if (KeyFunction == MD->getCanonicalDecl())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
|
||||
|
||||
// static, static inline, always_inline, and extern inline functions can
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// Simple key function test
|
||||
struct testa { virtual void a(); };
|
||||
void testa::a() {}
|
||||
|
||||
// Simple key function test
|
||||
struct testb { virtual void a() {} };
|
||||
testb *testbvar = new testb;
|
||||
|
||||
// Key function with out-of-line inline definition
|
||||
struct testc { virtual void a(); };
|
||||
inline void testc::a() {}
|
||||
|
||||
// Key functions with inline specifier (PR5705)
|
||||
struct testd { inline virtual void a(); };
|
||||
void testd::a() {}
|
||||
|
||||
// Key functions with inline specifier (PR5705)
|
||||
struct teste { inline virtual void a(); };
|
||||
teste *testevar = new teste;
|
||||
|
||||
// Key functions with namespace (PR5711)
|
||||
namespace {
|
||||
struct testf { virtual void a(); };
|
||||
}
|
||||
void testf::a() {}
|
||||
|
||||
// Key functions with namespace (PR5711)
|
||||
namespace {
|
||||
struct testg { virtual void a(); };
|
||||
}
|
||||
testg *testgvar = new testg;
|
||||
|
||||
// FIXME: The checks are extremely difficult to get right when the globals
|
||||
// aren't alphabetized
|
||||
// CHECK: @_ZTV5testa = constant [3 x i8*] [i8* null
|
||||
// CHECK: @_ZTV5testc = constant [3 x i8*] [i8* null
|
||||
// CHECK: @_ZTVN12_GLOBAL__N_15testgE = internal constant [3 x i8*] [i8* null
|
||||
// CHECK: @_ZTV5teste = weak_odr constant [3 x i8*] [i8* null
|
||||
// CHECK: @_ZTV5testb = weak_odr constant [3 x i8*] [i8* null
|
||||
|
Loading…
Reference in New Issue