From: Eli Friedman Date: Sat, 5 Dec 2009 04:55:55 +0000 (+0000) Subject: Tweak "key function" rules so that they work for templates with virtual X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=378fe06b93752669d8a7dd8fa7000094b9679267;p=clang Tweak "key function" rules so that they work for templates with virtual inline functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90645 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 3a1e248dbc..4c7b911934 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -663,6 +663,20 @@ void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { Alignment = NewAlignment; } +static bool MethodHasBody(const CXXMethodDecl *MD, const FunctionDecl *&fn) { + // Simple case: function has a body + if (MD->getBody(fn)) + return true; + + // Complex case: function is an instantiation of a function which has a + // body, but the definition hasn't been instantiated. + const FunctionDecl *PatternDecl = MD->getTemplateInstantiationPattern(); + if (PatternDecl && PatternDecl->getBody(fn)) + return true; + + return false; +} + static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) { if (!RD->isDynamicClass()) return 0; @@ -683,7 +697,7 @@ static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) { continue; const FunctionDecl *fn; - if (MD->getBody(fn) && !fn->isOutOfLine()) + if (MethodHasBody(MD, fn) && !fn->isOutOfLine()) continue; // We found it. diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp new file mode 100644 index 0000000000..478daa75cb --- /dev/null +++ b/test/CodeGenCXX/virt-template-vtable.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s + +template class A { + A() {} + virtual void a() {} +}; +class B : A { + B(); +}; +B::B() {} + +// CHECK: @_ZTV1AIiE = linkonce_odr constant