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

Reply via email to