On Fri, Nov 04, 2016 at 05:05:51PM +0100, Marek Polacek wrote: > This is a similar case to PR sanitizer/70342. Here, we were generating > expression > in a quadratic fashion because of the initializer--we create SAVE_EXPR <>, > then > UBSAN_NULL <SAVE_EXPR <>>, and then COMPOUND_EXPR of these two and so on. > > On this testcase we were instrumention CALL_EXPR that is in fact operator<<. > I > think those always return a reference, so it cannot be NULL, so there's no > point in instrumenting those?
How do you know what is the return type of a user defined overloaded operator? Even when it returns a reference, I thought the point of -fsanitize=null was for all references to verify their addresses are non-null. I must say I don't understand the issue, if it is the same SAVE_EXPR in both lhs of COMPOUND_EXPR and UBSAN_NULL argument, shouldn't cp_genericize_r use of hash table to avoid walking the same tree multiple times avoid the exponential compile time/memory? > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2016-11-04 Marek Polacek <pola...@redhat.com> > > PR sanitizer/78208 > * cp-gimplify.c (cp_genericize_r): Don't instrument > CALL_EXPR_OPERATOR_SYNTAX. > > * g++.dg/ubsan/null-8.C: New. > > diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c > index 9b9b511..f39e9d5 100644 > --- gcc/cp/cp-gimplify.c > +++ gcc/cp/cp-gimplify.c > @@ -1495,7 +1495,8 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void > *data) > = TREE_CODE (fn) == ADDR_EXPR > && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL > && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)); > - if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT)) > + if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT) > + && !CALL_EXPR_OPERATOR_SYNTAX (stmt)) > ubsan_maybe_instrument_member_call (stmt, is_ctor); > if ((flag_sanitize & SANITIZE_VPTR) && !is_ctor) > cp_ubsan_maybe_instrument_member_call (stmt); Jakub