On Sat, Oct 14, 2023 at 03:46:52PM -0600, Sandra Loosemore wrote:
> On 10/14/23 13:43, Tobias Burnus wrote:
> > When browsing libgomp doc, I came across
> > https://gcc.gnu.org/onlinedocs/libgomp/Enabling-OpenMP.html>> First, I
> > found especially the Fortran part difficult to read. Secondly,
> > it missed the C++ attribute syntax. And I also missed a reference to
> > -fopenmp-simd.
> > 
> > The attached patch tries to improve this. Note that it talks about C and
> > C++ attributes, even though C23's [[omp::]] support has not yet landed.
> > (But is expected very soon.)
> 
> Is somebody actively working on implementing that, and expecting to get it
> in before Stage 1 closes?  I don't think we should document features that

I am (attached is a WIP, which can now compile most of g++.dg/gomp/attrs-1.C
in -std=c2x -fopenmp, except for the scan/section directives).
That said, I agree it might be premature to document it before it is in.

> don't exist yet.  This syntax for C also isn't even in the draft OpenMP 6.0
> document so at this point it's just a hypothetical extension.

It is in OpenMP spec git and it is very unlikely it would be removed.

        Jakub
--- gcc/cp/parser.h.jj  2023-09-20 08:42:51.987008923 +0200
+++ gcc/cp/parser.h     2023-10-12 13:32:42.503496571 +0200
@@ -408,7 +408,8 @@ struct GTY(()) cp_parser {
      identifiers) rather than an explicit template parameter list.  */
   bool fully_implicit_function_template_p;
 
-  /* TRUE if omp::directive or omp::sequence attributes may not appear.  */
+  /* TRUE if omp::directive, omp::decl or omp::sequence attributes may not
+     appear.  */
   bool omp_attrs_forbidden_p;
 
   /* Tracks the function's template parameter list when declaring a function
--- gcc/c/c-decl.cc.jj  2023-10-11 10:59:12.378170030 +0200
+++ gcc/c/c-decl.cc     2023-10-11 17:23:42.902257966 +0200
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3.
 #include "context.h"  /* For 'g'.  */
 #include "omp-general.h"
 #include "omp-offload.h"  /* For offload_vars.  */
+#include "c-parser.h"
 
 #include "tree-pretty-print.h"
 
@@ -325,15 +326,34 @@ i_label_binding (tree node)
 
 /* The resulting tree type.  */
 
-union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE + 2 * (TREE_CODE 
(&%h.generic) == C_TOKEN_VEC)"),
        chain_next ("(union lang_tree_node *) c_tree_chain_next 
(&%h.generic)"))) lang_tree_node
  {
   union tree_node GTY ((tag ("0"),
                        desc ("tree_node_structure (&%h)")))
     generic;
   struct lang_identifier GTY ((tag ("1"))) identifier;
+  struct c_tree_token_vec GTY ((tag ("2"))) c_token_vec;
 };
 
+/* Langhook for tree_size.  */
+size_t
+c_tree_size (enum tree_code code)
+{
+  gcc_checking_assert (code >= NUM_TREE_CODES);
+  switch (code)
+    {
+    case C_TOKEN_VEC: return sizeof (c_tree_token_vec);
+    default:
+      switch (TREE_CODE_CLASS (code))
+       {
+       case tcc_declaration: return sizeof (tree_decl_non_common);
+       case tcc_type: return sizeof (tree_type_non_common);
+       default: gcc_unreachable ();
+       }
+    }
+}
+
 /* Track bindings and other things that matter for goto warnings.  For
    efficiency, we do not gather all the decls at the point of
    definition.  Instead, we point into the bindings structure.  As
--- gcc/c/c-parser.cc.jj        2023-10-11 10:59:12.426169364 +0200
+++ gcc/c/c-parser.cc   2023-10-13 17:47:27.329066662 +0200
@@ -247,12 +247,21 @@ struct GTY(()) c_parser {
      macro.  */
   BOOL_BITFIELD seen_string_literal : 1;
 
+  /* TRUE if omp::directive, omp::decl or omp::sequence attributes may not
+     appear.  */
+  BOOL_BITFIELD omp_attrs_forbidden_p : 1;
+
   /* Location of the last consumed token.  */
   location_t last_token_location;
 
   /* Holds state for parsing collapsed OMP_FOR loops.  Managed by
      c_parser_omp_for_loop.  */
   struct omp_for_parse_data * GTY((skip)) omp_for_parse_state;
+
+  /* If we're in the context of OpenMP directives written as C23
+     attributes turned into pragma, vector of tokens created from that,
+     otherwise NULL.  */
+  vec<c_token, va_gc> *in_omp_attribute_pragma;
 };
 
 /* Return a pointer to the Nth token in PARSERs tokens_buf.  */
@@ -1383,6 +1392,17 @@ c_parser_skip_to_pragma_eol (c_parser *p
     }
   while (token_type != CPP_PRAGMA_EOL);
 
+  if (parser->in_omp_attribute_pragma)
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if (token->type == CPP_EOF)
+       {
+         parser->tokens = &parser->tokens_buf[0];
+         parser->tokens_avail = token->flags;
+         parser->in_omp_attribute_pragma = NULL;
+       }
+    }
+
   parser->error = false;
 }
 
@@ -5430,6 +5450,109 @@ c_parser_balanced_token_sequence (c_pars
     }
 }
 
+static bool c_parser_check_balanced_raw_token_sequence (c_parser *,
+                                                       unsigned int *);
+
+/* Parse arguments of omp::directive or omp::decl attribute.
+
+   directive-name ,[opt] clause-list[opt]
+
+   For directive just remember the tokens in a vector for subsequent
+   parsing.  */
+
+static void
+c_parser_omp_directive_args (c_parser *parser, tree attribute, bool decl_p)
+{
+  unsigned int n = 1;
+  c_token *first = c_parser_peek_token (parser);
+  if (!c_parser_check_balanced_raw_token_sequence (parser, &n)
+      || (c_parser_peek_nth_token_raw (parser, n)->type
+         != CPP_CLOSE_PAREN))
+    {
+      c_parser_balanced_token_sequence (parser);
+      TREE_VALUE (attribute) = NULL_TREE;
+      return;
+    }
+  if (n == 1)
+    {
+      error_at (first->location, "expected OpenMP directive name");
+      TREE_VALUE (attribute) = NULL_TREE;
+      return;
+    }
+  vec<c_token, va_gc> *v;
+  vec_alloc (v, n - 1);
+  for (--n; n; --n)
+    {
+      c_token *tok = c_parser_peek_token (parser);
+      v->quick_push (*tok);
+      c_parser_consume_token (parser);
+    }
+  tree arg = make_node (C_TOKEN_VEC);
+  ((struct c_tree_token_vec *) arg)->tokens = v;
+  if (decl_p)
+    TREE_PUBLIC (arg) = 1;
+  TREE_VALUE (attribute) = tree_cons (NULL_TREE, arg, TREE_VALUE (attribute));
+}
+
+/* Parse arguments of omp::sequence attribute.
+
+   omp::[opt] directive-attr [ , omp::[opt] directive-attr ]...  */
+
+static void
+c_parser_omp_sequence_args (c_parser *parser, tree attribute)
+{
+  do
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if (token->type == CPP_NAME
+         && strcmp (IDENTIFIER_POINTER (token->value), "omp") == 0
+         && c_parser_peek_2nd_token (parser)->type == CPP_SCOPE)
+       {
+         c_parser_consume_token (parser);
+         c_parser_consume_token (parser);
+         token = c_parser_peek_token (parser);
+       }
+      bool directive = false;
+      const char *p;
+      if (token->type != CPP_NAME)
+       p = "";
+      else
+       p = IDENTIFIER_POINTER (token->value);
+      if (strcmp (p, "directive") == 0)
+       directive = true;
+      else if (strcmp (p, "sequence") != 0)
+       {
+         error_at (token->location, "expected %<directive%> or %<sequence%>");
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+           {
+             matching_parens parens;
+             parens.consume_open (parser);
+             c_parser_balanced_token_sequence (parser);
+             parens.require_close (parser);
+           }
+         if (c_parser_next_token_is_not (parser, CPP_COMMA))
+           break;
+         c_parser_consume_token (parser);
+         continue;
+       }
+      c_parser_consume_token (parser);
+      matching_parens parens;
+      if (parens.require_open (parser))
+       {
+         if (directive)
+           c_parser_omp_directive_args (parser, attribute, false);
+         else
+           c_parser_omp_sequence_args (parser, attribute);
+         parens.skip_until_found_close (parser);
+         if (c_parser_next_token_is_not (parser, CPP_COMMA))
+           break;
+         c_parser_consume_token (parser);
+       }
+    }
+  while (1);
+}
+
 /* Parse standard (C2X) attributes (including GNU attributes in the
    gnu:: namespace).
 
@@ -5512,7 +5635,19 @@ c_parser_std_attribute (c_parser *parser
   /* Parse the arguments, if any.  */
   const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
   if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
