Delay codegen of vtables when handling implicit instantiations.

This fixes PR6474.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98123 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2010-03-10 02:19:29 +00:00
Родитель 9a2a69f608
Коммит bbf58bb1b8
7 изменённых файлов: 58 добавлений и 37 удалений

Просмотреть файл

@ -3406,6 +3406,21 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
/*IsVirtual=*/false,
AddressPoints);
GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
e = RD->method_end(); i != e; ++i) {
if (!(*i)->isVirtual())
continue;
if(!(*i)->hasInlineBody() && !(*i)->isImplicit())
continue;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
} else {
CGM.BuildThunksForVirtual(GlobalDecl(*i));
}
}
}
llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
@ -3438,19 +3453,12 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
return;
}
// Emit the data.
if (Vtables.count(RD))
return;
TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
if (kind == TSK_ImplicitInstantiation)
CGM.DeferredVtables.push_back(RD);
else
GenerateClassData(CGM.getVtableLinkage(RD), RD);
for (CXXRecordDecl::method_iterator i = RD->method_begin(),
e = RD->method_end(); i != e; ++i) {
if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
} else {
CGM.BuildThunksForVirtual(GlobalDecl(*i));
}
}
}
}

Просмотреть файл

@ -174,14 +174,6 @@ private:
void ComputeMethodVtableIndices(const CXXRecordDecl *RD);
/// GenerateClassData - Generate all the class data requires to be generated
/// upon definition of a KeyFunction. This includes the vtable, the
/// rtti data structure and the VTT.
///
/// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
const CXXRecordDecl *RD);
llvm::GlobalVariable *
GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
bool GenerateDefinition, const CXXRecordDecl *LayoutClass,
@ -245,6 +237,14 @@ public:
llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD);
void MaybeEmitVtable(GlobalDecl GD);
/// GenerateClassData - Generate all the class data requires to be generated
/// upon definition of a KeyFunction. This includes the vtable, the
/// rtti data structure and the VTT.
///
/// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
const CXXRecordDecl *RD);
};
} // end namespace CodeGen

Просмотреть файл

@ -488,7 +488,15 @@ void CodeGenModule::EmitDeferred() {
// Emit code for any potentially referenced deferred decls. Since a
// previously unused static decl may become used during the generation of code
// for a static function, iterate until no changes are made.
while (!DeferredDeclsToEmit.empty()) {
while (!DeferredDeclsToEmit.empty() || !DeferredVtables.empty()) {
if (!DeferredVtables.empty()) {
const CXXRecordDecl *RD = DeferredVtables.back();
DeferredVtables.pop_back();
getVtableInfo().GenerateClassData(getVtableLinkage(RD), RD);
continue;
}
GlobalDecl D = DeferredDeclsToEmit.back();
DeferredDeclsToEmit.pop_back();

Просмотреть файл

@ -452,6 +452,8 @@ public:
/// the given LLVM type.
CharUnits GetTargetTypeStoreSize(const llvm::Type *Ty) const;
std::vector<const CXXRecordDecl*> DeferredVtables;
private:
/// UniqueMangledName - Unique a name by (if necessary) inserting it into the
/// MangledNames string map.

Просмотреть файл

@ -5902,10 +5902,13 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
// We will need to mark all of the virtual members as referenced to build the
// vtable.
// We actually call MarkVirtualMembersReferenced instead of adding to
// ClassesWithUnmarkedVirtualMembers because this marking is needed by
// codegen that will happend before we finish parsing the file.
if (needsVtable(MD, Context))
if (!needsVtable(MD, Context))
return;
TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
if (kind == TSK_ImplicitInstantiation)
ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
else
MarkVirtualMembersReferenced(Loc, RD);
}

Просмотреть файл

@ -22,6 +22,11 @@ int main() {
// CHECK: call void @_ZN14basic_iostreamIcED2Ev
// CHECK: call void @_ZN9basic_iosD2Ev
// basic_iostream's base dtor calls its non-virtual base dtor.
// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev
// CHECK: call void @_ZN13basic_istreamIcED2Ev
// CHECK: }
// basic_iostream's deleting dtor calls its complete dtor, then
// operator delete().
// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev
@ -40,11 +45,6 @@ int main() {
// CHECK: call void @_ZN13basic_istreamIcED1Ev
// CHECK: call void @_ZdlPv
// basic_iostream's base dtor calls its non-virtual base dtor.
// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev
// CHECK: call void @_ZN13basic_istreamIcED2Ev
// CHECK: }
// basic_istream's base dtor is a no-op.
// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev
// CHECK-NOT: call

Просмотреть файл

@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) {
}
void f(A<int> x) {
x.anchor(); // expected-note{{in instantiation of member function 'PR5557::A<int>::anchor' requested here}}
x.anchor();
}
template<typename T>
@ -52,4 +52,4 @@ T *HasOutOfLineKey<T>::f(float *fp) {
return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}}
}
HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}}
HasOutOfLineKey<int> out_of_line;