I've committed this patch to rectify the misinterpretation of the specification.
The pragma comes in two forms:
#pragma acc routine <clauses>
fn-decl-or-defn
and
#pragma acc routine (name) <clauses>
The latter form names a function already in scope, which makes it fairly
straight forwards. However, the current implentation was such that 'name' need
not be in scope -- in essence permitting forward reference to an undeclared
entity. No other part of C permits this, so such an interpretation of the
openacc spec must be wrong. I think the confusion comes from interpreting
The routine directive with a name may appear anywhere
that a function prototype is allowed and applies to the function in that scope
with that name,
but must appear before any definition or use of that function.
to mean the function could be declared after the pragma. But that's not what it
is saying -- merely that the pragma must appear before definition or use (we
don't check that constraint, it's immaterial to this immplementation), not
declaration. And the usual interpretation of 'in that scope' is an already
declared object.
I'll fix up the C++ parser next and then commit my testcases.
nathan
2015-08-15 Nathan Sidwell <nat...@codesourcery.com>
c/
* c-parser.c (struct c_parser): Remove oacc_routines field.
(c_parser_declaration_or_fndef): Remove 'named' parameter. Adjust
all callers. Adjust c_finish_oacc_routine calls.
(c_parser_oacc_routine): Reimplement.
(c_finish_oacc_routine): Reimplement.
testsuite/
* c-c++-common/goacc/dtype-1.c: Remove bogus routine tests.
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c (revision 226911)
+++ gcc/c/c-parser.c (working copy)
@@ -225,10 +225,6 @@ typedef struct GTY(()) c_parser {
/* Buffer to hold all the tokens from parsing the vector attribute for the
SIMD-enabled functions (formerly known as elemental functions). */
vec <c_token, va_gc> *cilk_simd_fn_tokens;
-
- /* OpenACC specific parser information. */
-
- vec <tree, va_gc> *oacc_routines;
} c_parser;
@@ -1171,7 +1167,7 @@ static void c_parser_external_declaratio
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, bool);
+ tree);
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,
@@ -1261,8 +1257,7 @@ static bool c_parser_pragma (c_parser *,
static bool c_parser_omp_target (c_parser *, enum pragma_context);
static void c_parser_omp_end_declare_target (c_parser *);
static void c_parser_omp_declare (c_parser *, enum pragma_context);
-static void c_parser_oacc_routine (c_parser *parser, enum pragma_context
- context);
+static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
static void c_parser_oacc_declare (c_parser *parser);
/* These Objective-C parser functions are only ever called when
@@ -1448,7 +1443,7 @@ c_parser_external_declaration (c_parser
only tell which after parsing the declaration specifiers, if
any, and the first declarator. */
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL, NULL_TREE, false);
+ NULL, vNULL, NULL_TREE);
break;
}
}
@@ -1767,7 +1762,7 @@ finish_oacc_declare (tree fnbody, tree d
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);
+static void c_finish_oacc_routine (c_parser *, tree, tree);
/* 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
@@ -1846,7 +1841,7 @@ c_parser_declaration_or_fndef (c_parser
bool nested, bool start_attr_ok,
tree *objc_foreach_object_declaration,
vec<c_token> omp_declare_simd_clauses,
- tree oacc_routine_clauses, bool oacc_routine_named)
+ tree oacc_routine_clauses)
{
struct c_declspecs *specs;
tree prefix_attrs;
@@ -2024,9 +2019,8 @@ c_parser_declaration_or_fndef (c_parser
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses);
- else
- c_finish_oacc_routine (parser, NULL_TREE,
- oacc_routine_clauses, oacc_routine_named);
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, NULL_TREE, oacc_routine_clauses);
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
@@ -2123,9 +2117,9 @@ c_parser_declaration_or_fndef (c_parser
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
- else
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- oacc_routine_named);
+
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, d, oacc_routine_clauses);
}
else
{
@@ -2139,9 +2133,8 @@ c_parser_declaration_or_fndef (c_parser
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
- else
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- oacc_routine_named);
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, d, oacc_routine_clauses);
start_init (d, asm_name, global_bindings_p ());
init_loc = c_parser_peek_token (parser)->location;
@@ -2188,16 +2181,17 @@ c_parser_declaration_or_fndef (c_parser
temp_store_parm_decls (d, parms);
c_finish_omp_declare_simd (parser, d, parms,
omp_declare_simd_clauses);
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- oacc_routine_named);
if (parms)
temp_pop_parm_decls ();
}
+ if (oacc_routine_clauses)
+ c_finish_oacc_routine (parser, d, oacc_routine_clauses);
+
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
-
+
if (c_parser_next_token_is_keyword (parser, RID_IN))
{
if (d)
@@ -2298,15 +2292,16 @@ c_parser_declaration_or_fndef (c_parser
while (c_parser_next_token_is_not (parser, CPP_EOF)
&& c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
c_parser_declaration_or_fndef (parser, false, false, false, true,
- false, NULL, vNULL, NULL_TREE, false);
+ false, NULL, vNULL, NULL_TREE);
store_parm_decls ();
if (omp_declare_simd_clauses.exists ()
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses);
- else
+
+ if (oacc_routine_clauses)
c_finish_oacc_routine (parser, current_function_decl,
- oacc_routine_clauses, oacc_routine_named);
+ oacc_routine_clauses);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
@@ -4969,7 +4964,7 @@ c_parser_compound_statement_nostart (c_p
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, vNULL, NULL_TREE, false);
+ true, NULL, vNULL, NULL_TREE);
if (last_stmt)
pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
"ISO C90 forbids mixed declarations and code");
@@ -4994,8 +4989,7 @@ c_parser_compound_statement_nostart (c_p
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, vNULL, NULL_TREE,
- false);
+ true, NULL, vNULL, NULL_TREE);
/* Following the old parser, __extension__ does not
disable this diagnostic. */
restore_extension_diagnostics (ext);
@@ -5144,7 +5138,7 @@ c_parser_label (c_parser *parser)
/*static_assert_ok*/ true,
/*empty_ok*/ true, /*nested*/ true,
/*start_attr_ok*/ true, NULL,
- vNULL, NULL_TREE, false);
+ vNULL, NULL_TREE);
}
}
}
@@ -5881,8 +5875,7 @@ c_parser_for_statement (c_parser *parser
else if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- &object_expression, vNULL, NULL_TREE,
- false);
+ &object_expression, vNULL, NULL_TREE);
parser->objc_could_be_foreach_context = false;
if (c_parser_next_token_is_keyword (parser, RID_IN))
@@ -5912,7 +5905,7 @@ c_parser_for_statement (c_parser *parser
c_parser_consume_token (parser);
c_parser_declaration_or_fndef (parser, true, true, true, true,
true, &object_expression, vNULL,
- NULL_TREE, false);
+ NULL_TREE);
parser->objc_could_be_foreach_context = false;
restore_extension_diagnostics (ext);
@@ -9049,8 +9042,7 @@ c_parser_objc_methodprotolist (c_parser
}
else
c_parser_declaration_or_fndef (parser, false, false, true,false,
- true, NULL, vNULL, NULL_TREE,
- false);
+ true, NULL, vNULL, NULL_TREE);
break;
}
}
@@ -13290,7 +13282,13 @@ c_parser_oacc_parallel (location_t loc,
static void
c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
{
- tree name = NULL_TREE;
+ 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);
+
+ if (context != pragma_external)
+ c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
c_parser_consume_pragma (parser);
@@ -13299,111 +13297,57 @@ c_parser_oacc_routine (c_parser *parser,
{
c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME)
- || c_parser_peek_token (parser)->id_kind != C_ID_ID)
- c_parser_error (parser, "expected identifier");
-
- // name should be an IDENTIFIER_NODE
- name = c_parser_peek_token (parser)->value;
+ c_token *token = c_parser_peek_token (parser);
- if (name == NULL_TREE)
+ if (token->type == CPP_NAME && token->id_kind == C_ID_ID)
{
- undeclared_variable (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
- name = error_mark_node;
+ decl = lookup_name (token->value);
+ if (!decl)
+ {
+ error_at (token->location, "%qE undeclared", token->value);
+ decl = error_mark_node;
+ }
+ c_parser_consume_token (parser);
}
-
- c_parser_consume_token (parser);
-
- if (name == error_mark_node)
- return;
+ else
+ c_parser_error (parser, "expected function name");
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
}
/* Build a chain of clauses. */
parser->in_pragma = true;
- tree clauses = NULL_TREE;
- clauses = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
- "#pragma acc routine",
- OACC_ROUTINE_CLAUSE_DEVICE_TYPE_MASK);
+ tree clauses = c_parser_oacc_all_clauses
+ (parser, OACC_ROUTINE_CLAUSE_MASK, "#pragma acc routine",
+ OACC_ROUTINE_CLAUSE_DEVICE_TYPE_MASK);
- if (name)
- {
- TREE_CHAIN (name) = clauses;
- vec_safe_push (parser->oacc_routines, name);
- }
+ /* 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);
else
- {
- if (context != pragma_external)
- {
- c_parser_error (parser, "%<#pragma acc routine%> must be "
- "followed by function declaration or definition");
- return;
- }
-
- 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, clauses, true);
- restore_extension_diagnostics (ext);
- }
- else
- c_parser_declaration_or_fndef (parser, true, true, true, false,
- true, NULL, vNULL, clauses, true);
- }
+ c_parser_declaration_or_fndef (parser, true, false, false, false,
+ true, NULL, vNULL, clauses);
}
static void
-c_finish_oacc_routine (c_parser *parser, tree fndecl, tree clauses,
- bool named)
+c_finish_oacc_routine (c_parser *ARG_UNUSED (parser),
+ tree fndecl, tree clauses)
{
- if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
+ if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL)
{
- if (!named)
- return;
-
- error ("%<#pragma acc routine%> not immediately followed by "
- "a function declaration or definition");
- gcc_unreachable();
+ if (fndecl != error_mark_node)
+ error_at (OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses)),
+ "%<#pragma acc routine%> does not refer to a function");
return;
}
- if (!named)
- {
- bool found = false;
- int i;
- tree t;
-
- for (i = 0; vec_safe_iterate (parser->oacc_routines, i, &t); i++)
- {
- if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
- IDENTIFIER_POINTER (t)))
- {
- found = true;
- clauses = TREE_CHAIN (t);
- break;
- }
- }
-
- if (!found)
- return;
- }
-
/* Process for function attrib */
- tree dims = build_oacc_routine_dims (clauses);
+ tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
replace_oacc_fn_attrib (fndecl, dims);
/* Also attach as a declare. */
- if (clauses != NULL_TREE)
- clauses = tree_cons (NULL_TREE, clauses, NULL_TREE);
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("omp declare target"),
clauses, DECL_ATTRIBUTES (fndecl));
@@ -14008,7 +13952,7 @@ c_parser_omp_for_loop (location_t loc, c
if (i > 0)
vec_safe_push (for_block, c_begin_compound_stmt (true));
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, vNULL, NULL_TREE, false);
+ NULL, vNULL, NULL_TREE);
decl = check_for_loop_decls (for_loc, flag_isoc99);
if (decl == NULL)
goto error_init;
@@ -15193,12 +15137,12 @@ c_parser_omp_declare_simd (c_parser *par
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, clauses, NULL_TREE, false);
+ NULL, clauses, NULL_TREE);
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, clauses, NULL_TREE, false);
+ NULL, clauses, NULL_TREE);
break;
case pragma_struct:
case pragma_param:
@@ -15218,8 +15162,7 @@ c_parser_omp_declare_simd (c_parser *par
if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, clauses, NULL_TREE,
- false);
+ true, NULL, clauses, NULL_TREE);
restore_extension_diagnostics (ext);
break;
}
@@ -15228,7 +15171,7 @@ c_parser_omp_declare_simd (c_parser *par
else if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, clauses, NULL_TREE, false);
+ NULL, clauses, NULL_TREE);
break;
}
c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by "
@@ -16576,8 +16519,6 @@ c_parse_file (void)
if (tparser.tokens == &tparser.tokens_buf[0])
the_parser->tokens = &the_parser->tokens_buf[0];
- the_parser->oacc_routines = NULL;
-
/* Initialize EH, if we've been told to do so. */
if (flag_exceptions)
using_eh_for_cleanups ();
Index: gcc/testsuite/c-c++-common/goacc/dtype-1.c
===================================================================
--- gcc/testsuite/c-c++-common/goacc/dtype-1.c (revision 226911)
+++ gcc/testsuite/c-c++-common/goacc/dtype-1.c (working copy)
@@ -90,24 +90,6 @@ test ()
#pragma acc update host(i1) async(4) wait (4) dtype(nvidia1) async(5) wait (5) dtype (*) async (6) wait (6)
}
-/* ACC ROUTINE DEVICE_TYPE: */
-
-#pragma acc routine (foo1) device_type (nvidia) gang
-#pragma acc routine (foo2) device_type (nvidia) worker
-#pragma acc routine (foo3) dtype (nvidia) vector
-#pragma acc routine (foo4) dtype (nvidia) seq
-#pragma acc routine (foo5) device_type (nvidia) bind (foo)
-#pragma acc routine (foo6) device_type (nvidia) gang device_type (*) seq
-#pragma acc routine (foo7) dtype (nvidia) worker dtype (*) seq
-#pragma acc routine (foo8) dtype (nvidia) vector device_type (*) seq
-#pragma acc routine (foo9) device_type (nvidia) seq device_type (*) worker
-#pragma acc routine (foo10) device_type (nvidia) bind (foo) dtype (*) seq
-#pragma acc routine (foo11) device_type (gpu) gang device_type (*) seq
-#pragma acc routine (foo12) device_type (gpu) worker dtype (*) seq
-#pragma acc routine (foo13) device_type (gpu) vector device_type (*) seq
-#pragma acc routine (foo14) dtype (gpu) seq dtype (*) worker
-#pragma acc routine (foo15) dtype (gpu) bind (foo) dtype (*) seq
-
/* { dg-final { scan-tree-dump-times "oacc_parallel device_type\\(nvidia\\) \\\[ wait\\(1\\) vector_length\\(32\\) num_workers\\(100\\) num_gangs\\(100\\) async\\(1\\) \\\]" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "oacc_parallel device_type\\(nvidia\\) \\\[ wait\\(2\\) vector_length\\(64\\) num_workers\\(200\\) num_gangs\\(200\\) async\\(2\\) \\\] wait\\(1\\) vector_length\\(1\\) num_workers\\(1\\) num_gangs\\(1\\) async\\(1\\)" 1 "omplower" } } */