This test took forever to compile with -fsanitize=null, because the
instrumentation was creating incredible amount of duplicated expressions, in a
quadratic fashion.  I think the problem is that we instrument &TARGET_EXPR <>
expressions, which doesn't seem to be needed -- we only need to instrument the
initializers in TARGET_EXPRs.  With this patch, we avoid creating tons of 
useless
expressions and the compile time is reduced from ~ infinity to <1s.

Jakub, do you see any problem with this?

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2016-04-27  Marek Polacek  <pola...@redhat.com>

        PR sanitizer/70342
        * c-ubsan.c (ubsan_maybe_instrument_reference_or_call): Don't
        null-instrument &TARGET_EXPR <...>.

        * g++.dg/ubsan/null-7.C: New test.

diff --git gcc/c-family/c-ubsan.c gcc/c-family/c-ubsan.c
index 4022bdf..b829c04 100644
--- gcc/c-family/c-ubsan.c
+++ gcc/c-family/c-ubsan.c
@@ -395,8 +395,11 @@ ubsan_maybe_instrument_reference_or_call (location_t loc, 
tree op, tree ptype,
          int save_flag_delete_null_pointer_checks
            = flag_delete_null_pointer_checks;
          flag_delete_null_pointer_checks = 1;
-         if (!tree_single_nonzero_warnv_p (op, &strict_overflow_p)
-             || strict_overflow_p)
+         if ((!tree_single_nonzero_warnv_p (op, &strict_overflow_p)
+              || strict_overflow_p)
+             /* Instrumenting &TARGET_EXPR <...> is a waste and can result
+                in compile-time hog; see PR70342.  */
+             && TREE_CODE (TREE_OPERAND (op, 0)) != TARGET_EXPR)
            instrument = true;
          flag_delete_null_pointer_checks
            = save_flag_delete_null_pointer_checks;
diff --git gcc/testsuite/g++.dg/ubsan/null-7.C 
gcc/testsuite/g++.dg/ubsan/null-7.C
index e69de29..8284bc7 100644
--- gcc/testsuite/g++.dg/ubsan/null-7.C
+++ gcc/testsuite/g++.dg/ubsan/null-7.C
@@ -0,0 +1,24 @@
+// PR sanitizer/70342
+// { dg-do compile }
+// { dg-options "-fsanitize=null" }
+
+class A {};
+class B {
+public:
+  B(A);
+};
+class C {
+public:
+  C operator<<(B);
+};
+class D {
+  D(const int &);
+  C m_blackList;
+};
+D::D(const int &) {
+  m_blackList << A() << A() << A() << A() << A() << A() << A() << A() << A()
+              << A() << A() << A() << A() << A() << A() << A() << A() << A()
+              << A() << A() << A() << A() << A() << A() << A() << A() << A()
+              << A() << A() << A() << A() << A() << A() << A() << A() << A()
+              << A() << A() << A() << A() << A() << A() << A() << A() << A();
+}

        Marek

Reply via email to