Commit ae9281fc by Thomas Schwinge Committed by Thomas Schwinge

Rework C/C++ OpenACC routine parsing

	gcc/c/
	* c-parser.c (struct oacc_routine_data): Add error_seen and
	fndecl_seen members.
	(c_finish_oacc_routine): Use these.
	(c_parser_declaration_or_fndef): Adjust.
	(c_parser_oacc_routine): Likewise.  Support more C language
	constructs, and improve diagnostics.  Move pragma context
	checking...
	(c_parser_pragma): ... here.
	gcc/cp/
	* parser.c (cp_ensure_no_oacc_routine): Improve diagnostics.
	(cp_parser_late_parsing_cilk_simd_fn_info): Fix diagnostics.
	(cp_parser_late_parsing_oacc_routine, cp_finalize_oacc_routine):
	Simplify code, and improve diagnostics.
	(cp_parser_oacc_routine): Likewise.  Move pragma context
	checking...
	(cp_parser_pragma): ... here.
	gcc/testsuite/
	* c-c++-common/goacc/routine-5.c: Update.

From-SVN: r239128
parent 0b212d8c
2016-08-04 Thomas Schwinge <thomas@codesourcery.com> 2016-08-04 Thomas Schwinge <thomas@codesourcery.com>
* c-parser.c (struct oacc_routine_data): Add error_seen and
fndecl_seen members.
(c_finish_oacc_routine): Use these.
(c_parser_declaration_or_fndef): Adjust.
(c_parser_oacc_routine): Likewise. Support more C language
constructs, and improve diagnostics. Move pragma context
checking...
(c_parser_pragma): ... here.
* c-parser.c (struct oacc_routine_data): New. * c-parser.c (struct oacc_routine_data): New.
(c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it. (c_parser_declaration_or_fndef, c_parser_oacc_routine): Use it.
Simplify code. Simplify code.
......
...@@ -1276,6 +1276,8 @@ enum c_parser_prec { ...@@ -1276,6 +1276,8 @@ enum c_parser_prec {
/* Helper data structure for parsing #pragma acc routine. */ /* Helper data structure for parsing #pragma acc routine. */
struct oacc_routine_data { struct oacc_routine_data {
bool error_seen; /* Set if error has been reported. */
bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
tree clauses; tree clauses;
location_t loc; location_t loc;
}; };
...@@ -1568,8 +1570,7 @@ c_parser_external_declaration (c_parser *parser) ...@@ -1568,8 +1570,7 @@ 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_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
static void c_finish_oacc_routine (struct oacc_routine_data *, tree, 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 /* 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 6.7, 6.9.1). If FNDEF_OK is true, a function definition is
...@@ -1754,8 +1755,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -1754,8 +1755,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
} }
c_parser_consume_token (parser); c_parser_consume_token (parser);
if (oacc_routine_data) if (oacc_routine_data)
c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false, true, c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
false);
return; return;
} }
...@@ -1853,7 +1853,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -1853,7 +1853,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
prefix_attrs = specs->attrs; prefix_attrs = specs->attrs;
all_prefix_attrs = prefix_attrs; all_prefix_attrs = prefix_attrs;
specs->attrs = NULL_TREE; specs->attrs = NULL_TREE;
for (bool first = true;; first = false) while (true)
{ {
struct c_declarator *declarator; struct c_declarator *declarator;
bool dummy = false; bool dummy = false;
...@@ -1873,8 +1873,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -1873,8 +1873,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE, c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses); omp_declare_simd_clauses);
if (oacc_routine_data) if (oacc_routine_data)
c_finish_oacc_routine (oacc_routine_data, NULL_TREE, c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
false, first, false);
c_parser_skip_to_end_of_block_or_statement (parser); c_parser_skip_to_end_of_block_or_statement (parser);
return; return;
} }
...@@ -1990,8 +1989,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -1990,8 +1989,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
finish_init (); finish_init ();
} }
if (oacc_routine_data) if (oacc_routine_data)
c_finish_oacc_routine (oacc_routine_data, d, c_finish_oacc_routine (oacc_routine_data, d, false);
false, first, false);
if (d != error_mark_node) if (d != error_mark_node)
{ {
maybe_warn_string_init (init_loc, TREE_TYPE (d), init); maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
...@@ -2036,8 +2034,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -2036,8 +2034,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
temp_pop_parm_decls (); temp_pop_parm_decls ();
} }
if (oacc_routine_data) if (oacc_routine_data)
c_finish_oacc_routine (oacc_routine_data, d, c_finish_oacc_routine (oacc_routine_data, d, false);
false, first, false);
if (d) if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name); NULL_TREE, asm_name);
...@@ -2149,8 +2146,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -2149,8 +2146,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses); omp_declare_simd_clauses);
if (oacc_routine_data) if (oacc_routine_data)
c_finish_oacc_routine (oacc_routine_data, current_function_decl, c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
false, first, true);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location; = c_parser_peek_token (parser)->location;
fnbody = c_parser_compound_statement (parser); fnbody = c_parser_compound_statement (parser);
...@@ -10123,6 +10119,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) ...@@ -10123,6 +10119,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
return false; return false;
case PRAGMA_OACC_ROUTINE: case PRAGMA_OACC_ROUTINE:
if (context != pragma_external)
{
error_at (c_parser_peek_token (parser)->location,
"%<#pragma acc routine%> must be at file scope");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
c_parser_oacc_routine (parser, context); c_parser_oacc_routine (parser, context);
return false; return false;
...@@ -14030,29 +14033,32 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser, ...@@ -14030,29 +14033,32 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
static void static void
c_parser_oacc_routine (c_parser *parser, enum pragma_context context) c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
{ {
tree decl = NULL_TREE; gcc_checking_assert (context == pragma_external);
oacc_routine_data data; oacc_routine_data data;
data.error_seen = false;
data.fndecl_seen = false;
data.clauses = NULL_TREE; data.clauses = NULL_TREE;
data.loc = c_parser_peek_token (parser)->location; data.loc = c_parser_peek_token (parser)->location;
if (context != pragma_external)
c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
c_parser_consume_pragma (parser); c_parser_consume_pragma (parser);
/* Scan for optional '( name )'. */ /* Look for optional '( name )'. */
if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN) if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{ {
c_parser_consume_token (parser); c_parser_consume_token (parser); /* '(' */
c_token *token = c_parser_peek_token (parser); tree decl = NULL_TREE;
if (token->type == CPP_NAME && (token->id_kind == C_ID_ID c_token *name_token = c_parser_peek_token (parser);
|| token->id_kind == C_ID_TYPENAME)) location_t name_loc = name_token->location;
if (name_token->type == CPP_NAME
&& (name_token->id_kind == C_ID_ID
|| name_token->id_kind == C_ID_TYPENAME))
{ {
decl = lookup_name (token->value); decl = lookup_name (name_token->value);
if (!decl) if (!decl)
error_at (token->location, "%qE has not been declared", error_at (name_loc,
token->value); "%qE has not been declared", name_token->value);
c_parser_consume_token (parser); c_parser_consume_token (parser);
} }
else else
...@@ -14064,22 +14070,56 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context) ...@@ -14064,22 +14070,56 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
c_parser_skip_to_pragma_eol (parser, false); c_parser_skip_to_pragma_eol (parser, false);
return; return;
} }
data.clauses
= c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
"#pragma acc routine");
if (TREE_CODE (decl) != FUNCTION_DECL)
{
error_at (name_loc, "%qD does not refer to a function", decl);
return;
}
c_finish_oacc_routine (&data, decl, false);
} }
else /* No optional '( name )'. */
{
data.clauses
= c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
"#pragma acc routine");
/* Build a chain of clauses. */ /* Emit a helpful diagnostic if there's another pragma following this
parser->in_pragma = true; one. Also don't allow a static assertion declaration, as in the
data.clauses following we'll just parse a *single* "declaration or function
= c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK, definition", and the static assertion counts an one. */
"#pragma acc routine"); if (c_parser_next_token_is (parser, CPP_PRAGMA)
|| c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
if (decl) {
c_finish_oacc_routine (&data, decl, true, true, false); error_at (data.loc,
else if (c_parser_peek_token (parser)->type == CPP_PRAGMA) "%<#pragma acc routine%> not immediately followed by"
/* This will emit an error. */ " function declaration or definition");
c_finish_oacc_routine (&data, NULL_TREE, false, true, false); /* ..., and then just keep going. */
else return;
c_parser_declaration_or_fndef (parser, true, false, false, false, }
true, NULL, vNULL, &data);
/* We only have to consider the pragma_external case here. */
if (c_parser_next_token_is (parser, CPP_KEYWORD)
&& c_parser_peek_token (parser)->keyword == RID_EXTENSION)
{
int ext = disable_extension_diagnostics ();
do
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_KEYWORD)
&& c_parser_peek_token (parser)->keyword == RID_EXTENSION);
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
NULL, vNULL, &data);
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
NULL, vNULL, &data);
}
} }
/* Finalize an OpenACC routine pragma, applying it to FNDECL. /* Finalize an OpenACC routine pragma, applying it to FNDECL.
...@@ -14087,24 +14127,46 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context) ...@@ -14087,24 +14127,46 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
static void static void
c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl, c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
bool named, bool first, bool is_defn) bool is_defn)
{ {
if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL || !first) /* Keep going if we're in error reporting mode. */
if (data->error_seen
|| fndecl == error_mark_node)
return;
if (data->fndecl_seen)
{ {
if (fndecl != error_mark_node) error_at (data->loc,
error_at (data->loc, "%<#pragma acc routine%> %s", "%<#pragma acc routine%> not immediately followed by"
named ? "does not refer to a function" " a single function declaration or definition");
: "not followed by single function"); data->error_seen = true;
return;
}
if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
{
error_at (data->loc,
"%<#pragma acc routine%> not immediately followed by"
" function declaration or definition");
data->error_seen = true;
return; return;
} }
if (get_oacc_fn_attrib (fndecl)) if (get_oacc_fn_attrib (fndecl))
error_at (data->loc, {
"%<#pragma acc routine%> already applied to %D", fndecl); error_at (data->loc,
"%<#pragma acc routine%> already applied to %qD", fndecl);
data->error_seen = true;
return;
}
if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl))) if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
error_at (data->loc, "%<#pragma acc routine%> must be applied before %s", {
TREE_USED (fndecl) ? "use" : "definition"); error_at (data->loc,
"%<#pragma acc routine%> must be applied before %s",
TREE_USED (fndecl) ? "use" : "definition");
data->error_seen = true;
return;
}
/* Process the routine's dimension clauses. */ /* Process the routine's dimension clauses. */
tree dims = build_oacc_routine_dims (data->clauses); tree dims = build_oacc_routine_dims (data->clauses);
...@@ -14114,6 +14176,9 @@ c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl, ...@@ -14114,6 +14176,9 @@ c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
DECL_ATTRIBUTES (fndecl) DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("omp declare target"), = tree_cons (get_identifier ("omp declare target"),
NULL_TREE, DECL_ATTRIBUTES (fndecl)); NULL_TREE, DECL_ATTRIBUTES (fndecl));
/* Remember that we've used this "#pragma acc routine". */
data->fndecl_seen = true;
} }
/* OpenACC 2.0: /* OpenACC 2.0:
......
2016-08-04 Thomas Schwinge <thomas@codesourcery.com> 2016-08-04 Thomas Schwinge <thomas@codesourcery.com>
* parser.c (cp_ensure_no_oacc_routine): Improve diagnostics.
(cp_parser_late_parsing_cilk_simd_fn_info): Fix diagnostics.
(cp_parser_late_parsing_oacc_routine, cp_finalize_oacc_routine):
Simplify code, and improve diagnostics.
(cp_parser_oacc_routine): Likewise. Move pragma context
checking...
(cp_parser_pragma): ... here.
* parser.h (struct cp_omp_declare_simd_data): New. * parser.h (struct cp_omp_declare_simd_data): New.
(struct cp_parser): Use it for oacc_routine member. (struct cp_parser): Use it for oacc_routine member.
* parser.c (cp_ensure_no_oacc_routine, cp_parser_oacc_routine) * parser.c (cp_ensure_no_oacc_routine, cp_parser_oacc_routine)
......
2016-08-04 Thomas Schwinge <thomas@codesourcery.com>
* c-c++-common/goacc/routine-5.c: Update.
2016-08-04 Bernd Edlinger <bernd.edlinger@hotmail.de> 2016-08-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR rtl-optimization/70903 PR rtl-optimization/70903
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment