https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104492
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- So IL wise the issue is that we go from <bb 2> : candidates(address-taken)[0].m_size = 2; candidates(address-taken)[0].m_data = "so"; _1 = std::end<const QLatin1String, 1> (&candidates(address-taken)); _2 = std::begin<const QLatin1String, 1> (&candidates(address-taken)); _11 = std::find<const QLatin1String*, QStringView> (_2, _1, &s(address-taken)); _3 = _11; _4 = std::end<const QLatin1String, 1> (&candidates(address-taken)); _13 = _3 != _4; candidates(address-taken) ={v} {CLOBBER(eol)}; return _13; to _32 = std::__find_if<const QLatin1String*, __gnu_cxx::__ops::_Iter_equals_val<const QStringView> > (&candidates(address-taken), &MEM <const struct QLatin1String[1]> [(void *)&candidates(address-taken) + 16B], __pred, D.182436); __pred ={v} {CLOBBER(eol)}; _33 = &MEM <const struct QLatin1String[1]> [(void *)&candidates(address-taken) + 16B] != _32; candidates(address-taken) ={v} {CLOBBER(eol)}; _66 = _33; s(address-taken) ={v} {CLOBBER(eol)}; _19 = _66; retval.0_20 = _19; D.169966(address-taken) ={v} {CLOBBER(eol)}; if (retval.0_20 != 0) exposing the forwarding opportunity into the conditional: _32 = std::__find_if<const QLatin1String*, __gnu_cxx::__ops::_Iter_equals_val<const QStringView> > (&candidates(address-taken), &MEM <const struct QLatin1String[1]> [(void *)&candidates(address-taken) + 16B], __pred, D.182436); __pred ={v} {CLOBBER(eol)}; candidates(address-taken) ={v} {CLOBBER(eol)}; s(address-taken) ={v} {CLOBBER(eol)}; D.169966 ={v} {CLOBBER(eol)}; if (&MEM <const struct QLatin1String[1]> [(void *)&candidates(address-taken) + 16B] != _32) as noted CLOBBERs are not barriers for values but only for memory so any such forwarding (which would also happen for non-equality compares) interferes with the intent of -Wdangling-pointer. I'll note that a CLOBBER does _not_ invalidate the pointer to the storage but only its contents as opposed to some reading of 'realloc' or 'free' semantics imposed by the C standard. The documentation mentions two levels of -Wdangling-pointer but all examples are about either the pointer escaping the function (to the caller) or about accesses to the storage whose contents became indeterminate. Unrolling and IVOPTs/SLSR could also expose re-use of storage accessed by a pointer to the "first" instance of a variable. I'm not sure what can be done about all this for the late pass_warn_access (which runs _very_ late). It's going to be prone to such issues and maybe -Wanalyzer is a better tool for the purpose. I was not successful in auto-reducing the testcase to something that closely resembles the above IL but I guess crafting a manual testcase from it would be possible. For the specific case we now pass 'equality' to pass_waccess::warn_invalid_pointer which is true for the original testcase but is only used to prune diagnostics after free/realloc and not when using the (undocumented) -Wdangling-pointer=3 level (level 3 is also rejected because it has IntegerRange(0, 2)). This case is about iteration over an auto variable and the "found" check being forwarded across the storage invalidation. The following fixes the original (and my misreduced) testcase. I'm going to test it and post it for review. diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 879dbcc1e52..6c404f18db7 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -3896,13 +3896,13 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple *us e_stmt, return; } + if ((equality && warn_use_after_free < 3) + || (maybe && warn_use_after_free < 2) + || warning_suppressed_p (use_stmt, OPT_Wuse_after_free)) + return; + if (is_gimple_call (inval_stmt)) { - if ((equality && warn_use_after_free < 3) - || (maybe && warn_use_after_free < 2) - || warning_suppressed_p (use_stmt, OPT_Wuse_after_free)) - return; - const tree inval_decl = gimple_call_fndecl (inval_stmt); if ((ref && warning_at (use_loc, OPT_Wuse_after_free, @@ -3923,10 +3923,6 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple *use_stmt, return; } - if ((maybe && warn_dangling_pointer < 2) - || warning_suppressed_p (use_stmt, OPT_Wdangling_pointer_)) - return; - if (DECL_NAME (var)) { if ((ref