-    goto out;
+    {
+      if ((flag_openmp || flag_openmp_simd)
+         && ns
+         && is_attribute_p ("omp", ns)
+         && (is_attribute_p ("directive", name)
+             || is_attribute_p ("sequence", name)
+             || is_attribute_p ("decl", name)))
+       {
+         error ("%<omp::%E%> attribute requires argument", name);
+         return error_mark_node;
+       }
+      goto out;
+    }
   {
     location_t open_loc = c_parser_peek_token (parser)->location;
     matching_parens parens;
@@ -5549,7 +5684,37 @@ c_parser_std_attribute (c_parser *parser
                                          require_string, assume_attr, false);
       }
     else
-      c_parser_balanced_token_sequence (parser);
+      {
+       if ((flag_openmp || flag_openmp_simd)
+           && ns
+           && is_attribute_p ("omp", ns))
+         {
+           if (is_attribute_p ("directive", name))
+             {
+               c_parser_omp_directive_args (parser, attribute, false);
+               parens.require_close (parser);
+               return attribute;
+             }
+           else if (is_attribute_p ("decl", name))
+             {
+               TREE_VALUE (TREE_PURPOSE (attribute))
+                 = get_identifier ("directive");
+               c_parser_omp_directive_args (parser, attribute, true);
+               parens.require_close (parser);
+               return attribute;
+             }
+           else if (is_attribute_p ("sequence", name))
+             {
+               TREE_VALUE (TREE_PURPOSE (attribute))
+                 = get_identifier ("directive");
+               c_parser_omp_sequence_args (parser, attribute);
+               parens.require_close (parser);
+               TREE_VALUE (attribute) = nreverse (TREE_VALUE (attribute));
+               return attribute;
+             }
+         }
+       c_parser_balanced_token_sequence (parser);
+      }
     parens.require_close (parser);
   }
  out:
@@ -6322,6 +6487,243 @@ add_structured_block_stmt (tree sl)
     add_stmt (build1 (OMP_STRUCTURED_BLOCK, void_type_node, sl));
 }
 
