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
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 932bd07..a77a28c 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -3405,7 +3405,22 @@
Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
/*IsVirtual=*/false,
AddressPoints);
- GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
+ 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 @@
return;
}
- // Emit the data.
- GenerateClassData(CGM.getVtableLinkage(RD), RD);
+ if (Vtables.count(RD))
+ return;
- 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));
- }
- }
- }
+ TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
+ if (kind == TSK_ImplicitInstantiation)
+ CGM.DeferredVtables.push_back(RD);
+ else
+ GenerateClassData(CGM.getVtableLinkage(RD), RD);
}
-
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index 6ccb011..57220d9 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -173,15 +173,7 @@
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
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 @@
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
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index d6a56da..c67948d 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -488,7 +488,15 @@
// 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();
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index c86f8b4..40dc563 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -451,7 +451,9 @@
/// GetTargetTypeStoreSize - Return the store size, in character units, of
/// 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.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a89f355..79cab15 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5902,10 +5902,13 @@
// 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);
}
diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp
index b6e85e2..7de9dd2 100644
--- a/test/CodeGenCXX/virtual-base-destructor-call.cpp
+++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp
@@ -22,6 +22,11 @@
// 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 @@
// 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
diff --git a/test/SemaTemplate/virtual-member-functions.cpp b/test/SemaTemplate/virtual-member-functions.cpp
index 58ac08c..8df808d 100644
--- a/test/SemaTemplate/virtual-member-functions.cpp
+++ b/test/SemaTemplate/virtual-member-functions.cpp
@@ -14,7 +14,7 @@
}
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 @@
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;