If we have a pointer to final class, we know the dynamic type of the object
must be that class, because it can't have any derived classes.

Tested x86_64-pc-linux-gnu, applying to trunk.
---
 gcc/cp/class.c                         | 6 ++++--
 gcc/testsuite/g++.dg/tree-ssa/final1.C | 8 ++++++++
 gcc/cp/ChangeLog                       | 4 ++++
 3 files changed, 16 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/tree-ssa/final1.C

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index e0df9ef2b20..a679e651bbe 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7477,10 +7477,12 @@ resolves_to_fixed_type_p (tree instance, int* nonnull)
     }
 
   fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
-  if (fixed == NULL_TREE)
-    return 0;
   if (INDIRECT_TYPE_P (t))
     t = TREE_TYPE (t);
+  if (CLASS_TYPE_P (t) && CLASSTYPE_FINAL (t))
+    return 1;
+  if (fixed == NULL_TREE)
+    return 0;
   if (!same_type_ignoring_top_level_qualifiers_p (t, fixed))
     return 0;
   return cdtorp ? -1 : 1;
diff --git a/gcc/testsuite/g++.dg/tree-ssa/final1.C 
b/gcc/testsuite/g++.dg/tree-ssa/final1.C
new file mode 100644
index 00000000000..43407f09675
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/final1.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-not "vptr" gimple } }
+
+struct A { int i; };
+struct B final: public virtual A { int j; };
+
+int f(B* b) { return b->i; }
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3459ad7718b..0ad67f6bc1b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+2019-06-25  Jason Merrill  <ja...@redhat.com>
+
+       * class.c (resolves_to_fixed_type_p): Check CLASSTYPE_FINAL.
+
 2019-06-24  Jan Hubicka  <j...@suse.cz>
 
        * lex.c (cxx_make_type): Set TYPE_CXX_ODR_P.

base-commit: 14462095a3d89c8dccb0da790e30a13b59a02a9c
-- 
2.20.1

Reply via email to