}
void
-pass_waccess::set_pass_param (unsigned int n, bool early)
+pass_waccess::set_pass_param (unsigned int n, bool param)
{
- gcc_assert (n == 0);
-
- m_early_checks_p = early;
+ /* Check for dangling pointers in the earliest runs of the pass.
+ The latest point -Wdangling-pointer should run is just before
+ loop unrolling which introduces uses after clobbers. Most cases
+ can be detected without optimization; cases where the address of
+ the local variable is passed to and then returned from a user-
+ defined function before its lifetime ends and the returned pointer
+ becomes dangling depend on inlining. */
+ if (n == 0)
+ m_early_checks_p = param;
+ else if (n == 1)
+ m_check_dangling_p = param;
+ else
+ __builtin_unreachable ();
}
/* Return true when any checks performed by the pass are enabled. */
&& gimple_call_internal_fn (stmt) == IFN_ASAN_MARK)
return;
+ if (m_check_dangling_p)
+ {
+ check_call_dangling (stmt);
+
+ /* Don't do any other checks when doing dangling pointer checks the
+ second time. */
+ if (!m_early_checks_p)
+ return;
+ }
+
if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
check_builtin (stmt);
}
check_call_access (stmt);
- check_call_dangling (stmt);
if (m_early_checks_p)
return;
m_ptr_qry.rvals = enable_ranger (fun);
m_func = fun;
- /* Check for dangling pointers in the earliest run of the pass.
- The latest point -Wdangling-pointer should run is just before
- loop unrolling which introduces uses after clobbers. Most cases
- can be detected without optimization; cases where the address of
- the local variable is passed to and then returned from a user-
- defined function before its lifetime ends and the returned pointer
- becomes dangling depend on inlining. */
- m_check_dangling_p = m_early_checks_p;
-
auto_bitmap bb_uids_set (&bitmap_default_obstack);
m_bb_uids_set = bb_uids_set;
NEXT_PASS (pass_warn_printf);
NEXT_PASS (pass_warn_nonnull_compare);
NEXT_PASS (pass_early_warn_uninitialized);
- NEXT_PASS (pass_warn_access, /*early=*/true);
+ NEXT_PASS (pass_warn_access, /*early=*/true, /*check_dangling=*/true);
NEXT_PASS (pass_ubsan);
NEXT_PASS (pass_nothrow);
NEXT_PASS (pass_rebuild_cgraph_edges);
NEXT_PASS (pass_object_sizes);
NEXT_PASS (pass_post_ipa_warn);
/* Must run before loop unrolling. */
- NEXT_PASS (pass_warn_access, /*early=*/true);
+ NEXT_PASS (pass_warn_access, /*early=*/false, /*check_dangling=*/true);
/* Profile count may overflow as a result of inlinining very large
loop nests. This pass should run before any late pass that makes
use of profile. */
NEXT_PASS (pass_gimple_isel);
NEXT_PASS (pass_harden_conditional_branches);
NEXT_PASS (pass_harden_compares);
- NEXT_PASS (pass_warn_access, /*early=*/false);
+ NEXT_PASS (pass_warn_access, /*early=*/false, /*check_dangling=*/false);
NEXT_PASS (pass_cleanup_cfg_post_optimizing);
NEXT_PASS (pass_warn_function_noreturn);
--- /dev/null
+// { dg-do compile }
+// { dg-additional-options "-O2 -Wstringop-overflow" }
+
+long ext_f (void *, unsigned long)
+ __attribute__ ((__access__ (__write_only__, 1, 2)));
+
+long f (void *b, unsigned long n)
+{
+ unsigned long sz = __builtin_dynamic_object_size(b, 0);
+
+ return (__builtin_constant_p (sz) && sz == -1UL) ? ext_f (b, n) : 0;
+}
+
+
+void test (unsigned limit, long init_off)
+{
+ char buf[4096];
+ unsigned long off = 0;
+
+ while (off == 0)
+ off += init_off;
+
+ while (off < limit)
+ {
+ long n = f (buf + off, sizeof (buf) - off);
+
+ if (n <= 0)
+ continue;
+
+ off += n;
+ }
+}