зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
9a2a69f608
Коммит
bbf58bb1b8
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче