Hi!

On Wed, 13 Jul 2016 11:25:46 +0200, I wrote:
>     C/C++: Simplify handling of location information for OpenACC routine 
> directives

Without changes, committed to trunk in r239127:

commit 5f429ee2993ea1795d88c5589251c500e6e9062a
Author: tschwinge <tschwinge@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Thu Aug 4 13:35:19 2016 +0000

    C/C++: Simplify handling of location information for OpenACC routine 
directives
    
        gcc/c/
        * c-parser.c (struct oacc_routine_data): New.
        (c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it.
        Simplify code.
        (c_finish_oacc_routine): Likewise.  Don't attach clauses to "omp
        declare target" attribute.
        gcc/cp/
        * parser.h (struct cp_omp_declare_simd_data): New.
        (struct cp_parser): Use it for oacc_routine member.
        * parser.c (cp_ensure_no_oacc_routine, cp_parser_oacc_routine)
        (cp_parser_late_parsing_oacc_routine, cp_finalize_oacc_routine):
        Use it.  Simplify code.
        (cp_parser_new): Initialize all members pointing to special
        parsing data structures.
        (cp_parser_cilk_simd_fn_vector_attrs): Initialize
        parser->cilk_simd_fn_info->clauses.
        (cp_parser_omp_declare_simd): Initialize
        parser->omp_declare_simd->clauses.
        (cp_parser_late_parsing_omp_declare_simd): Simplify code.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239127 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/c/ChangeLog  |   8 +++++
 gcc/c/c-parser.c |  86 ++++++++++++++++++++++----------------------
 gcc/cp/ChangeLog |  15 ++++++++
 gcc/cp/parser.c  | 108 ++++++++++++++++++++++++-------------------------------
 gcc/cp/parser.h  |  21 ++++++-----
 5 files changed, 126 insertions(+), 112 deletions(-)

diff --git gcc/c/ChangeLog gcc/c/ChangeLog
index 1c0688b..7ef094a 100644
--- gcc/c/ChangeLog
+++ gcc/c/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-04  Thomas Schwinge  <tho...@codesourcery.com>
+
+       * c-parser.c (struct oacc_routine_data): New.
+       (c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it.
+       Simplify code.
+       (c_finish_oacc_routine): Likewise.  Don't attach clauses to "omp
+       declare target" attribute.
+
 2016-08-01  Jan Beulich  <jbeul...@suse.com>
 
        * c-fold.c (c_fully_fold_internal): Also emit shift count
diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index cc68912..c4a9797 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -1274,11 +1274,17 @@ enum c_parser_prec {
   NUM_PRECS
 };
 
+/* Helper data structure for parsing #pragma acc routine.  */
+struct oacc_routine_data {
+  tree clauses;
+  location_t loc;
+};
+
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
                                           bool, bool, tree *, vec<c_token>,
-                                          tree = NULL_TREE);
+                                          struct oacc_routine_data * = NULL);
 static void c_parser_static_assert_declaration_no_semi (c_parser *);
 static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
@@ -1370,7 +1376,7 @@ static bool c_parser_omp_target (c_parser *, enum 
pragma_context, bool *);
 static void c_parser_omp_end_declare_target (c_parser *);
 static void c_parser_omp_declare (c_parser *, enum pragma_context);
 static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
-static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
+static void c_parser_oacc_routine (c_parser *, enum pragma_context);
 
 /* These Objective-C parser functions are only ever called when
    compiling Objective-C.  */
@@ -1562,7 +1568,8 @@ c_parser_external_declaration (c_parser *parser)
 }
 
 static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
-static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
+static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool,
+                                  bool, bool);
 
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
@@ -1641,7 +1648,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                               bool nested, bool start_attr_ok,
                               tree *objc_foreach_object_declaration,
                               vec<c_token> omp_declare_simd_clauses,
-                              tree oacc_routine_clauses)
+                              struct oacc_routine_data *oacc_routine_data)
 {
   struct c_declspecs *specs;
   tree prefix_attrs;
@@ -1746,9 +1753,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
          pedwarn (here, 0, "empty declaration");
        }
       c_parser_consume_token (parser);
-      if (oacc_routine_clauses)
-       c_finish_oacc_routine (parser, NULL_TREE,
-                              oacc_routine_clauses, false, true, false);
+      if (oacc_routine_data)
+       c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false, true,
+                              false);
       return;
     }
 
@@ -1865,9 +1872,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
              || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
            c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
                                       omp_declare_simd_clauses);
-         if (oacc_routine_clauses)
-           c_finish_oacc_routine (parser, NULL_TREE,
-                                  oacc_routine_clauses,
+         if (oacc_routine_data)
+           c_finish_oacc_routine (oacc_routine_data, NULL_TREE,
                                   false, first, false);
          c_parser_skip_to_end_of_block_or_statement (parser);
          return;
@@ -1983,8 +1989,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                  init = c_parser_initializer (parser);
                  finish_init ();
                }
