From: Andi Kleen <[email protected]>
A compound statement didn't reset the musttail state after the statement
with the attribute, which lead to bogus errors later. Always reset it.
Proposed for trunk and gcc-15 / 16.
PR c/124532
gcc/c/ChangeLog:
* c-parser.cc (struct attr_state): Add reset method.
(c_parser_compound_statement_nostart): Rename a to astate.
Reset state before iterating statements.
gcc/testsuite/ChangeLog:
* c-c++-common/pr124532.c: New test.
---
gcc/c/c-parser.cc | 13 ++++++++++---
gcc/testsuite/c-c++-common/pr124532.c | 13 +++++++++++++
2 files changed, 23 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/pr124532.c
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 07c7900c332e..0dd3e052b0e9 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1795,6 +1795,8 @@ struct attr_state
{
/* True if we parsed a musttail attribute for return. */
bool musttail_p;
+
+ void reset() { musttail_p = false; }
};
static bool c_parser_nth_token_starts_std_attributes (c_parser *,
@@ -7648,7 +7650,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
bool in_omp_loop_block
= omp_for_parse_state ? omp_for_parse_state->want_nested_loop : false;
tree sl = NULL_TREE;
- attr_state a = {};
+ attr_state astate = {};
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
@@ -7740,6 +7742,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
sl = push_stmt_list ();
parser->error = false;
before_labels = get_before_labels ();
+ astate.reset ();
continue;
}
else if (want_nested_loop
@@ -7773,6 +7776,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
}
parser->error = false;
before_labels = get_before_labels ();
+ astate.reset ();
continue;
}
else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -7784,6 +7788,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
/* FIXME: Maybe issue a warning or something here? */
c_parser_consume_token (parser);
before_labels = get_before_labels ();
+ astate.reset ();
continue;
}
}
@@ -7795,7 +7800,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
if (have_std_attrs)
{
std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- std_attrs = c_parser_handle_musttail (parser, std_attrs, a);
+ std_attrs = c_parser_handle_musttail (parser, std_attrs, astate);
}
if (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
@@ -7937,6 +7942,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
error_at (loc, "%<else%> without a previous %<if%>");
c_parser_consume_token (parser);
before_labels = get_before_labels ();
+ astate.reset ();
continue;
}
}
@@ -7949,7 +7955,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
mark_valid_location_for_stdc_pragma (false);
if (!omp_for_parse_state)
c_parser_statement_after_labels (parser, NULL, before_labels,
- NULL, a);
+ NULL, astate);
else
{
/* In canonical loop nest form, nested loops can only appear
@@ -7966,6 +7972,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
}
parser->error = false;
+ astate.reset ();
}
if (last_label)
pedwarn_c11 (label_loc, OPT_Wfree_labels,
diff --git a/gcc/testsuite/c-c++-common/pr124532.c
b/gcc/testsuite/c-c++-common/pr124532.c
new file mode 100644
index 000000000000..53ec308d08d3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr124532.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { musttail && { c || c++11 } } } } */
+
+extern int f(void);
+
+static int g(void) {
+ [[gnu::musttail]] return f();
+ return 42;
+}
+
+static int g2(void) {
+ if (1) [[gnu::musttail]] return f();
+ return 42;
+}
--
2.54.0