+struct c_omp_attribute_data
+{
+  vec<c_token, va_gc> *tokens;
+  const c_omp_directive *dir;
+  c_omp_directive_kind kind;
+};
+
+/* Handle omp::directive and omp::sequence attributes in ATTRS
+   (if any) at the start of a statement or in attribute-declaration.  */
+
+static bool
+c_parser_handle_statement_omp_attributes (c_parser *parser, tree &attrs)
+{
+  if (!flag_openmp && !flag_openmp_simd)
+    return false;
+
+  auto_vec<c_omp_attribute_data, 16> vd;
+  int cnt = 0;
+  int tokens = 0;
+  bool bad = false;
+  for (tree *pa = &attrs; *pa; )
+    if (is_attribute_namespace_p ("omp", *pa)
+       && is_attribute_p ("directive", get_attribute_name (*pa)))
+      {
+       cnt++;
+       for (tree a = TREE_VALUE (*pa); a; a = TREE_CHAIN (a))
+         {
+           tree d = TREE_VALUE (a);
+           gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
+           vec<c_token, va_gc> *toks
+             = ((struct c_tree_token_vec *) d)->tokens;
+           c_token *first = toks->address ();
+           c_token *last = first + toks->length ();
+           if (parser->omp_attrs_forbidden_p)
+             {
+               error_at (first->location,
+                         "mixing OpenMP directives with attribute and pragma "
+                         "syntax on the same statement");
+               parser->omp_attrs_forbidden_p = false;
+               bad = true;
+             }
+           else if (TREE_PUBLIC (d))
+             {
+               error_at (first->location,
+                         "OpenMP %<omp::decl%> attribute on a statement");
+               bad = true;
+             }
+           const char *directive[3] = {};
+           for (int i = 0; i < 3; i++)
+             {
+               tree id = NULL_TREE;
+               if (first + i == last)
+                 break;
+               if (first[i].type == CPP_NAME)
+                 id = first[i].value;
+               else if (first[i].type == CPP_KEYWORD)
+                 id = ridpointers[(int) first[i].keyword];
+               else
+                 break;
+               directive[i] = IDENTIFIER_POINTER (id);
+             }
+           const c_omp_directive *dir = NULL;
+           if (directive[0])
+             dir = c_omp_categorize_directive (directive[0], directive[1],
+                                               directive[2]);
+           if (dir == NULL)
+             {
+               error_at (first->location,
+                         "unknown OpenMP directive name in %qs attribute "
+                         "argument",
+                         TREE_PUBLIC (d) ? "omp::decl" : "omp::directive");
+               continue;
+             }
+           c_omp_directive_kind kind = dir->kind;
+           if (dir->id == PRAGMA_OMP_ORDERED)
+             {
+               /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
+                  depend/doacross clause.  */
+               if (directive[1]
+                   && (strcmp (directive[1], "depend") == 0
+                       || strcmp (directive[1], "doacross") == 0))
+                 kind = C_OMP_DIR_STANDALONE;
+               else if (first + 2 < last
+                        && first[1].type == CPP_COMMA
+                        && first[2].type == CPP_NAME
+                        && (strcmp (IDENTIFIER_POINTER (first[2].value),
+                                    "depend") == 0
+                            || strcmp (IDENTIFIER_POINTER (first[2].value),
+                                       "doacross") == 0))
+                 kind = C_OMP_DIR_STANDALONE;
+             }
+           else if (dir->id == PRAGMA_OMP_ERROR)
+             {
+               /* error with at(execution) clause is C_OMP_DIR_STANDALONE.  */
+               int paren_depth = 0;
+               for (int i = 1; first + i < last; i++)
+                 if (first[i].type == CPP_OPEN_PAREN)
+                   paren_depth++;
+                 else if (first[i].type == CPP_CLOSE_PAREN)
+                   paren_depth--;
+                 else if (paren_depth == 0
+                          && first + i + 2 < last
+                          && first[i].type == CPP_NAME
+                          && first[i + 1].type == CPP_OPEN_PAREN
+                          && first[i + 2].type == CPP_NAME
+                          && !strcmp (IDENTIFIER_POINTER (first[i].value),
+                                      "at")
+                          && !strcmp (IDENTIFIER_POINTER (first[i
+                                                                + 2].value),
+                                      "execution"))
+                   {
+                     kind = C_OMP_DIR_STANDALONE;
+                     break;
+                   }
+             }
+           c_omp_attribute_data v = { toks, dir, kind };
+           vd.safe_push (v);
+           if (flag_openmp || dir->simd)
+             tokens += (last - first) + 1;
+         }
+       c_omp_attribute_data v = {};
+       vd.safe_push (v);
+       *pa = TREE_CHAIN (*pa);
+      }
+    else
+      pa = &TREE_CHAIN (*pa);
+
+  if (bad)
+    return false;
+
+  unsigned int i;
+  c_omp_attribute_data *v;
+  c_omp_attribute_data *construct_seen = nullptr;
+  c_omp_attribute_data *standalone_seen = nullptr;
+  c_omp_attribute_data *prev_standalone_seen = nullptr;
+  FOR_EACH_VEC_ELT (vd, i, v)
+    if (v->tokens)
+      {
+       if (v->kind == C_OMP_DIR_CONSTRUCT && !construct_seen)
+         construct_seen = v;
+       else if (v->kind == C_OMP_DIR_STANDALONE && !standalone_seen)
+         standalone_seen = v;
+      }
+    else
+      {
+       if (standalone_seen && !prev_standalone_seen)
+         {
+           prev_standalone_seen = standalone_seen;
+           standalone_seen = nullptr;
+         }
+      }
+
+  if (cnt > 1 && construct_seen)
+    {
+      error_at ((*construct_seen->tokens)[0].location,
+               "OpenMP construct among %<omp::directive%> attributes"
+               " requires all %<omp::directive%> attributes on the"
+               " same statement to be in the same %<omp::sequence%>");
+      return false;
+    }
+  if (cnt > 1 && standalone_seen && prev_standalone_seen)
+    {
+      error_at ((*standalone_seen->tokens)[0].location,
+               "multiple OpenMP standalone directives among"
+               " %<omp::directive%> attributes must be all within the"
+               " same %<omp::sequence%>");
+      return false;
+    }
+
+  if (prev_standalone_seen)
+    standalone_seen = prev_standalone_seen;
+  if (standalone_seen
+      && !c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      error_at (standalone_seen->tokens->address ()->location,
+               "standalone OpenMP directives in %<omp::directive%> attribute"
+               " can only appear on an empty statement");
+      return false;
+    }
+  if (cnt && c_parser_next_token_is (parser, CPP_PRAGMA))
+    {
+      c_token *token = c_parser_peek_token (parser);
+      enum pragma_kind kind = token->pragma_kind;
+      if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
+       {
+         error_at (token->location,
+                   "mixing OpenMP directives with attribute and pragma "
+                   "syntax on the same statement");
+         return false;
+       }
+    }
+
+  if (!tokens)
+    return false;
+
+  unsigned int tokens_avail = parser->tokens_avail;
+  gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+
+  tokens++;
+  vec<c_token, va_gc> *toks = NULL;
+  vec_safe_reserve (toks, tokens, true);
+  FOR_EACH_VEC_ELT (vd, i, v)
+    {
+      if (!v->tokens)
+       continue;
+      if (!flag_openmp && !v->dir->simd)
+       continue;
+      c_token *first = v->tokens->address ();
+      c_token *last = first + v->tokens->length ();
+      c_token tok = {};
+      tok.type = CPP_PRAGMA;
+      tok.keyword = RID_MAX;
+      tok.pragma_kind = pragma_kind (v->dir->id);
+      tok.location = first->location;
+      toks->quick_push (tok);
+      while (++first < last)
+       toks->quick_push (*first);
+      tok = {};
+      tok.type = CPP_PRAGMA_EOL;
+      tok.keyword = RID_MAX;
+      tok.location = last->location;
+      toks->quick_push (tok);
+    }
+
+  c_token tok = {};
+  tok.type = CPP_EOF;
+  tok.keyword = RID_MAX;
+  tok.location = toks->last ().location;
+  tok.flags = tokens_avail;
+  toks->quick_push (tok);
+
+  parser->tokens = toks->address ();
+  parser->tokens_avail = tokens;
+  parser->in_omp_attribute_pragma = toks;
+  return true;
+}
+
 /* Parse a compound statement except for the opening brace.  This is
    used for parsing both compound statements and statement expressions
    (which follow different paths to handling the opening).  */