-             if (oacc_routine_clauses)
-               c_finish_oacc_routine (parser, d, oacc_routine_clauses,
+             if (oacc_routine_data)
+               c_finish_oacc_routine (oacc_routine_data, d,
                                       false, first, false);
              if (d != error_mark_node)
                {
@@ -2029,8 +2035,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                  if (parms)
                    temp_pop_parm_decls ();
                }
-             if (oacc_routine_clauses)
-               c_finish_oacc_routine (parser, d, oacc_routine_clauses,
+             if (oacc_routine_data)
+               c_finish_oacc_routine (oacc_routine_data, d,
                                       false, first, false);
              if (d)
                finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
@@ -2142,9 +2148,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
          || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
        c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
                                   omp_declare_simd_clauses);
-      if (oacc_routine_clauses)
-       c_finish_oacc_routine (parser, current_function_decl,
-                              oacc_routine_clauses, false, first, true);
+      if (oacc_routine_data)
+       c_finish_oacc_routine (oacc_routine_data, current_function_decl,
+                              false, first, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
       fnbody = c_parser_compound_statement (parser);
@@ -14025,9 +14031,9 @@ static void
 c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
 {
   tree decl = NULL_TREE;
-  /* Create a dummy claue, to record location.  */
-  tree c_head = build_omp_clause (c_parser_peek_token (parser)->location,
-                                 OMP_CLAUSE_SEQ);
+  oacc_routine_data data;
+  data.clauses = NULL_TREE;
+  data.loc = c_parser_peek_token (parser)->location;
   
   if (context != pragma_external)
     c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
@@ -14062,56 +14068,52 @@ c_parser_oacc_routine (c_parser *parser, enum 
pragma_context context)
 
   /* Build a chain of clauses.  */
   parser->in_pragma = true;
-  tree clauses = c_parser_oacc_all_clauses
-    (parser, OACC_ROUTINE_CLAUSE_MASK, "#pragma acc routine");
+  data.clauses
+    = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+                                "#pragma acc routine");
 
-  /* Force clauses to be non-null, by attaching context to it.  */
-  clauses = tree_cons (c_head, clauses, NULL_TREE);
-  
   if (decl)
-    c_finish_oacc_routine (parser, decl, clauses, true, true, false);
+    c_finish_oacc_routine (&data, decl, true, true, false);
   else if (c_parser_peek_token (parser)->type == CPP_PRAGMA)
     /* This will emit an error.  */
-    c_finish_oacc_routine (parser, NULL_TREE, clauses, false, true, false);
+    c_finish_oacc_routine (&data, NULL_TREE, false, true, false);
   else
     c_parser_declaration_or_fndef (parser, true, false, false, false,
-                                  true, NULL, vNULL, clauses);
+                                  true, NULL, vNULL, &data);
 }
 
-/* Finalize an OpenACC routine pragma, applying it to FNDECL.  CLAUSES
-   are the parsed clauses.  IS_DEFN is true if we're applying it to
-   the definition (so expect FNDEF to look somewhat defined.  */
+/* Finalize an OpenACC routine pragma, applying it to FNDECL.
+   IS_DEFN is true if we're applying it to the definition.  */
 
 static void
-c_finish_oacc_routine (c_parser *ARG_UNUSED (parser), tree fndecl,
-                      tree clauses, bool named, bool first, bool is_defn)
+c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
+                      bool named, bool first, bool is_defn)
 {
-  location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses));
-
   if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL || !first)
     {
       if (fndecl != error_mark_node)
-       error_at (loc, "%<#pragma acc routine%> %s",
+       error_at (data->loc, "%<#pragma acc routine%> %s",
                  named ? "does not refer to a function"
                  : "not followed by single function");
       return;
     }
 
   if (get_oacc_fn_attrib (fndecl))
-    error_at (loc, "%<#pragma acc routine%> already applied to %D", fndecl);
+    error_at (data->loc,
+             "%<#pragma acc routine%> already applied to %D", fndecl);
 
   if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
-    error_at (loc, "%<#pragma acc routine%> must be applied before %s",
+    error_at (data->loc, "%<#pragma acc routine%> must be applied before %s",
              TREE_USED (fndecl) ? "use" : "definition");
 
-  /* Process for function attrib  */
-  tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
+  /* Process the routine's dimension clauses.  */
+  tree dims = build_oacc_routine_dims (data->clauses);
   replace_oacc_fn_attrib (fndecl, dims);
 
-  /* Also attach as a declare.  */
+  /* Add an "omp declare target" attribute.  */
   DECL_ATTRIBUTES (fndecl)
     = tree_cons (get_identifier ("omp declare target"),
-                clauses, DECL_ATTRIBUTES (fndecl));
+                NULL_TREE, DECL_ATTRIBUTES (fndecl));
 }
 
 /* OpenACC 2.0:
diff --git gcc/cp/ChangeLog gcc/cp/ChangeLog
index 2a99370..45e647d 100644
--- gcc/cp/ChangeLog
+++ gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2016-08-04  Thomas Schwinge  <tho...@codesourcery.com>
+
+       * parser.h (struct cp_omp_declare_simd_data): New.
+       (struct cp_parser): Use it for oacc_routine member.
+       * parser.c (cp_ensure_no_oacc_routine, cp_parser_oacc_routine)
+       (cp_parser_late_parsing_oacc_routine, cp_finalize_oacc_routine):
+       Use it.  Simplify code.
+       (cp_parser_new): Initialize all members pointing to special
+       parsing data structures.
+       (cp_parser_cilk_simd_fn_vector_attrs): Initialize
+       parser->cilk_simd_fn_info->clauses.
+       (cp_parser_omp_declare_simd): Initialize
+       parser->omp_declare_simd->clauses.
+       (cp_parser_late_parsing_omp_declare_simd): Simplify code.
+
 2016-08-04  Marek Polacek  <pola...@redhat.com>
 
        PR c++/70229
diff --git gcc/cp/parser.c gcc/cp/parser.c
index b71b9e5..e696d46 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -1391,10 +1391,8 @@ cp_ensure_no_oacc_routine (cp_parser *parser)
 {
   if (parser->oacc_routine && !parser->oacc_routine->error_seen)
     {
-      tree clauses = parser->oacc_routine->clauses;
-      location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses));
-
-      error_at (loc, "%<#pragma acc routine%> not followed by a function "
+      error_at (parser->oacc_routine->loc,
+               "%<#pragma acc routine%> not followed by a function "
                "declaration or definition");
       parser->oacc_routine = NULL;
     }
@@ -3775,15 +3773,17 @@ cp_parser_new (void)
   /* No template parameters apply.  */
   parser->num_template_parameter_lists = 0;
 
+  /* Special parsing data structures.  */
+  parser->omp_declare_simd = NULL;
+  parser->cilk_simd_fn_info = NULL;
+  parser->oacc_routine = NULL;
+
   /* Not declaring an implicit function template.  */
   parser->auto_is_implicit_function_template_parm_p = false;
   parser->fully_implicit_function_template_p = false;
   parser->implicit_template_parms = 0;
   parser->implicit_template_scope = 0;
 
-  /* Active OpenACC routine clauses.  */
-  parser->oacc_routine = NULL;
-
   /* Allow constrained-type-specifiers. */
   parser->prevent_constrained_type_specifiers = 0;
 
