https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104702

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #2)
> I think the problem in this case are primarily the warning-control.cc
> changes.
> In GCC 11, build_vec_init did at the end:
>   /* Now make the result have the correct type.  */
>   if (TREE_CODE (atype) == ARRAY_TYPE)
>     {
>       atype = build_pointer_type (atype);
>       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
>       stmt_expr = cp_build_fold_indirect_ref (stmt_expr);
>       TREE_NO_WARNING (stmt_expr) = 1;
>     }
> GCC 12 does instead:
>   if (TREE_CODE (atype) == ARRAY_TYPE)
>     {
>       atype = build_pointer_type (atype);
>       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
>       stmt_expr = cp_build_fold_indirect_ref (stmt_expr);
>       suppress_warning (stmt_expr /* What warning? */);
>     }
> Clearly, at least one of the intended warnings that should be suppressed is
> OPT_Wunused_value.
> But as EXPR_LOCATION (stmt_expr) == UNKNOWN_LOCATION here, all
> suppress_warning
> does is set TREE_NO_WARNING bit on it (i.e. like GCC 11 used).
> Later on, add_stmt is called on it and does:
>             if (!EXPR_HAS_LOCATION (t))
>               SET_EXPR_LOCATION (t, input_location);
> There was also even before build_vec_init a call to
> suppress_warning with some unrelated expression that had the
> 284032 {file = 0x3f67310 "pr104702.C", line = 11, column = 31, data = 0x0,
> sysp = false}
> location (with OPT_Wparentheses) which is the input_location now newly set
> by add_stmt on the INDIRECT_REF.
> Later on, convert_to_void calls
>                       && !warning_suppressed_p (expr, OPT_Wunused_value)
> on the INDIRECT_REF.  TREE_NO_WARNING bit is set, but at this point it has a
> location, so it looks up the location in hash map, finds that
> OPT_Wparantheses
> is the warning to be suppressed there and returns that OPT_Wunused_value
> isn't suppressed there, even when we wanted to suppress all warnings on the
> tree.

So shouldn't warning_suppressed_p (tree, ...) also honor TREE_NO_WARNING
even if a location is present?  That is,

diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 0cbb4f079fa..d36f3ff6965 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -120,10 +120,12 @@ get_nowarn_spec (const gimple *stmt)
 bool
 warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
 {
-  const nowarn_spec_t *spec = get_nowarn_spec (expr);
+  if (get_no_warning_bit (expr))
+    return true;

+  const nowarn_spec_t *spec = get_nowarn_spec (expr);
   if (!spec)
-    return get_no_warning_bit (expr);
+    return false;

   const nowarn_spec_t optspec (opt);
   bool dis = *spec & optspec;

or, if that's not desired, at least

  gcc_checking_assert (!get_no_warning_bit (expr));

when there's a spec?

Reply via email to