c++: #pragma doesn't disable -Wunused-label [PR113582]

The PR complains that

  void do_something(){
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-label"
    start:;
    #pragma GCC diagnostic pop
  } #1

doesn't work.  That's because we warn_for_unused_label only while we're
in finish_function, meaning we're at #1 where we're outside the #pragma
region.  We can use suppress_warning + warning_suppressed_p to fix this.

Note that I'm not using TREE_USED.  Propagating it in tsubst_stmt/LABEL_EXPR
from decl to label would mean that we don't warn in do_something2, but
I think we want the warning there: we're in a template and the goto is
a discarded statement.

	PR c++/113582

gcc/c-family/ChangeLog:

	* c-warn.cc (warn_for_unused_label): Don't warn if -Wunused-label has
	been suppressed for the label.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_label_for_labeled_statement): suppress_warning
	if it's not enabled at input_location.
	* pt.cc (tsubst_stmt): Call copy_warning.

gcc/testsuite/ChangeLog:

	* g++.dg/warn/Wunused-label-4.C: New test.
This commit is contained in:
Marek Polacek 2024-01-24 18:06:48 -05:00
parent 5726de79e2
commit d9318caed3
4 changed files with 42 additions and 6 deletions

View File

@ -2185,7 +2185,9 @@ warn_for_unused_label (tree label)
{
if (!TREE_USED (label))
{
if (DECL_INITIAL (label))
if (warning_suppressed_p (label, OPT_Wunused_label))
/* Don't warn. */;
else if (DECL_INITIAL (label))
warning (OPT_Wunused_label, "label %q+D defined but not used", label);
else
warning (OPT_Wunused_label, "label %q+D declared but not defined", label);

View File

@ -13108,7 +13108,11 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
/* Anything else must be an ordinary label. */
label = finish_label_stmt (cp_parser_identifier (parser));
if (label && TREE_CODE (label) == LABEL_DECL)
FALLTHROUGH_LABEL_P (label) = fallthrough_p;
{
FALLTHROUGH_LABEL_P (label) = fallthrough_p;
if (!warning_enabled_at (input_location, OPT_Wunused_label))
suppress_warning (label, OPT_Wunused_label);
}
break;
}

View File

@ -18837,11 +18837,12 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case LABEL_EXPR:
{
tree decl = LABEL_EXPR_LABEL (t);
tree label;
label = finish_label_stmt (DECL_NAME (decl));
tree label = finish_label_stmt (DECL_NAME (decl));
if (TREE_CODE (label) == LABEL_DECL)
FALLTHROUGH_LABEL_P (label) = FALLTHROUGH_LABEL_P (decl);
{
FALLTHROUGH_LABEL_P (label) = FALLTHROUGH_LABEL_P (decl);
copy_warning (label, decl);
}
if (DECL_ATTRIBUTES (decl) != NULL_TREE)
cplus_decl_attributes (&label, DECL_ATTRIBUTES (decl), 0);
}

View File

@ -0,0 +1,29 @@
// PR c++/113582
// { dg-do compile { target c++17 } }
// { dg-options "-Wunused-label" }
template<bool B> void
do_something ()
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-label"
start:
if constexpr(B)
goto start;
#pragma GCC diagnostic pop
}
template<bool B> void
do_something2 ()
{
start: // { dg-warning "defined but not used" }
if constexpr(B)
goto start;
}
void
g ()
{
do_something<0>();
do_something2<0>();
}