@@ -19820,8 +19820,9 @@ parsing_nsdmi (void)
 
    Returns the type indicated by the type-id.
 
-   In addition to this, parse any queued up omp declare simd
-   clauses and Cilk Plus SIMD-enabled function's vector attributes.
+   In addition to this, parse any queued up #pragma omp declare simd
+   clauses, Cilk Plus SIMD-enabled functions' vector attributes, and
+   #pragma acc routine clauses.
 
    QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
    function.  */
@@ -23727,6 +23728,7 @@ cp_parser_cilk_simd_fn_vector_attrs (cp_parser *parser, 
cp_token *v_token)
       parser->cilk_simd_fn_info->error_seen = false;
       parser->cilk_simd_fn_info->fndecl_seen = false;
       parser->cilk_simd_fn_info->tokens = vNULL;
+      parser->cilk_simd_fn_info->clauses = NULL_TREE;
     }
   int paren_scope = 0;
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -35729,6 +35731,9 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token 
*pragma_tok,
       data.error_seen = false;
       data.fndecl_seen = false;
       data.tokens = vNULL;
+      data.clauses = NULL_TREE;
+      /* It is safe to take the address of a local variable; it will only be
+        used while this scope is live.  */
       parser->omp_declare_simd = &data;
     }
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
@@ -35846,7 +35851,6 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser 
*parser, tree attrs)
       error ("%<#pragma omp declare simd%> not immediately followed by "
             "a single function declaration or definition");
       data->error_seen = true;
-      return attrs;
     }
   if (data->error_seen)
     return attrs;
@@ -36560,21 +36564,19 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
                        enum pragma_context context)
 {
   bool first_p = parser->oacc_routine == NULL;
-  location_t loc = pragma_tok->location;
-  cp_omp_declare_simd_data data;
+  cp_oacc_routine_data data;
   if (first_p)
     {
       data.error_seen = false;
       data.fndecl_seen = false;
       data.tokens = vNULL;
       data.clauses = NULL_TREE;
+      data.loc = pragma_tok->location;
+      /* It is safe to take the address of a local variable; it will only be
+        used while this scope is live.  */
       parser->oacc_routine = &data;
     }
 
-  tree decl = NULL_TREE;
-  /* Create a dummy claue, to record location.  */
-  tree c_head = build_omp_clause (pragma_tok->location, OMP_CLAUSE_SEQ);
-
   if (context != pragma_external)
     {
       cp_parser_error (parser, "%<#pragma acc routine%> not at file scope");
@@ -36595,7 +36597,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
            parser->oacc_routine->error_seen = true;
          cp_parser_require_pragma_eol (parser, pragma_tok);
 
-         error_at (OMP_CLAUSE_LOCATION (parser->oacc_routine->clauses),
+         error_at (parser->oacc_routine->loc,
                    "%<#pragma acc routine%> not followed by a "
                    "function declaration or definition");
 
@@ -36615,7 +36617,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
                                         /*template_p=*/NULL,
                                         /*declarator_p=*/false,
                                         /*optional_p=*/false);
-      decl = cp_parser_lookup_name_simple (parser, id, token->location);
+      tree decl = cp_parser_lookup_name_simple (parser, id, token->location);
       if (id != error_mark_node && decl == error_mark_node)
        cp_parser_name_lookup_error (parser, id, decl, NLE_NULL,
                                     token->location);
@@ -36630,20 +36632,17 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
 
       /* Build a chain of clauses.  */
       parser->lexer->in_pragma = true;
-      tree clauses = NULL_TREE;
-      clauses = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
-                                           "#pragma acc routine",
-                                           cp_lexer_peek_token
-                                           (parser->lexer));
-
-      /* Force clauses to be non-null, by attaching context to it.  */
-      clauses = tree_cons (c_head, clauses, NULL_TREE);
+      data.clauses
+       = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+                                     "#pragma acc routine",
+                                     cp_lexer_peek_token (parser->lexer));
 
       if (decl && is_overloaded_fn (decl)
          && (TREE_CODE (decl) != FUNCTION_DECL
              || DECL_FUNCTION_TEMPLATE_P  (decl)))
        {
-         error_at (loc, "%<#pragma acc routine%> names a set of overloads");
+         error_at (data.loc,
+                   "%<#pragma acc routine%> names a set of overloads");
          parser->oacc_routine = NULL;
          return;
        }
