https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70147
--- Comment #15 from Bernd Edlinger <bernd.edlinger at hotmail dot de> --- Yep, maybe this would be a compromise: Index: cp-ubsan.c =================================================================== --- cp-ubsan.c (revision 234184) +++ cp-ubsan.c (working copy) @@ -285,6 +285,15 @@ cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, voi if (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo)) { + tree if_stmt = NULL_TREE; + + if (BINFO_VIRTUAL_P (binfo)) + { + tree flag = DECL_CHAIN (DECL_ARGUMENTS (current_function_decl)); + if_stmt = begin_if_stmt (); + finish_if_stmt_cond (flag, if_stmt); + } + tree base_ptr = TREE_VALUE ((tree) data); base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1, @@ -301,6 +310,11 @@ cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, voi tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr)); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); + if (if_stmt != NULL_TREE) + { + finish_then_clause (if_stmt); + finish_if_stmt (if_stmt); + } } return NULL_TREE; It does not catch the calls to i() but, it slightly improves this test case and avoids the eh-problem from the previous example: cat test1.cc struct A { A () {} A (int x) : a (x) {} virtual int i () { return 0; } int a; }; __attribute__((noinline,noclone)) int foo (A* x) { return x->i(); } struct B : virtual A { B () {} B (int x) : A (foo (this)) {} }; struct C : virtual B { C () : A (foo (this)), B (foo (this)) {} }; int main () { C cc; } this invalid example does not crash as it would with my other patch, which never erases the virtual vptr. g++ -fsanitize=undefined -fno-sanitize-recover=undefined test1.cc ./a.out test1.cc:2:64: runtime error: load of null pointer of type '<unknown> *' note the message is about null pointer not undefined vptr, but at least it is not a segfault.