From 09039e9c723456cd008c7fa94ea772ee796cda2c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 26 Jun 2019 00:56:07 -0400 Subject: [PATCH] PR c++/70462 - unnecessary base ctor variant with final. As pointed out in the PR, we don't need base 'tor variants for a final class, since it can never be a base. I tried also dropping complete variants for abstract classes, but that runs into ABI compatibility problems with older releases that refer to those symbols. * optimize.c (populate_clone_array): Skip base variant if CLASSTYPE_FINAL. (maybe_clone_body): We don't need an alias if we are only defining one clone. From-SVN: r272669 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/optimize.c | 12 ++++++++---- gcc/testsuite/g++.dg/other/final8.C | 9 +++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/final8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dee69b87eba..9d89ccb4ab9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2019-06-25 Jason Merrill + PR c++/70462 - unnecessary base ctor variant with final. + * optimize.c (populate_clone_array): Skip base variant if + CLASSTYPE_FINAL. + (maybe_clone_body): We don't need an alias if we are only defining + one clone. + * class.c (resolves_to_fixed_type_p): Check CLASSTYPE_FINAL. 2019-06-25 Jakub Jelinek diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index aace7dea684..0774857f503 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -247,15 +247,19 @@ populate_clone_array (tree fn, tree *fns) fns[1] = NULL_TREE; fns[2] = NULL_TREE; - /* Look for the complete destructor which may be used to build the - delete destructor. */ + tree ctx = DECL_CONTEXT (fn); + FOR_EACH_CLONE (clone, fn) if (DECL_NAME (clone) == complete_dtor_identifier || DECL_NAME (clone) == complete_ctor_identifier) fns[1] = clone; else if (DECL_NAME (clone) == base_dtor_identifier || DECL_NAME (clone) == base_ctor_identifier) - fns[0] = clone; + { + /* We don't need to define the base variants for a final class. */ + if (!CLASSTYPE_FINAL (ctx)) + fns[0] = clone; + } else if (DECL_NAME (clone) == deleting_dtor_identifier) fns[2] = clone; else @@ -480,7 +484,7 @@ maybe_clone_body (tree fn) /* Remember if we can't have multiple clones for some reason. We need to check this before we remap local static initializers in clone_body. */ - if (!tree_versionable_function_p (fn)) + if (!tree_versionable_function_p (fn) && fns[0] && fns[1]) need_alias = true; /* We know that any clones immediately follow FN in the TYPE_FIELDS diff --git a/gcc/testsuite/g++.dg/other/final8.C b/gcc/testsuite/g++.dg/other/final8.C new file mode 100644 index 00000000000..f90f94e9ea0 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/final8.C @@ -0,0 +1,9 @@ +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler-not "_ZN1BC2Ev" } } +// { dg-final { scan-assembler-not "_ZN1BD2Ev" } } + +struct A { int i; A(); virtual ~A() = 0; }; +struct B final: public virtual A { int j; B(); ~B(); }; + +B::B() {} +B::~B() {} -- 2.30.2