@@ -36652,7 +36651,8 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
         namespaces?  */
       if (!DECL_NAMESPACE_SCOPE_P (decl))
        {
-         error_at (loc, "%<#pragma acc routine%> does not refer to a "
+         error_at (data.loc,
+                   "%<#pragma acc routine%> does not refer to a "
                    "namespace scope function");
          parser->oacc_routine = NULL;
          return;
@@ -36660,14 +36660,12 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
 
       if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
        {
-         error_at (loc,
+         error_at (data.loc,
                    "%<#pragma acc routine%> does not refer to a function");
          parser->oacc_routine = NULL;
          return;
        }
 
-      data.clauses = clauses;
-
       cp_finalize_oacc_routine (parser, decl, false);
       data.tokens.release ();
       parser->oacc_routine = NULL;
@@ -36685,23 +36683,18 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
        = cp_token_cache_new (pragma_tok, cp_lexer_peek_token (parser->lexer));
       parser->oacc_routine->tokens.safe_push (cp);
 
-      if (first_p)
-       parser->oacc_routine->clauses = c_head;
-
       while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
        cp_parser_pragma (parser, context, NULL);
 
       if (first_p)
        {
-         /* Create an empty list of clauses.  */
-         parser->oacc_routine->clauses = tree_cons (c_head, NULL_TREE,
-                                                    NULL_TREE);
          cp_parser_declaration (parser);
 
          if (parser->oacc_routine
              && !parser->oacc_routine->error_seen
              && !parser->oacc_routine->fndecl_seen)
-           error_at (loc, "%<#pragma acc routine%> not followed by a "
+           error_at (data.loc,
+                     "%<#pragma acc routine%> not followed by a "
                      "function declaration or definition");
 
          data.tokens.release ();
@@ -36717,19 +36710,15 @@ static tree
 cp_parser_late_parsing_oacc_routine (cp_parser *parser, tree attrs)
 {
   struct cp_token_cache *ce;
-  cp_omp_declare_simd_data *data = parser->oacc_routine;
-  tree cl, clauses = parser->oacc_routine->clauses;
-  location_t loc;
+  cp_oacc_routine_data *data = parser->oacc_routine;
 
-  loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE(clauses));
-  
   if ((!data->error_seen && data->fndecl_seen)
       || data->tokens.length () != 1)
     {
-      error_at (loc, "%<#pragma acc routine%> not followed by a "
+      error_at (data->loc,
+               "%<#pragma acc routine%> not followed by a "
                "function declaration or definition");
       data->error_seen = true;
-      return attrs;
     }
   if (data->error_seen)
     return attrs;
@@ -36741,15 +36730,11 @@ cp_parser_late_parsing_oacc_routine (cp_parser 
*parser, tree attrs)
   gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA);
 
   cp_token *pragma_tok = cp_lexer_consume_token (parser->lexer);
-  cl = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+  parser->oacc_routine->clauses
+    = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
                                  "#pragma acc routine", pragma_tok);
   cp_parser_pop_lexer (parser);
 
-  tree c_head = build_omp_clause (loc, OMP_CLAUSE_SEQ);
-
-  /* Force clauses to be non-null, by attaching context to it.  */
-  parser->oacc_routine->clauses = tree_cons (c_head, cl, NULL_TREE);
-
   data->fndecl_seen = true;
   return attrs;
 }
@@ -36762,9 +36747,6 @@ cp_finalize_oacc_routine (cp_parser *parser, tree 
fndecl, bool is_defn)
 {
   if (__builtin_expect (parser->oacc_routine != NULL, 0))
     {
-      tree clauses = parser->oacc_routine->clauses;
-      location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE(clauses));
-
       if (parser->oacc_routine->error_seen)
        return;
       
@@ -36782,31 +36764,35 @@ cp_finalize_oacc_routine (cp_parser *parser, tree 
fndecl, bool is_defn)
 
       if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL)
        {
-         error_at (loc,
+         error_at (parser->oacc_routine->loc,
                    "%<#pragma acc routine%> not followed by a function "
                    "declaration or definition");
          parser->oacc_routine = NULL;
+         return;
        }
          
       if (get_oacc_fn_attrib (fndecl))
        {
-         error_at (loc, "%<#pragma acc routine%> already applied to %D",
-                   fndecl);
+         error_at (parser->oacc_routine->loc,
+                   "%<#pragma acc routine%> already applied to %D", fndecl);
          parser->oacc_routine = NULL;
+         return;
        }
 
       if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
        {
-         error_at (loc, "%<#pragma acc routine%> must be applied before %s",
+         error_at (parser->oacc_routine->loc,
+                   "%<#pragma acc routine%> must be applied before %s",
                    TREE_USED (fndecl) ? "use" : "definition");
          parser->oacc_routine = NULL;
+         return;
        }
 
-      /* Process for function attrib  */
-      tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
+      /* Process the routine's dimension clauses.  */
+      tree dims = build_oacc_routine_dims (parser->oacc_routine->clauses);
       replace_oacc_fn_attrib (fndecl, dims);
       
-      /* Add an "omp target" attribute.  */
+      /* Add an "omp declare target" attribute.  */
       DECL_ATTRIBUTES (fndecl)
        = tree_cons (get_identifier ("omp declare target"),
                     NULL_TREE, DECL_ATTRIBUTES (fndecl));
diff --git gcc/cp/parser.h gcc/cp/parser.h
index 2923378..2d3feb6 100644
--- gcc/cp/parser.h
+++ gcc/cp/parser.h
@@ -199,7 +199,8 @@ struct GTY (()) cp_parser_context {
 };
 
 
-/* Control structure for #pragma omp declare simd parsing.  */
+/* Helper data structure for parsing #pragma omp declare simd, and Cilk Plus
+   SIMD-enabled functions' vector attribute.  */
 struct cp_omp_declare_simd_data {
   bool error_seen; /* Set if error has been reported.  */
   bool fndecl_seen; /* Set if one fn decl/definition has been seen already.  */
@@ -207,6 +208,10 @@ struct cp_omp_declare_simd_data {
   tree clauses;
 };
 
+/* Helper data structure for parsing #pragma acc routine.  */
+struct cp_oacc_routine_data : cp_omp_declare_simd_data {
+  location_t loc;
+};
 
 /* The cp_parser structure represents the C++ parser.  */
 
@@ -363,18 +368,16 @@ struct GTY(()) cp_parser {
   unsigned num_template_parameter_lists;
 
   /* When parsing #pragma omp declare simd, this is a pointer to a
-     data structure with everything needed for parsing the clauses.  */
+     helper data structure.  */
   cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
 
-  /* When parsing the vector attribute in Cilk Plus SIMD-enabled function,
-     this is a pointer to data structure with everything needed for parsing
-     the clauses.  The cp_omp_declare_simd_data struct will hold all the
-     necessary information, so creating another struct for this is not
-     necessary.  */
+  /* When parsing Cilk Plus SIMD-enabled functions' vector attributes,
+     this is a pointer to a helper data structure.  */
   cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info;
 
-  /* Parsing information for #pragma acc routine.  */
-  cp_omp_declare_simd_data * GTY((skip)) oacc_routine;
+  /* When parsing #pragma acc routine, this is a pointer to a helper data
+     structure.  */
+  cp_oacc_routine_data * GTY((skip)) oacc_routine;
   
   /* Nonzero if parsing a parameter list where 'auto' should trigger an 
implicit
      template parameter.  */

Backported to gomp-4_0-branch in r239132:

commit 42de06d87fcc520a46243e9f80cc62f051798e43
Author: tschwinge <tschwinge@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Thu Aug 4 13:49:48 2016 +0000

    C/C++: Simplify handling of location information for OpenACC routine 
directives
    
    Backport trunk r239127:
    
        gcc/c/
        * c-parser.c (struct oacc_routine_data): New.
        (c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it.
        Simplify code.
        (c_finish_oacc_routine): Likewise.  Don't attach clauses to "omp
        declare target" attribute.
        gcc/cp/
        * parser.h (struct cp_omp_declare_simd_data): New.
        (struct cp_parser): Use it for oacc_routine member.
        * parser.c (cp_ensure_no_oacc_routine, cp_parser_oacc_routine)
        (cp_parser_late_parsing_oacc_routine, cp_finalize_oacc_routine):
        Use it.  Simplify code.
        (cp_parser_new): Initialize all members pointing to special
        parsing data structures.
        (cp_parser_cilk_simd_fn_vector_attrs): Initialize
        parser->cilk_simd_fn_info->clauses.
        (cp_parser_omp_declare_simd): Initialize
        parser->omp_declare_simd->clauses.
        (cp_parser_late_parsing_omp_declare_simd): Simplify code.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gomp-4_0-branch@239132 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/c/ChangeLog.gomp  |   6 +++
 gcc/c/c-parser.c      |  97 +++++++++++++++++++++++-----------------------
 gcc/cp/ChangeLog.gomp |  16 ++++++++
 gcc/cp/parser.c       | 105 +++++++++++++++++++++-----------------------------
 gcc/cp/parser.h       |  21 +++++-----
 5 files changed, 127 insertions(+), 118 deletions(-)

diff --git gcc/c/ChangeLog.gomp gcc/c/ChangeLog.gomp
index 4a4bb24..3b86603 100644
--- gcc/c/ChangeLog.gomp
+++ gcc/c/ChangeLog.gomp
@@ -1,5 +1,11 @@
 2016-08-04  Thomas Schwinge  <tho...@codesourcery.com>
 
+       Backport trunk r239127:
+       * c-parser.c (struct oacc_routine_data): New.
+       (c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it.
+       Simplify code.
+       (c_finish_oacc_routine): Likewise.
+
        Backport trunk r236639:
        * c-parser.c (c_parser_oacc_routine): Tighten syntax checks.
 
diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index 20b31dd..1aa7e70 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -1264,11 +1264,17 @@ enum c_parser_prec {
   NUM_PRECS
 };
 
+/* Helper data structure for parsing #pragma acc routine.  */
+struct oacc_routine_data {
+  tree clauses;
+  location_t loc;
+};
+
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
                                           bool, bool, tree *, vec<c_token>,
-                                          tree = NULL_TREE);
+                                          struct oacc_routine_data * = NULL);
 static void c_parser_static_assert_declaration_no_semi (c_parser *);
 static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
@@ -1360,7 +1366,7 @@ static bool c_parser_omp_target (c_parser *, enum 
pragma_context, bool *);
 static void c_parser_omp_end_declare_target (c_parser *);
 static void c_parser_omp_declare (c_parser *, enum pragma_context);
 static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
-static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
+static void c_parser_oacc_routine (c_parser *, enum pragma_context);
 
 /* These Objective-C parser functions are only ever called when
    compiling Objective-C.  */
@@ -1557,7 +1563,8 @@ c_parser_external_declaration (c_parser *parser)
 }
 
 static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
-static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
+static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool,
+                                  bool, bool);
 
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
@@ -1636,7 +1643,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                               bool nested, bool start_attr_ok,
                               tree *objc_foreach_object_declaration,
                               vec<c_token> omp_declare_simd_clauses,
-                              tree oacc_routine_clauses)
+                              struct oacc_routine_data *oacc_routine_data)
 {
   struct c_declspecs *specs;
   tree prefix_attrs;
@@ -1706,9 +1713,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
          pedwarn (here, 0, "empty declaration");
        }
       c_parser_consume_token (parser);
-      if (oacc_routine_clauses)
-       c_finish_oacc_routine (parser, NULL_TREE,
-                              oacc_routine_clauses, false, true, false);
+      if (oacc_routine_data)
+       c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false, true,
+                              false);
       return;
     }
 
@@ -1825,9 +1832,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
              || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
            c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
                                       omp_declare_simd_clauses);
