Hi! DECL_OMP_PRIVATIZED_MEMBER vars are artificial, DECL_IGNORED_P and useful only during OpenMP lowering, their DECL_VALUE_EXPR isn't really useful afterwards (just shouldn't be cleared because then we could try to expand those vars if we don't optimize them as unused).
The sanitizer can add calls in them to UBSAN_VPTR etc. though, which LTO streaming doesn't like. The following patch just makes sure it doesn't see them. Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2018-01-23 Jakub Jelinek <ja...@redhat.com> PR sanitizer/83987 * tree.c (cp_free_lang_data): Change DECL_VALUE_EXPR of DECL_OMP_PRIVATIZED_MEMBER vars to error_mark_node. * g++.dg/ubsan/pr83987.C: New test. --- gcc/cp/tree.c.jj 2018-01-17 22:00:06.878228591 +0100 +++ gcc/cp/tree.c 2018-01-23 10:17:03.810795156 +0100 @@ -5274,6 +5274,16 @@ cp_free_lang_data (tree t) /* We do not need the leftover chaining of namespaces from the binding level. */ DECL_CHAIN (t) = NULL_TREE; + /* Set DECL_VALUE_EXPRs of OpenMP privatized member artificial + decls to error_mark_node. These are DECL_IGNORED_P and after + OpenMP lowering they aren't useful anymore. Clearing DECL_VALUE_EXPR + doesn't work, as expansion could then consider them as something + to be expanded. */ + if (VAR_P (t) + && DECL_LANG_SPECIFIC (t) + && DECL_OMP_PRIVATIZED_MEMBER (t) + && DECL_IGNORED_P (t)) + SET_DECL_VALUE_EXPR (t, error_mark_node); } /* Stub for c-common. Please keep in sync with c-decl.c. --- gcc/testsuite/g++.dg/ubsan/pr83987.C.jj 2018-01-23 10:35:37.158192734 +0100 +++ gcc/testsuite/g++.dg/ubsan/pr83987.C 2018-01-23 10:37:04.819118976 +0100 @@ -0,0 +1,15 @@ +// PR sanitizer/83987 +// { dg-do compile { target fopenmp } } +// { dg-options "-fopenmp -fsanitize=vptr -O0" } + +struct A { int i; }; +struct B : virtual A { void foo (); }; + +void +B::foo () +{ +#pragma omp sections lastprivate (i) + { + i = 0; + } +} Jakub