Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

cp_ubsan_instrument_vptr tried to open-code vfield access and failed to
look into the base subobject to find it.  We have a function for that.

        PR c++/125745

gcc/cp/ChangeLog:

        * cp-ubsan.cc (cp_ubsan_instrument_vptr): Use build_vfield_ref.

gcc/testsuite/ChangeLog:

        * g++.dg/ubsan/vptr-19.C: New test.
---
 gcc/cp/cp-ubsan.cc                   | 5 +----
 gcc/testsuite/g++.dg/ubsan/vptr-19.C | 8 ++++++++
 2 files changed, 9 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ubsan/vptr-19.C

diff --git a/gcc/cp/cp-ubsan.cc b/gcc/cp/cp-ubsan.cc
index 9fc5744ea40..68689c8e36f 100644
--- a/gcc/cp/cp-ubsan.cc
+++ b/gcc/cp/cp-ubsan.cc
@@ -69,10 +69,7 @@ cp_ubsan_instrument_vptr (location_t loc, tree op, tree 
type, bool is_addr,
   if (!is_addr)
     op = build_fold_addr_expr_loc (loc, op);
   op = save_expr (op);
-  tree vptr = fold_build3_loc (loc, COMPONENT_REF,
-                              TREE_TYPE (TYPE_VFIELD (type)),
-                              build_fold_indirect_ref_loc (loc, op),
-                              TYPE_VFIELD (type), NULL_TREE);
+  tree vptr = build_vfield_ref (build_fold_indirect_ref_loc (loc, op), type);
   vptr = fold_convert_loc (loc, pointer_sized_int_node, vptr);
   vptr = fold_convert_loc (loc, uint64_type_node, vptr);
   if (ckind == UBSAN_DOWNCAST_POINTER)
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-19.C 
b/gcc/testsuite/g++.dg/ubsan/vptr-19.C
new file mode 100644
index 00000000000..25ad7ff5177
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/vptr-19.C
@@ -0,0 +1,8 @@
+// PR c++/125745
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fsanitize=undefined }
+
+struct A { virtual void foo (); };
+struct B : A { constexpr int foo () const { return 42; } };
+constexpr B x;
+struct C { int i; C () : i (x.foo ()) {} };

base-commit: 26bb981f58efbeccf52d9e8a0b33a6ae1b5c67e4
-- 
2.54.0

Reply via email to