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