On Fri, Oct 27, 2017 at 01:16:08PM +0200, Martin Liška wrote: > On 10/27/2017 12:52 PM, Jakub Jelinek wrote: > > The decl.c change seems to be only incremental change from a not publicly > > posted patch rather than the full diff against trunk. > > Sorry for that. Sending full patch.
Thanks. > --- a/gcc/cp/decl.c > +++ b/gcc/cp/decl.c > @@ -15280,7 +15280,19 @@ begin_destructor_body (void) > if (flag_lifetime_dse > /* Clobbering an empty base is harmful if it overlays real data. */ > && !is_empty_class (current_class_type)) > - finish_decl_cleanup (NULL_TREE, build_clobber_this ()); > + { > + if (sanitize_flags_p (SANITIZE_VPTR) > + && (flag_sanitize_recover & SANITIZE_VPTR) == 0) > + { > + tree fndecl = builtin_decl_explicit (BUILT_IN_MEMSET); > + tree call = build_call_expr (fndecl, 3, > + current_class_ptr, integer_zero_node, > + TYPE_SIZE_UNIT (current_class_type)); I wonder if it wouldn't be cheaper to just use thisref = {}; rather than memset, pretty much the same thing as build_clobber_this () emits, except for the TREE_VOLATILE. Also, build_clobber_this has: if (vbases) exprstmt = build_if_in_charge (exprstmt); so it doesn't clobber if not in charge, not sure if it applies here too. So maybe easiest would be add a bool argument to build_clobber_this which would say whether it is a clobber or real clearing? > + finish_decl_cleanup (NULL_TREE, call); > + } > + else > + finish_decl_cleanup (NULL_TREE, build_clobber_this ()); > + } > > /* And insert cleanups for our bases and members so that they > will be properly destroyed if we throw. */ > diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-12.C > b/gcc/testsuite/g++.dg/ubsan/vptr-12.C > new file mode 100644 > index 00000000000..96c8473d757 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ubsan/vptr-12.C > @@ -0,0 +1,26 @@ > +// { dg-do run } > +// { dg-shouldfail "ubsan" } > +// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" } > + > +struct MyClass > +{ > + virtual ~MyClass () {} > + virtual void > + Doit () > + { > + } Why not put all the above 4 lines into a single one, the dtor already uses that kind of formatting. > +}; > + > +int > +main () > +{ > + MyClass *c = new MyClass; > + c->~MyClass (); > + c->Doit (); > + > + return 0; > +} > + > +// { dg-output "\[^\n\r]*vptr-12.C:19:\[0-9]*: runtime error: member call on > address 0x\[0-9a-fA-F]* which does not point to an object of type > 'MyClass'(\n|\r\n|\r)" } > +// { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" } > + Unnecessary empty line at end. Jakub