Don't emit an available_externally vtable pointing to linkonce_odr funcs.
This fixes pr13124. From the discussion at http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-June/022606.html we know that we cannot make funcions in a weak_odr vtable also weak_odr. They should remain linkonce_odr. The side effect is that we cannot emit a available_externally vtable unless we also emit a copy of the function. This also has an issue: If codegen is going to output a function, sema has to mark it used. Given llvm.org/pr9114, it looks like sema cannot be more aggressive at marking functions used because of vtables. This leaves us with a few unpleasant options: * Marking functions in vtables used if possible. This sounds a bit sloppy, so we should avoid it. * Producing available_externally vtables only when all the functions in it are already used or weak_odr. This would cover cases like -------------------- struct foo { virtual ~foo(); }; struct bar : public foo { virtual void zed(); }; void f() { foo *x(new bar); delete x; } void g(bar *x) { x->~bar(); // force the destructor to be used } -------------------------- and ---------------------------------- template<typename T> struct bar { virtual ~bar(); }; template<typename T> bar<T>::~bar() { } // make the destructor weak_odr instead of linkonce_odr extern template class bar<int>; void f() { bar<int> *x(new bar<int>); delete x; } ---------------------------- These look like corner cases, so it is unclear if it is worth it. * And finally: Just nuke this optimization. That is what this patch implements. llvm-svn: 189852
This commit is contained in:
@@ -753,12 +753,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
|
||||
switch (keyFunction->getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
// When compiling with optimizations turned on, we emit all vtables,
|
||||
// even if the key function is not defined in the current translation
|
||||
// unit. If this is the case, use available_externally linkage.
|
||||
if (!def && CodeGenOpts.OptimizationLevel)
|
||||
return llvm::GlobalVariable::AvailableExternallyLinkage;
|
||||
|
||||
assert(def && "Should not have been asked to emit this");
|
||||
if (keyFunction->isInlined())
|
||||
return !Context.getLangOpts().AppleKext ?
|
||||
llvm::GlobalVariable::LinkOnceODRLinkage :
|
||||
@@ -777,9 +772,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
|
||||
llvm::Function::InternalLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
return !Context.getLangOpts().AppleKext ?
|
||||
llvm::GlobalVariable::AvailableExternallyLinkage :
|
||||
llvm::Function::InternalLinkage;
|
||||
llvm_unreachable("Should not have been asked to emit this");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,7 +788,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
|
||||
return llvm::GlobalVariable::LinkOnceODRLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
return llvm::GlobalVariable::AvailableExternallyLinkage;
|
||||
llvm_unreachable("Should not have been asked to emit this");
|
||||
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return llvm::GlobalVariable::WeakODRLinkage;
|
||||
@@ -897,16 +890,6 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
|
||||
/// we define that v-table?
|
||||
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM,
|
||||
const CXXRecordDecl *RD) {
|
||||
// If we're building with optimization, we always emit v-tables
|
||||
// since that allows for virtual function calls to be devirtualized.
|
||||
// If the v-table is defined strongly elsewhere, this definition
|
||||
// will be emitted available_externally.
|
||||
//
|
||||
// However, we don't want to do this in -fapple-kext mode, because
|
||||
// kext mode does not permit devirtualization.
|
||||
if (CGM.getCodeGenOpts().OptimizationLevel && !CGM.getLangOpts().AppleKext)
|
||||
return true;
|
||||
|
||||
return !CGM.getVTables().isVTableExternal(RD);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user