@@ -6495,6 +6897,8 @@ c_parser_compound_statement_nostart (c_p
        }
       else if (c_parser_next_tokens_start_declaration (parser)
               || (have_std_attrs
+                  && !c_parser_handle_statement_omp_attributes (parser,
+                                                                std_attrs)
                   && c_parser_next_token_is (parser, CPP_SEMICOLON)))
        {
          if (last_label)
@@ -6569,8 +6973,10 @@ c_parser_compound_statement_nostart (c_p
        }
       else if (c_parser_next_token_is (parser, CPP_PRAGMA))
        {
-         if (have_std_attrs)
+         if (have_std_attrs && !parser->in_omp_attribute_pragma)
            c_parser_error (parser, "expected declaration or statement");
+         else if (std_attrs)
+           c_warn_unused_attributes (std_attrs);
          /* External pragmas, and some omp pragmas, are not associated
             with regular c code, and so are not to be considered statements
             syntactically.  This ensures that the user doesn't put them
@@ -6588,7 +6994,7 @@ c_parser_compound_statement_nostart (c_p
                check_omp_intervening_code (parser);
            }
          if (omp_for_parse_state)
-             omp_for_parse_state->want_nested_loop = want_nested_loop;
+           omp_for_parse_state->want_nested_loop = want_nested_loop;
        }
       else if (c_parser_next_token_is (parser, CPP_EOF))
        {
@@ -6687,8 +7093,10 @@ c_parser_all_labels (c_parser *parser)
            c_parser_error (parser, "expected statement");
        }
     }
-   if (std_attrs)
-     c_warn_unused_attributes (std_attrs);
+  if (std_attrs
+      && (!c_parser_handle_statement_omp_attributes (parser, std_attrs)
+         || std_attrs))
+    c_warn_unused_attributes (std_attrs);
 }
 
 /* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
@@ -6935,6 +7343,7 @@ c_parser_statement (c_parser *parser, bo
   c_parser_all_labels (parser);
   if (loc_after_labels)
     *loc_after_labels = c_parser_peek_token (parser)->location;
+  parser->omp_attrs_forbidden_p = false;
   c_parser_statement_after_labels (parser, if_p, NULL);
 }
 
@@ -14206,6 +14615,7 @@ c_parser_omp_variable_list (c_parser *pa
   bool array_section_p;
   auto_vec<c_token> tokens;
   unsigned int tokens_avail = 0;
+  c_token *saved_tokens = NULL;
   bool first = true;
 
   while (1)
@@ -14285,8 +14695,8 @@ c_parser_omp_variable_list (c_parser *pa
          tokens.safe_push (eof_token);
          tokens.safe_push (eof_token);
 
+         saved_tokens = parser->tokens;
          tokens_avail = parser->tokens_avail;
-         gcc_assert (parser->tokens == &parser->tokens_buf[0]);
          parser->tokens = tokens.address ();
          parser->tokens_avail = tokens.length ();
        }
@@ -14503,7 +14913,7 @@ c_parser_omp_variable_list (c_parser *pa
 
       if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
        {
-         parser->tokens = &parser->tokens_buf[0];
+         parser->tokens = saved_tokens;
          parser->tokens_avail = tokens_avail;
        }
       if (c_parser_next_token_is_not (parser, CPP_COMMA))
@@ -18631,6 +19041,7 @@ static tree
 c_parser_omp_structured_block (c_parser *parser, bool *if_p)
 {
   tree stmt = push_stmt_list ();
+  parser->omp_attrs_forbidden_p = true;
   c_parser_statement (parser, if_p);
   return pop_stmt_list (stmt);
 }
@@ -22022,6 +22433,7 @@ c_parser_omp_parallel (location_t loc, c
     }
 
   block = c_begin_omp_parallel ();
+  parser->omp_attrs_forbidden_p = true;
   c_parser_statement (parser, if_p);
   stmt = c_finish_omp_parallel (loc, clauses, block);
 
@@ -22117,6 +22529,7 @@ c_parser_omp_task (location_t loc, c_par
                                      "#pragma omp task");
 
   block = c_begin_omp_task ();
+  parser->omp_attrs_forbidden_p = true;
   c_parser_statement (parser, if_p);
   return c_finish_omp_task (loc, clauses, block);
 }
@@ -23972,6 +24385,7 @@ static void
 c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
 {
   unsigned int tokens_avail = 0, i;
+  c_token *saved_tokens = NULL;
   vec<tree> types = vNULL;
   vec<c_token> clauses = vNULL;
   enum tree_code reduc_code = ERROR_MARK;
@@ -24142,8 +24556,8 @@ c_parser_omp_declare_reduction (c_parser
   int errs = errorcount;
   FOR_EACH_VEC_ELT (types, i, type)
     {
+      saved_tokens = parser->tokens;
       tokens_avail = parser->tokens_avail;
-      gcc_assert (parser->tokens == &parser->tokens_buf[0]);
       if (!clauses.is_empty ())
        {
          parser->tokens = clauses.address ();
@@ -24304,7 +24718,7 @@ c_parser_omp_declare_reduction (c_parser
 
       if (!clauses.is_empty ())
        {
-         parser->tokens = &parser->tokens_buf[0];
+         parser->tokens = saved_tokens;
          parser->tokens_avail = tokens_avail;
        }
       if (bad)
--- gcc/c/c-objc-common.h.jj    2023-10-11 10:59:12.398169753 +0200
+++ gcc/c/c-objc-common.h       2023-10-11 17:23:42.906257914 +0200
@@ -26,6 +26,8 @@ along with GCC; see the file COPYING3.
 
 #undef LANG_HOOKS_IDENTIFIER_SIZE
 #define LANG_HOOKS_IDENTIFIER_SIZE C_SIZEOF_STRUCT_LANG_IDENTIFIER
+#undef LANG_HOOKS_TREE_SIZE
+#define LANG_HOOKS_TREE_SIZE c_tree_size
 #undef LANG_HOOKS_FINISH
 #define LANG_HOOKS_FINISH c_common_finish
 #undef LANG_HOOKS_OPTION_LANG_MASK
--- gcc/c/c-parser.h.jj 2023-10-11 10:59:12.446169086 +0200
+++ gcc/c/c-parser.h    2023-10-11 17:23:42.906257914 +0200
@@ -80,6 +80,12 @@ struct GTY (()) c_token {
   }
 };
 
+/* Used by C_TOKEN_VEC tree.  */
+struct GTY (()) c_tree_token_vec {
+  struct tree_base base;
+  vec<c_token, va_gc> *tokens;
+};
+
 /* The parser.  */
 struct c_parser;
 
--- gcc/c/c-tree.def.jj 2023-10-11 17:23:42.906257914 +0200
+++ gcc/c/c-tree.def    2023-10-11 17:23:42.906257914 +0200
@@ -0,0 +1,31 @@
+/* This file contains the definitions and documentation for the
+   additional tree codes used in the GNU C compiler (see tree.def
+   for the standard codes).
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* Tree nodes used in the C frontend only, not shared with C++ frontend.  */
+
+/* Used to represent a vector of tokens for deferred parsing.  */
+DEFTREECODE (C_TOKEN_VEC, "c_token_vec", tcc_exceptional, 0)
+
+/*
+Local variables:
+mode:c
+End:
+*/
--- gcc/c/c-lang.cc.jj  2023-10-11 10:59:12.398169753 +0200
+++ gcc/c/c-lang.cc     2023-10-11 17:23:42.906257914 +0200
@@ -25,6 +25,8 @@ along with GCC; see the file COPYING3.
 #include "langhooks.h"
 #include "langhooks-def.h"
 #include "c-objc-common.h"
+#include "c-family/c-pragma.h"
+#include "c-parser.h"
 
 enum c_language_kind c_language = clk_c;
 
--- gcc/c/c-tree.h.jj   2023-10-11 10:59:12.446169086 +0200
+++ gcc/c/c-tree.h      2023-10-11 17:23:42.906257914 +0200
@@ -596,6 +596,7 @@ enum c_inline_static_type {
 
 
 /* in c-parser.cc */
+struct c_tree_token_vec;
 extern void c_parse_init (void);
 extern bool c_keyword_starts_typename (enum rid keyword);
 
@@ -719,6 +720,7 @@ extern struct c_declspecs *declspecs_add
 extern struct c_declspecs *declspecs_add_alignas (location_t,
                                                  struct c_declspecs *, tree);
 extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
+extern size_t c_tree_size (enum tree_code);
 
 /* in c-objc-common.cc */
 extern bool c_objc_common_init (void);
--- gcc/objc/objc-act.h.jj      2023-10-11 10:59:12.496168392 +0200
+++ gcc/objc/objc-act.h 2023-10-11 17:23:42.906257914 +0200
@@ -738,8 +738,6 @@ struct objc_try_context
 
 extern tree objc_create_temporary_var (tree, const char *);
 
-size_t objc_common_tree_size (enum tree_code code);
-
 
 #define objc_is_object_id(TYPE) (OBJC_TYPE_NAME (TYPE) == objc_object_id)
 #define objc_is_class_id(TYPE) (OBJC_TYPE_NAME (TYPE) == objc_class_id)
--- gcc/objc/objc-lang.cc.jj    2023-10-11 10:59:12.496168392 +0200
+++ gcc/objc/objc-lang.cc       2023-10-11 17:23:42.927257640 +0200
@@ -44,8 +44,6 @@ enum c_language_kind c_language = clk_ob
 #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
 #undef LANG_HOOKS_INIT_TS
 #define LANG_HOOKS_INIT_TS objc_common_init_ts
-#undef LANG_HOOKS_TREE_SIZE
-#define LANG_HOOKS_TREE_SIZE objc_common_tree_size
 #undef LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE
 #define LANG_HOOKS_GET_SARIF_SOURCE_LANGUAGE objc_get_sarif_source_language
 
--- gcc/objc/objc-act.cc.jj     2023-10-11 10:59:12.482168587 +0200
+++ gcc/objc/objc-act.cc        2023-10-11 17:23:42.928257627 +0200
@@ -10340,24 +10340,5 @@ objc_common_init_ts (void)
   MARK_TS_TYPED (PROPERTY_REF);
 }
 
-size_t
-objc_common_tree_size (enum tree_code code)
-{
-  switch (code)
-    {
-    case CLASS_METHOD_DECL:
-    case INSTANCE_METHOD_DECL:
-    case KEYWORD_DECL:
-    case PROPERTY_DECL:                        return sizeof 
(tree_decl_non_common);
-    case CLASS_INTERFACE_TYPE:
-    case CLASS_IMPLEMENTATION_TYPE:
-    case CATEGORY_INTERFACE_TYPE:
-    case CATEGORY_IMPLEMENTATION_TYPE:
-    case PROTOCOL_INTERFACE_TYPE:      return sizeof (tree_type_non_common);
-    default:
-      gcc_unreachable ();
-    }
-}
-
 
 #include "gt-objc-objc-act.h"

Reply via email to