-         if (oacc_routine_clauses)
-           c_finish_oacc_routine (parser, NULL_TREE,
-                                  oacc_routine_clauses,
+         if (oacc_routine_data)
+           c_finish_oacc_routine (oacc_routine_data, NULL_TREE,
                                   false, first, false);
          c_parser_skip_to_end_of_block_or_statement (parser);
          return;
@@ -1943,8 +1949,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                  init = c_parser_initializer (parser);
                  finish_init ();
                }
-             if (oacc_routine_clauses)
-               c_finish_oacc_routine (parser, d, oacc_routine_clauses,
+             if (oacc_routine_data)
+               c_finish_oacc_routine (oacc_routine_data, d,
                                       false, first, false);
              if (d != error_mark_node)
                {
@@ -1989,8 +1995,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                  if (parms)
                    temp_pop_parm_decls ();
                }
-             if (oacc_routine_clauses)
-               c_finish_oacc_routine (parser, d, oacc_routine_clauses,
+             if (oacc_routine_data)
+               c_finish_oacc_routine (oacc_routine_data, d,
                                       false, first, false);
              if (d)
                finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
@@ -2102,9 +2108,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
          || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
        c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
                                   omp_declare_simd_clauses);
-      if (oacc_routine_clauses)
-       c_finish_oacc_routine (parser, current_function_decl,
-                              oacc_routine_clauses, false, first, true);
+      if (oacc_routine_data)
+       c_finish_oacc_routine (oacc_routine_data, current_function_decl,
+                              false, first, true);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
       fnbody = c_parser_compound_statement (parser);
@@ -14155,10 +14161,10 @@ static void
 c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
 {
   tree decl = NULL_TREE;
-  /* Create a dummy clause, to record the location.  */
-  tree c_head = build_omp_clause (c_parser_peek_token (parser)->location,
-                                 OMP_CLAUSE_ERROR);
-
+  oacc_routine_data data;
+  data.clauses = NULL_TREE;
+  data.loc = c_parser_peek_token (parser)->location;
+  
   if (context != pragma_external)
     c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
 
@@ -14192,58 +14198,53 @@ c_parser_oacc_routine (c_parser *parser, enum 
pragma_context context)
 
   /* Build a chain of clauses.  */
   parser->in_pragma = true;
-  tree clauses = c_parser_oacc_all_clauses
-    (parser, OACC_ROUTINE_CLAUSE_MASK, "#pragma acc routine",
-     OACC_ROUTINE_CLAUSE_DEVICE_TYPE_MASK);
-  /* Prepend the dummy clause.  */
-  OMP_CLAUSE_CHAIN (c_head) = clauses;
-  clauses = c_head;
-  
+  data.clauses
+    = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+                                "#pragma acc routine",
+                                OACC_ROUTINE_CLAUSE_DEVICE_TYPE_MASK);
+
   if (decl)
-    c_finish_oacc_routine (parser, decl, clauses, true, true, false);
+    c_finish_oacc_routine (&data, decl, true, true, false);
   else if (c_parser_peek_token (parser)->type == CPP_PRAGMA)
     /* This will emit an error.  */
-    c_finish_oacc_routine (parser, NULL_TREE, clauses, false, true, false);
+    c_finish_oacc_routine (&data, NULL_TREE, false, true, false);
   else
     c_parser_declaration_or_fndef (parser, true, false, false, false,
-                                  true, NULL, vNULL, clauses);
+                                  true, NULL, vNULL, &data);
 }
 
