https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101839
--- Comment #8 from Xionghu Luo (luoxhu at gcc dot gnu.org) <yinyuefengyi at gmail dot com> --- The relationship is: A A::type | ------------ | | BA BA::type CA CA::type | CBA CBA::type class CA and CBA are final, also function CA::type and BA::type are final, then in function possible_polymorphic_call_targets for "target" BA::type, the "DECL_FINAL_P (target)" check is not accurate enough, as there may be classes like CBA derived from BA and have instance that need continue walk recursively in possible_polymorphic_call_targets_1 to record_target_from_binfo. if (target) { /* In the case we get complete method, we don't need to walk derivations. */ if (DECL_FINAL_P (target)) context.maybe_derived_type = false; } So fix this by belong change only stop walk derivations when target is final and it's class outer_type->type is also final? diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc index 412ca14f66b..77f9b268e86 100644 --- a/gcc/ipa-devirt.cc +++ b/gcc/ipa-devirt.cc @@ -3188,7 +3188,9 @@ possible_polymorphic_call_targets (tree otr_type, /* In the case we get complete method, we don't need to walk derivations. */ - if (target && DECL_FINAL_P (target)) + if (target && TREE_CODE (target) == FUNCTION_DECL && DECL_FINAL_P (target) + && RECORD_OR_UNION_TYPE_P (out er_type->type) + && TYPE_FINAL_P (outer_type->type)) context.speculative_maybe_derived_type = false; if (type_possibly_instantiated_p (speculative_outer_type->type)) maybe_record_node (nodes, target, &inserted, can_refer, &speculation_complete); @@ -3233,7 +3235,9 @@ possible_polymorphic_call_targets (tree otr_type, { /* In the case we get complete method, we don't need to walk derivations. */ - if (DECL_FINAL_P (target)) + if (TREE_CODE (target) == FUNCTION_DECL && DECL_FINAL_P (target) + && RECORD_OR_UNION_TYPE_P (outer_type->type) + && TYPE_FINAL_P (outer_type->type)) context.maybe_derived_type = false; }