diff mbox

C/C++: Simplify handling of location information for OpenACC routine directives

Message ID 87poqhnb39.fsf@hertz.schwinge.homeip.net
State New
Headers show

Commit Message

Thomas Schwinge July 13, 2016, 9:25 a.m. UTC
Hi!

Working on something else regarding the C/C++ OpenACC routine directive,
I couldn't but untangle that arcane location_t handling, currently using
a dummy OMP_CLAUSE_SEQ.  Along the way, I also updated some comments, and
simplified some code.  OK for trunk?  (Another C/C++ OpenACC routine
cleanup patch is emerging, depending on this one.)

commit 9ae5f6d868db428888b585de8a1d5ec3c2746619
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Fri Jul 8 18:30:45 2016 +0200

    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.
---
 gcc/c/c-parser.c |  86 ++++++++++++++++++++++----------------------
 gcc/cp/parser.c  | 108 ++++++++++++++++++++++++-------------------------------
 gcc/cp/parser.h  |  21 ++++++-----
 3 files changed, 103 insertions(+), 112 deletions(-)



Grüße
 Thomas

Comments

Thomas Schwinge July 20, 2016, 11:50 a.m. UTC | #1
Hi!

Ping.

On Wed, 13 Jul 2016 11:25:46 +0200, I wrote:
> Working on something else regarding the C/C++ OpenACC routine directive,
> I couldn't but untangle that arcane location_t handling, currently using
> a dummy OMP_CLAUSE_SEQ.  Along the way, I also updated some comments, and
> simplified some code.  OK for trunk?  (Another C/C++ OpenACC routine
> cleanup patch is emerging, depending on this one.)
> 
> commit 9ae5f6d868db428888b585de8a1d5ec3c2746619
> Author: Thomas Schwinge <thomas@codesourcery.com>
> Date:   Fri Jul 8 18:30:45 2016 +0200
> 
>     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.
> ---
>  gcc/c/c-parser.c |  86 ++++++++++++++++++++++----------------------
>  gcc/cp/parser.c  | 108 ++++++++++++++++++++++++-------------------------------
>  gcc/cp/parser.h  |  21 ++++++-----
>  3 files changed, 103 insertions(+), 112 deletions(-)
> 
> diff --git gcc/c/c-parser.c gcc/c/c-parser.c
> index 1a50dea..cc9ee59 100644
> --- gcc/c/c-parser.c
> +++ gcc/c/c-parser.c
> @@ -1271,11 +1271,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,
> @@ -1367,7 +1373,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.  */
> @@ -1559,7 +1565,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
> @@ -1638,7 +1645,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;
> @@ -1743,9 +1750,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;
>      }
>  
> @@ -1862,9 +1869,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;
> @@ -1980,8 +1986,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)
>  		{
> @@ -2026,8 +2032,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,
> @@ -2139,9 +2145,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);
> @@ -14030,9 +14036,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");
> @@ -14067,56 +14073,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/parser.c gcc/cp/parser.c
> index ef35aa9..28417d8 100644
> --- gcc/cp/parser.c
> +++ gcc/cp/parser.c
> @@ -1382,10 +1382,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;
>      }
> @@ -3754,15 +3752,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;
>  
> @@ -19778,8 +19778,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.  */
> @@ -23685,6 +23686,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))
> @@ -35653,6 +35655,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)
> @@ -35770,7 +35775,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;
> @@ -36484,21 +36488,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");
> @@ -36519,7 +36521,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");
>  
> @@ -36539,7 +36541,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);
> @@ -36554,20 +36556,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;
>  	}
> @@ -36576,7 +36575,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;
> @@ -36584,14 +36584,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;
> @@ -36609,23 +36607,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 ();
> @@ -36641,19 +36634,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;
> @@ -36665,15 +36654,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;
>  }
> @@ -36686,9 +36671,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;
>        
> @@ -36706,31 +36688,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 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
diff mbox

Patch

diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index 1a50dea..cc9ee59 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -1271,11 +1271,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,
@@ -1367,7 +1373,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.  */
@@ -1559,7 +1565,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
@@ -1638,7 +1645,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;
@@ -1743,9 +1750,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;
     }
 
@@ -1862,9 +1869,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;
@@ -1980,8 +1986,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)
 		{
@@ -2026,8 +2032,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,
@@ -2139,9 +2145,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);
@@ -14030,9 +14036,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");
@@ -14067,56 +14073,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/parser.c gcc/cp/parser.c
index ef35aa9..28417d8 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -1382,10 +1382,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;
     }
@@ -3754,15 +3752,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;
 
@@ -19778,8 +19778,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.  */
@@ -23685,6 +23686,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))
@@ -35653,6 +35655,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)
@@ -35770,7 +35775,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;
@@ -36484,21 +36488,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");
@@ -36519,7 +36521,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");
 
@@ -36539,7 +36541,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);
@@ -36554,20 +36556,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;
 	}
@@ -36576,7 +36575,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;
@@ -36584,14 +36584,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;
@@ -36609,23 +36607,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 ();
@@ -36641,19 +36634,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;
@@ -36665,15 +36654,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;
 }
@@ -36686,9 +36671,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;
       
@@ -36706,31 +36688,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 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.  */