-/* Finalize an OpenACC routine pragma, applying it to FNDECL.  CLAUSES
-   are the parsed clauses.  IS_DEFN is true if we're applying it to
-   the definition (so expect FNDEF to look somewhat defined.  */
+/* Finalize an OpenACC routine pragma, applying it to FNDECL.
+   IS_DEFN is true if we're applying it to the definition.  */
 
 static void
-c_finish_oacc_routine (c_parser *ARG_UNUSED (parser), tree fndecl,
-                      tree clauses, bool named, bool first, bool is_defn)
+c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
+                      bool named, bool first, bool is_defn)
 {
-  location_t loc = OMP_CLAUSE_LOCATION (clauses);
-  /* Get rid of the dummy clause.  */
-  clauses = OMP_CLAUSE_CHAIN (clauses);
-
   if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL || !first)
     {
       if (fndecl != error_mark_node)
-       error_at (loc, "%<#pragma acc routine%> %s",
+       error_at (data->loc, "%<#pragma acc routine%> %s",
                  named ? "does not refer to a function"
                  : "not followed by single function");
       return;
     }
 
   if (get_oacc_fn_attrib (fndecl))
-    error_at (loc, "%<#pragma acc routine%> already applied to %D", fndecl);
+    error_at (data->loc,
+             "%<#pragma acc routine%> already applied to %D", fndecl);
 
   if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
-    error_at (loc, "%<#pragma acc routine%> must be applied before %s",
+    error_at (data->loc, "%<#pragma acc routine%> must be applied before %s",
              TREE_USED (fndecl) ? "use" : "definition");
 
-  /* Process for function attrib  */
-  tree dims = build_oacc_routine_dims (clauses);
+  /* Process the routine's dimension clauses.  */
+  tree dims = build_oacc_routine_dims (data->clauses);
   replace_oacc_fn_attrib (fndecl, dims);
 
-  /* Also add an "omp declare target" attribute, with clauses.  */
-  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("omp declare target"),
-                                       clauses, DECL_ATTRIBUTES (fndecl));
+  /* Add an "omp declare target" attribute.  */
+  DECL_ATTRIBUTES (fndecl)
+    = tree_cons (get_identifier ("omp declare target"),
+                data->clauses, DECL_ATTRIBUTES (fndecl));
 }
 
 /* OpenACC 2.0:
diff --git gcc/cp/ChangeLog.gomp gcc/cp/ChangeLog.gomp
index cc51940..1864ea5 100644
--- gcc/cp/ChangeLog.gomp
+++ gcc/cp/ChangeLog.gomp
@@ -1,3 +1,19 @@
+2016-08-04  Thomas Schwinge  <tho...@codesourcery.com>
+
+       Backport trunk r239127:
+       * parser.h (struct cp_omp_declare_simd_data): New.
+       (struct cp_parser): Use it for oacc_routine member.
+       * parser.c (cp_ensure_no_oacc_routine, cp_parser_oacc_routine)
+       (cp_parser_late_parsing_oacc_routine, cp_finalize_oacc_routine):
+       Use it.  Simplify code.
+       (cp_parser_new): Initialize all members pointing to special
+       parsing data structures.
+       (cp_parser_cilk_simd_fn_vector_attrs): Initialize
+       parser->cilk_simd_fn_info->clauses.
+       (cp_parser_omp_declare_simd): Initialize
+       parser->omp_declare_simd->clauses.
+       (cp_parser_late_parsing_omp_declare_simd): Simplify code.
+
 2016-07-15  Cesar Philippidis  <ce...@codesourcery.com>
 
        Backport from trunk:
diff --git gcc/cp/parser.c gcc/cp/parser.c
index ebeaf36..282d28f 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -1381,8 +1381,7 @@ cp_ensure_no_oacc_routine (cp_parser *parser)
 {
   if (parser->oacc_routine && !parser->oacc_routine->error_seen)
     {
-      /* The first clause is a dummy, providing location information.  */
-      error_at (OMP_CLAUSE_LOCATION (parser->oacc_routine->clauses),
+      error_at (parser->oacc_routine->loc,
                "%<#pragma acc routine%> not followed by a function "
                "declaration or definition");
       parser->oacc_routine = NULL;
@@ -3755,15 +3754,17 @@ cp_parser_new (void)
   /* No template parameters apply.  */
   parser->num_template_parameter_lists = 0;
 
+  /* Special parsing data structures.  */
+  parser->omp_declare_simd = NULL;
+  parser->cilk_simd_fn_info = NULL;
+  parser->oacc_routine = NULL;
+
   /* Not declaring an implicit function template.  */
   parser->auto_is_implicit_function_template_parm_p = false;
   parser->fully_implicit_function_template_p = false;
   parser->implicit_template_parms = 0;
   parser->implicit_template_scope = 0;
 
-  /* Active OpenACC routine clauses.  */
-  parser->oacc_routine = NULL;
-
   /* Allow constrained-type-specifiers. */
   parser->prevent_constrained_type_specifiers = 0;
 
@@ -19764,8 +19765,9 @@ parsing_nsdmi (void)
 
    Returns the type indicated by the type-id.
 
-   In addition to this, parse any queued up omp declare simd
-   clauses and Cilk Plus SIMD-enabled function's vector attributes.
+   In addition to this, parse any queued up #pragma omp declare simd
+   clauses, Cilk Plus SIMD-enabled functions' vector attributes, and
+   #pragma acc routine clauses.
 
    QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
    function.  */
@@ -23642,6 +23644,7 @@ cp_parser_cilk_simd_fn_vector_attrs (cp_parser *parser, 
cp_token *v_token)
       parser->cilk_simd_fn_info->error_seen = false;
       parser->cilk_simd_fn_info->fndecl_seen = false;
       parser->cilk_simd_fn_info->tokens = vNULL;
+      parser->cilk_simd_fn_info->clauses = NULL_TREE;
     }
   int paren_scope = 0;
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -35784,6 +35787,9 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token 
*pragma_tok,
       data.error_seen = false;
       data.fndecl_seen = false;
       data.tokens = vNULL;
