Hi! As ubsan_expand_vptr_ifn points *gsip to the first stmt in the next bb, we want to always return true as no_next, we never want to gsi_next on it before processing it further, otherwise we could skip some important statement (e.g. another UBSAN_* call).
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2015-02-10 Jakub Jelinek <ja...@redhat.com> PR sanitizer/65004 * ubsan.c (ubsan_expand_vptr_ifn): Always return true. * g++.dg/asan/pr65004.C: New test. --- gcc/ubsan.c.jj 2015-01-28 08:39:53.000000000 +0100 +++ gcc/ubsan.c 2015-02-10 18:44:59.796872508 +0100 @@ -1148,7 +1148,7 @@ ubsan_expand_vptr_ifn (gimple_stmt_itera /* Get rid of the UBSAN_VPTR call from the IR. */ unlink_stmt_vdef (stmt); gsi_remove (&gsi, true); - return gsi_end_p (*gsip); + return true; } /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says --- gcc/testsuite/g++.dg/asan/pr65004.C.jj 2015-02-10 18:49:48.521988574 +0100 +++ gcc/testsuite/g++.dg/asan/pr65004.C 2015-02-10 18:51:22.249407985 +0100 @@ -0,0 +1,48 @@ +// PR sanitizer/65004 +// { dg-do compile } +// { dg-options "-fcompare-debug -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all" } + +namespace N { + template <typename Signature> struct function; + namespace detail { + namespace function { + struct vtable_base { }; + } + } + struct function_base { + detail::function::vtable_base * vtable; + }; + template <typename R, typename T0> struct function1 : public function_base { }; + template <typename R, typename T0> struct function <R (T0)> : public function1 <R, T0> { }; +} +namespace Bar { + typedef N::function <void (const char *)> WarningHandler; +} +namespace Foo { + struct FooRecord { + virtual ~FooRecord (); + }; + struct TestRecord : public FooRecord { + long x; + }; +} +namespace Foo { + using Bar::WarningHandler; + struct FooScanner { + WarningHandler warnHandler; + int readByte (); + long readSignedInteger (); + }; + struct FooRecordReader { + FooScanner & scanner; + long readSInt (); + void readTestRecord (TestRecord * recp); + }; + inline long FooRecordReader::readSInt () { + return scanner.readSignedInteger (); + } + void FooRecordReader::readTestRecord (TestRecord * recp) { + int infoByte = scanner.readByte (); + recp->x = readSInt (); + } +} Jakub