+      data.clauses = NULL_TREE;
+      /* It is safe to take the address of a local variable; it will only be
+        used while this scope is live.  */
       parser->omp_declare_simd = &data;
     }
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
@@ -35901,7 +35907,6 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser 
*parser, tree attrs)
       error ("%<#pragma omp declare simd%> not immediately followed by "
             "a single function declaration or definition");
       data->error_seen = true;
-      return attrs;
     }
   if (data->error_seen)
     return attrs;
@@ -36625,20 +36630,19 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
                        enum pragma_context context)
 {
   bool first_p = parser->oacc_routine == NULL;
-  location_t loc = pragma_tok->location;
-  cp_omp_declare_simd_data data;
+  cp_oacc_routine_data data;
   if (first_p)
     {
       data.error_seen = false;
       data.fndecl_seen = false;
       data.tokens = vNULL;
       data.clauses = NULL_TREE;
+      data.loc = pragma_tok->location;
+      /* It is safe to take the address of a local variable; it will only be
+        used while this scope is live.  */
       parser->oacc_routine = &data;
     }
 
-  /* Create a dummy clause, to record the location.  */
-  tree c_head = build_omp_clause (pragma_tok->location, OMP_CLAUSE_ERROR);
-
   if (context != pragma_external)
     {
       cp_parser_error (parser, "%<#pragma acc routine%> not at file scope");
@@ -36660,8 +36664,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
            parser->oacc_routine->error_seen = true;
          cp_parser_require_pragma_eol (parser, pragma_tok);
 
-         /* The first clause is a dummy, providing location information.  */
-         error_at (OMP_CLAUSE_LOCATION (parser->oacc_routine->clauses),
+         error_at (parser->oacc_routine->loc,
                    "%<#pragma acc routine%> not followed by a "
                    "function declaration or definition");
 
@@ -36696,34 +36699,29 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
 
       /* Build a chain of clauses.  */
       parser->lexer->in_pragma = true;
-      tree clauses
+      data.clauses
        = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
                                      "#pragma acc routine",
                                      cp_lexer_peek_token (parser->lexer));
 
-      /* Prepend the dummy clause.  */
-      OMP_CLAUSE_CHAIN (c_head) = clauses;
-      clauses = c_head;
-
       if (decl && is_overloaded_fn (decl)
          && (TREE_CODE (decl) != FUNCTION_DECL
              || DECL_FUNCTION_TEMPLATE_P  (decl)))
        {
-         error_at (loc, "%<#pragma acc routine%> names a set of overloads");
+         error_at (data.loc,
+                   "%<#pragma acc routine%> names a set of overloads");
          parser->oacc_routine = NULL;
          return;
        }
 
       if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
        {
-         error_at (loc,
+         error_at (data.loc,
                    "%<#pragma acc routine%> does not refer to a function");
          parser->oacc_routine = NULL;
          return;
        }
 
-      data.clauses = clauses;
-
       cp_finalize_oacc_routine (parser, decl, false);
       data.tokens.release ();
       parser->oacc_routine = NULL;
@@ -36741,21 +36739,18 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token 
*pragma_tok,
        = cp_token_cache_new (pragma_tok, cp_lexer_peek_token (parser->lexer));
       parser->oacc_routine->tokens.safe_push (cp);
 
-      if (first_p)
-       parser->oacc_routine->clauses = c_head;
-
       while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
        cp_parser_pragma (parser, context, NULL);
 
       if (first_p)
        {
-         parser->oacc_routine->clauses = c_head;
          cp_parser_declaration (parser);
 
          if (parser->oacc_routine
              && !parser->oacc_routine->error_seen
              && !parser->oacc_routine->fndecl_seen)
-           error_at (loc, "%<#pragma acc routine%> not followed by a "
+           error_at (data.loc,
+                     "%<#pragma acc routine%> not followed by a "
                      "function declaration or definition");
 
          data.tokens.release ();
@@ -36771,21 +36766,15 @@ static tree
 cp_parser_late_parsing_oacc_routine (cp_parser *parser, tree attrs)
 {
   struct cp_token_cache *ce;
-  cp_omp_declare_simd_data *data = parser->oacc_routine;
-  tree cl, clauses = parser->oacc_routine->clauses;
-
-  /* The first clause is a dummy, providing location information.  */
-  location_t loc = OMP_CLAUSE_LOCATION (clauses);
-  /* Get rid of it now.  */
-  clauses = OMP_CLAUSE_CHAIN (clauses);
+  cp_oacc_routine_data *data = parser->oacc_routine;
 
   if ((!data->error_seen && data->fndecl_seen)
       || data->tokens.length () != 1)
     {
-      error_at (loc, "%<#pragma acc routine%> not followed by a "
+      error_at (data->loc,
+               "%<#pragma acc routine%> not followed by a "
                "function declaration or definition");
       data->error_seen = true;
-      return attrs;
     }
   if (data->error_seen)
     return attrs;
@@ -36797,18 +36786,12 @@ cp_parser_late_parsing_oacc_routine (cp_parser 
*parser, tree attrs)
   gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA);
 
   cp_token *pragma_tok = cp_lexer_consume_token (parser->lexer);
-  cl = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
-                                  "#pragma acc routine", pragma_tok,
+  parser->oacc_routine->clauses
+    = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+                                 "#pragma acc routine", pragma_tok,
                                   OACC_ROUTINE_CLAUSE_DEVICE_TYPE_MASK);
   cp_parser_pop_lexer (parser);
 
-  /* Create a dummy clause, to record the location.  */
-  tree c_head = build_omp_clause (loc, OMP_CLAUSE_ERROR);
-
-  /* Prepend the dummy clause.  */
-  OMP_CLAUSE_CHAIN (c_head) = cl;
-  parser->oacc_routine->clauses = c_head;
-
   data->fndecl_seen = true;
   return attrs;
 }
@@ -36821,11 +36804,6 @@ cp_finalize_oacc_routine (cp_parser *parser, tree 
fndecl, bool is_defn)
 {
   if (__builtin_expect (parser->oacc_routine != NULL, 0))
     {
-      tree clauses = parser->oacc_routine->clauses;
-      location_t loc = OMP_CLAUSE_LOCATION (clauses);
-      /* Get rid of the dummy clause.  */
-      clauses = OMP_CLAUSE_CHAIN (clauses);
-
       if (parser->oacc_routine->error_seen)
        return;
       
@@ -36843,28 +36821,32 @@ cp_finalize_oacc_routine (cp_parser *parser, tree 
fndecl, bool is_defn)
 
       if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL)
        {
-         error_at (loc,
+         error_at (parser->oacc_routine->loc,
                    "%<#pragma acc routine%> not followed by a function "
                    "declaration or definition");
          parser->oacc_routine = NULL;
+         return;
        }
          
       if (get_oacc_fn_attrib (fndecl))
        {
-         error_at (loc, "%<#pragma acc routine%> already applied to %D",
-                   fndecl);
+         error_at (parser->oacc_routine->loc,
+                   "%<#pragma acc routine%> already applied to %D", fndecl);
          parser->oacc_routine = NULL;
+         return;
        }
 
       if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
        {
-         error_at (loc, "%<#pragma acc routine%> must be applied before %s",
+         error_at (parser->oacc_routine->loc,
+                   "%<#pragma acc routine%> must be applied before %s",
                    TREE_USED (fndecl) ? "use" : "definition");
          parser->oacc_routine = NULL;
+         return;
        }
 
       /* Process the bind clause, if present.  */
-      for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+      for (tree c = parser->oacc_routine->clauses; c; c = OMP_CLAUSE_CHAIN (c))
        {
          if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_BIND)
            continue;
@@ -36880,6 +36862,7 @@ cp_finalize_oacc_routine (cp_parser *parser, tree 
fndecl, bool is_defn)
              error_at (OMP_CLAUSE_LOCATION (c),
                        "bind identifier %qE is not compatible with "
                        "function %qE", bind_decl, fndecl);
+             parser->oacc_routine = NULL;
              return;
            }
 
@@ -36891,14 +36874,14 @@ cp_finalize_oacc_routine (cp_parser *parser, tree 
fndecl, bool is_defn)
          break;
        }
 
-      /* Process for function attrib  */
-      tree dims = build_oacc_routine_dims (clauses);
+      /* Process the routine's dimension clauses.  */
+      tree dims = build_oacc_routine_dims (parser->oacc_routine->clauses);
       replace_oacc_fn_attrib (fndecl, dims);
       
-      /* Also add an "omp declare target" attribute, with clauses.  */
+      /* Add an "omp declare target" attribute.  */
       DECL_ATTRIBUTES (fndecl)
        = tree_cons (get_identifier ("omp declare target"),
-                    clauses, DECL_ATTRIBUTES (fndecl));
+                    parser->oacc_routine->clauses, DECL_ATTRIBUTES (fndecl));
     }
 }
 
diff --git gcc/cp/parser.h gcc/cp/parser.h
index ccbace9..a777a84 100644
--- gcc/cp/parser.h
+++ gcc/cp/parser.h
@@ -199,7 +199,8 @@ struct GTY (()) cp_parser_context {
 };
 
 
-/* Control structure for #pragma omp declare simd parsing.  */
+/* Helper data structure for parsing #pragma omp declare simd, and Cilk Plus
+   SIMD-enabled functions' vector attribute.  */
 struct cp_omp_declare_simd_data {
   bool error_seen; /* Set if error has been reported.  */
   bool fndecl_seen; /* Set if one fn decl/definition has been seen already.  */
@@ -207,6 +208,10 @@ struct cp_omp_declare_simd_data {
   tree clauses;
 };
 
+/* Helper data structure for parsing #pragma acc routine.  */
+struct cp_oacc_routine_data : cp_omp_declare_simd_data {
+  location_t loc;
+};
 
 /* The cp_parser structure represents the C++ parser.  */
 
@@ -363,18 +368,16 @@ struct GTY(()) cp_parser {
   unsigned num_template_parameter_lists;
 
   /* When parsing #pragma omp declare simd, this is a pointer to a
-     data structure with everything needed for parsing the clauses.  */
+     helper data structure.  */
   cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
 
-  /* When parsing the vector attribute in Cilk Plus SIMD-enabled function,
-     this is a pointer to data structure with everything needed for parsing
-     the clauses.  The cp_omp_declare_simd_data struct will hold all the
-     necessary information, so creating another struct for this is not
-     necessary.  */
+  /* When parsing Cilk Plus SIMD-enabled functions' vector attributes,
+     this is a pointer to a helper data structure.  */
   cp_omp_declare_simd_data * GTY((skip)) cilk_simd_fn_info;
 
-  /* Parsing information for #pragma acc routine.  */
-  cp_omp_declare_simd_data * GTY((skip)) oacc_routine;
+  /* When parsing #pragma acc routine, this is a pointer to a helper data
+     structure.  */
+  cp_oacc_routine_data * GTY((skip)) oacc_routine;
   
   /* Nonzero if parsing a parameter list where 'auto' should trigger an 
implicit
      template parameter.  */


Grüße
 Thomas

Attachment: signature.asc
Description: PGP signature

Reply via email to