Fortran: Fixes to OpenMP 'interop' directive parsing support

Handle lists as argument to 'fr' and 'attr'; fix parsing corner cases.
Additionally, 'fr' values are now internally stored as integer, permitting
the diagnoses (warning) for values not defined in the OpenMP additional
definitions document.

	PR fortran/116661

gcc/fortran/ChangeLog:

	* gfortran.h (gfc_omp_namelist): Rename 'init' members for clarity.
	* match.cc (gfc_free_omp_namelist): Handle renaming.
	* dump-parse-tree.cc (show_omp_namelist): Update for new format
	and features.
	* openmp.cc (gfc_match_omp_prefer_type): Parse list to 'fr' and 'attr';
	store 'fr' values as integer.
	(gfc_match_omp_init): Rename variable names.

gcc/ChangeLog:

	* omp-api.h (omp_get_fr_id_from_name, omp_get_name_from_fr_id): New
	prototypes.
	* omp-general.cc (omp_get_fr_id_from_name, omp_get_name_from_fr_id):
	New.

include/ChangeLog:

	* gomp-constants.h (GOMP_INTEROP_IFR_LAST,
	GOMP_INTEROP_IFR_SEPARATOR, GOMP_INTEROP_IFR_NONE): New.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/interop-1.f90: Extend, update dg-*.
	* gfortran.dg/gomp/interop-2.f90: Update dg-error.
	* gfortran.dg/gomp/interop-3.f90: Add dg-warning.
This commit is contained in:
Tobias Burnus 2024-09-13 16:48:57 +02:00
parent 508ef58524
commit 99988464fc
10 changed files with 314 additions and 162 deletions

View file

@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see
#include "constructor.h"
#include "version.h"
#include "parse.h" /* For gfc_ascii_statement. */
#include "omp-api.h" /* For omp_get_name_from_fr_id. */
#include "gomp-constants.h" /* For GOMP_INTEROP_IFR_SEPARATOR. */
/* Keep track of indentation for symbol tree dumps. */
static int show_level = 0;
@ -1537,35 +1539,69 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n)
}
else if (list_type == OMP_LIST_INIT)
{
int i = 0;
if (n->u.init.target)
fputs ("target,", dumpfile);
if (n->u.init.targetsync)
fputs ("targetsync,", dumpfile);
char *prefer_type = n->u.init.str;
if (n->u.init.len)
fputs ("prefer_type(", dumpfile);
if (n->u.init.len)
while (*prefer_type)
{
fputc ('{', dumpfile);
if (n->u2.interop_int && n->u2.interop_int[i] != 0)
fprintf (dumpfile, "fr(%d),", n->u2.interop_int[i]);
else if (prefer_type[0] != ' ' || prefer_type[1] != '\0')
fprintf (dumpfile, "fr(\"%s\"),", prefer_type);
prefer_type += 1 + strlen (prefer_type);
while (*prefer_type)
{
fprintf (dumpfile, "attr(\"%s\"),", prefer_type);
prefer_type += 1 + strlen (prefer_type);
}
fputc ('}', dumpfile);
++prefer_type;
++i;
if (n->u2.init_interop_fr)
{
char *attr_str = n->u.init.attr;
int idx = 0;
int fr_id;
fputs ("prefer_type(", dumpfile);
do
{
fr_id = n->u2.init_interop_fr[idx];
fputc ('{', dumpfile);
if (fr_id != GOMP_INTEROP_IFR_NONE)
{
fputs ("fr(", dumpfile);
do
{
const char *fr_str = omp_get_name_from_fr_id (fr_id);
if (fr_str)
fprintf (dumpfile, "\"%s\"", fr_str);
else
fprintf (dumpfile, "%d", fr_id);
fr_id = n->u2.init_interop_fr[++idx];
if (fr_id != GOMP_INTEROP_IFR_SEPARATOR)
fputc (',', dumpfile);
}
while (fr_id != GOMP_INTEROP_IFR_SEPARATOR);
fputc (')', dumpfile);
if (attr_str && (attr_str[0] != ' ' || attr_str[1] != '\0'))
fputc (',', dumpfile);
}
else
fr_id = n->u2.init_interop_fr[++idx];
if (attr_str && attr_str[0] == ' ' && attr_str[1] == '\0')
attr_str += 2;
else if (attr_str)
{
fputs ("attr(\"", dumpfile);
do
{
fputs ((char *) attr_str, dumpfile);
fputc ('"', dumpfile);
attr_str += strlen (attr_str) + 1;
if (attr_str[0] == '\0')
break;
fputs (",\"", dumpfile);
}
while (true);
fputc (')', dumpfile);
}
fputc ('}', dumpfile);
fr_id = n->u2.init_interop_fr[++idx];
if (fr_id == GOMP_INTEROP_IFR_SEPARATOR)
break;
fputc (',', dumpfile);
if (attr_str)
++attr_str;
}
while (true);
fputc (')', dumpfile);
}
if (n->u.init.len)
fputc (')', dumpfile);
fputc (':', dumpfile);
}
fprintf (dumpfile, "%s", n->sym ? n->sym->name : "omp_all_memory");

View file

@ -1389,7 +1389,7 @@ typedef struct gfc_omp_namelist
bool present_modifier;
struct
{
char *str;
char *attr;
int len;
bool target;
bool targetsync;
@ -1402,7 +1402,7 @@ typedef struct gfc_omp_namelist
gfc_expr *allocator;
struct gfc_symbol *traits_sym;
struct gfc_omp_namelist *duplicate_of;
int *interop_int;
char *init_interop_fr;
} u2;
struct gfc_omp_namelist *next;
locus where;

View file

@ -5551,7 +5551,7 @@ gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns,
{
gfc_omp_namelist *n;
gfc_expr *last_allocator = NULL;
char *last_init_str = NULL;
char *last_init_attr = NULL;
for (; name; name = n)
{
@ -5575,11 +5575,11 @@ gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns,
{ } /* name->u2.traits_sym: shall not call gfc_free_symbol here. */
else if (free_init)
{
if (name->u.init.str != last_init_str)
if (name->u.init.attr != last_init_attr)
{
last_init_str = name->u.init.str;
free (name->u.init.str);
free (name->u2.interop_int);
last_init_attr = name->u.init.attr;
free (name->u.init.attr);
free (name->u2.init_interop_fr);
}
}
else if (name->u2.udr)

View file

@ -1827,16 +1827,31 @@ error:
where 'fr' takes an integer named constant or a string literal
and 'attr takes a string literal, starting with 'ompx_')
Document string + int format
*/
For the foreign runtime identifiers, string values are converted to
their integer value; unknown string or integer values are set to 0.
For the simple syntax, pref_int_array contains alternatingly the
fr_id integer value and GOMP_INTEROP_IFR_SEPARATOR followed by a
GOMP_INTEROP_IFR_SEPARATOR as last item.
For the complex syntax, it contains the values associated with a
'fr(...)' followed by GOMP_INTEROP_IFR_SEPARATOR. If there is no
'fr' in a curly-brace block, it is GOMP_INTEROP_IFR_NONE followed
by GOMP_INTEROP_IFR_SEPARATOR. An additional GOMP_INTEROP_IFR_SEPARATOR
at the end terminates the array.
For attributes, if the simply syntax is used, it is NULL - likewise if no
'attr' appears. For the complex syntax it is: For reach curly-brace block,
it is \0\0 is no attr appears and otherwise a concatenation (including
the \0) of all 'attr' strings followed by a tailing '\0'. At the end,
another '\0' follows. */
static match
gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_array)
gfc_match_omp_prefer_type (char **fr_int_array, char **attr_str, int *attr_str_len)
{
gfc_expr *e;
size_t cnt = 0;
std::vector<int> int_list;
std::string pref_string;
int cnt_brace_grp = 0;
std::vector<char> int_list;
std::string attr_string;
/* New syntax. */
if (gfc_peek_ascii_char () == '{')
do
@ -1846,8 +1861,8 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
gfc_error ("Expected %<{%> at %C");
return MATCH_ERROR;
}
std::string attr;
bool fr_found = false;
bool attr_found = false;
do
{
if (gfc_match ("fr ( ") == MATCH_YES)
@ -1859,99 +1874,129 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
return MATCH_ERROR;
}
fr_found = true;
gfc_symbol *sym = NULL;
e = NULL;
locus loc = gfc_current_locus;
if (gfc_match_symbol (&sym, 0) != MATCH_YES
|| gfc_match (" _") == MATCH_YES)
do
{
gfc_current_locus = loc;
if (gfc_match_expr (&e) == MATCH_ERROR)
if (gfc_match_expr (&e) != MATCH_YES)
return MATCH_ERROR;
}
if ((!sym && !e)
|| (e && (!gfc_resolve_expr (e)
|| e->expr_type != EXPR_CONSTANT
|| e->ts.type != BT_CHARACTER
|| e->ts.kind != gfc_default_character_kind
|| e->value.character.length == 0))
|| (sym && (sym->attr.flavor != FL_PARAMETER
|| sym->ts.type != BT_INTEGER
|| !mpz_fits_sint_p (sym->value->value.integer)
|| sym->attr.dimension)))
{
gfc_error ("Expected constant integer identifier or "
"non-empty default-kind character literal at %L",
&loc);
gfc_free_expr (e);
if (e->expr_type != EXPR_CONSTANT
|| e->ref != NULL
|| !gfc_resolve_expr (e)
|| (e->ts.type != BT_INTEGER
&& e->ts.type != BT_CHARACTER)
|| (e->ts.type == BT_INTEGER
&& (!e->symtree
|| e->symtree->n.sym->attr.flavor != FL_PARAMETER
|| !mpz_fits_sint_p (e->value.integer)))
|| (e->ts.type == BT_CHARACTER
&& (e->ts.kind != gfc_default_character_kind
|| e->value.character.length == 0)))
{
gfc_error ("Expected scalar integer parameter or "
"non-empty default-kind character literal "
"at %L", &e->where);
gfc_free_expr (e);
return MATCH_ERROR;
}
gfc_gobble_whitespace ();
int val;
if (e->ts.type == BT_INTEGER)
{
val = mpz_get_si (e->value.integer);
if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
{
gfc_warning (OPT_Wopenmp,
"Unknown foreign runtime identifier "
"%qd at %L", val, &e->where);
val = 0;
}
}
else
{
char *str = XALLOCAVEC (char,
e->value.character.length+1);
for (int i = 0; i < e->value.character.length + 1; i++)
str[i] = e->value.character.string[i];
if (memchr (str, '\0', e->value.character.length) != 0)
{
gfc_error ("Unexpected null character in character "
"literal at %L", &e->where);
return MATCH_ERROR;
}
val = omp_get_fr_id_from_name (str);
if (val == 0)
gfc_warning (OPT_Wopenmp,
"Unknown foreign runtime identifier %qs "
"at %L", str, &e->where);
}
int_list.push_back (val);
if (gfc_match (", ") == MATCH_YES)
continue;
if (gfc_match (") ") == MATCH_YES)
break;
gfc_error ("Expected %<,%> or %<)%> at %C");
return MATCH_ERROR;
}
if (sym)
{
for (size_t i = int_list.size(); i < cnt; ++i)
int_list.push_back (0);
int_list.push_back (mpz_get_si (sym->value->value.integer));
pref_string += ' ';
pref_string += '\0';
}
else
{
char *str = XALLOCAVEC (char, e->value.character.length+1);
for (int i = 0; i < e->value.character.length + 1; i++)
str[i] = e->value.character.string[i];
if (memchr (str, '\0', e->value.character.length) != 0)
{
gfc_error ("Unexpected null character in character "
"literal at %L", &loc);
return MATCH_ERROR;
}
pref_string += str;
pref_string += '\0';
}
while (true);
}
else if (gfc_match ("attr ( ") == MATCH_YES)
{
locus loc = gfc_current_locus;
if (gfc_match_expr (&e) != MATCH_YES
|| e->expr_type != EXPR_CONSTANT
|| e->ts.type != BT_CHARACTER)
attr_found = true;
if (attr_string.empty ())
for (int i = 0; i < cnt_brace_grp; ++i)
{
/* Add dummy elements for previous curly-brace blocks. */
attr_string += ' ';
attr_string += '\0';
attr_string += '\0';
}
do
{
gfc_error ("Expected default-kind character literal at %L",
&loc);
gfc_free_expr (e);
if (gfc_match_expr (&e) != MATCH_YES)
return MATCH_ERROR;
if (e->expr_type != EXPR_CONSTANT
|| e->rank != 0
|| e->ts.type != BT_CHARACTER
|| e->ts.kind != gfc_default_character_kind)
{
gfc_error ("Expected default-kind character literal "
"at %L", &e->where);
gfc_free_expr (e);
return MATCH_ERROR;
}
gfc_gobble_whitespace ();
char *str = XALLOCAVEC (char, e->value.character.length+1);
for (int i = 0; i < e->value.character.length + 1; i++)
str[i] = e->value.character.string[i];
if (!startswith (str, "ompx_"))
{
gfc_error ("Character literal at %L must start with "
"%<ompx_%>", &e->where);
gfc_free_expr (e);
return MATCH_ERROR;
}
if (memchr (str, '\0', e->value.character.length) != 0
|| memchr (str, ',', e->value.character.length) != 0)
{
gfc_error ("Unexpected null or %<,%> character in "
"character literal at %L", &e->where);
return MATCH_ERROR;
}
attr_string += str;
attr_string += '\0';
if (gfc_match (", ") == MATCH_YES)
continue;
if (gfc_match (") ") == MATCH_YES)
break;
gfc_error ("Expected %<,%> or %<)%> at %C");
return MATCH_ERROR;
}
char *str = XALLOCAVEC (char, e->value.character.length+1);
for (int i = 0; i < e->value.character.length + 1; i++)
str[i] = e->value.character.string[i];
if (!startswith (str, "ompx_"))
{
gfc_error ("Character literal at %L must start with "
"%<ompx_%>", &e->where);
gfc_free_expr (e);
return MATCH_ERROR;
}
if (memchr (str, '\0', e->value.character.length) != 0
|| memchr (str, ',', e->value.character.length) != 0)
{
gfc_error ("Unexpected null or %<,%> character in "
"character literal at %L", &e->where);
return MATCH_ERROR;
}
attr += str;
attr += '\0';
while (true);
}
else
{
gfc_error ("Expected %<fr(%> or %<attr(%> at %C");
return MATCH_ERROR;
}
++cnt;
if (gfc_match (") ") != MATCH_YES)
{
gfc_error ("Expected %<)%> at %C");
return MATCH_ERROR;
}
if (gfc_match (", ") == MATCH_YES)
continue;
if (gfc_match ("} ") == MATCH_YES)
@ -1960,13 +2005,20 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
return MATCH_ERROR;
}
while (true);
++cnt_brace_grp;
if (!fr_found)
int_list.push_back (GOMP_INTEROP_IFR_NONE);
int_list.push_back (GOMP_INTEROP_IFR_SEPARATOR);
if (!attr_string.empty ())
{
pref_string += ' ';
pref_string += '\0';
if (!attr_found)
{
/* Dummy entry. */
attr_string += ' ';
attr_string += '\0';
}
attr_string += '\0';
}
pref_string += attr;
pref_string += '\0';
if (gfc_match (", ") == MATCH_YES)
continue;
@ -1982,6 +2034,7 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
if (gfc_match_expr (&e) != MATCH_YES)
return MATCH_ERROR;
if (!gfc_resolve_expr (e)
|| e->rank != 0
|| e->expr_type != EXPR_CONSTANT
|| (e->ts.type != BT_INTEGER && e->ts.type != BT_CHARACTER)
|| (e->ts.type == BT_INTEGER
@ -1990,17 +2043,23 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
&& (e->ts.kind != gfc_default_character_kind
|| e->value.character.length == 0)))
{
gfc_error ("Expected constant integer expression or non-empty "
"default-kind character literal at %L", &e->where);
gfc_error ("Expected constant scalar integer expression or "
"non-empty default-kind character literal at %L", &e->where);
gfc_free_expr (e);
return MATCH_ERROR;
}
gfc_gobble_whitespace ();
int val;
if (e->ts.type == BT_INTEGER)
{
for (size_t i = int_list.size(); i < cnt; ++i)
int_list.push_back (0);
int_list.push_back (mpz_get_si (e->value.integer));
pref_string += ' ';
val = mpz_get_si (e->value.integer);
if (val < 1 || val > GOMP_INTEROP_IFR_LAST)
{
gfc_warning (OPT_Wopenmp,
"Unknown foreign runtime identifier %qd at %L",
val, &e->where);
val = 0;
}
}
else
{
@ -2009,15 +2068,18 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
str[i] = e->value.character.string[i];
if (memchr (str, '\0', e->value.character.length) != 0)
{
gfc_error ("Unexpected null character in character literal "
"at %L", &e->where);
gfc_error ("Unexpected null character in character "
"literal at %L", &e->where);
return MATCH_ERROR;
}
pref_string += str;
val = omp_get_fr_id_from_name (str);
if (val == 0)
gfc_warning (OPT_Wopenmp,
"Unknown foreign runtime identifier %qs at %L",
str, &e->where);
}
pref_string += '\0';
pref_string += '\0';
++cnt;
int_list.push_back (val);
int_list.push_back (GOMP_INTEROP_IFR_SEPARATOR);
gfc_free_expr (e);
if (gfc_match (", ") == MATCH_YES)
continue;
@ -2027,19 +2089,16 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar
return MATCH_ERROR;
}
while (true);
if (!int_list.empty())
for (size_t i = int_list.size(); i < cnt; ++i)
int_list.push_back (0);
int_list.push_back (GOMP_INTEROP_IFR_SEPARATOR);
*fr_int_array = XNEWVEC (char, int_list.size ());
memcpy (*fr_int_array, int_list.data (), sizeof (char) * int_list.size ());
pref_string += '\0';
*pref_str_len = pref_string.length();
*pref_str = XNEWVEC (char, pref_string.length ());
memcpy (*pref_str, pref_string.data (), pref_string.length ());
if (!int_list.empty ())
if (!attr_string.empty ())
{
*pref_int_array = XNEWVEC (int, cnt);
memcpy (*pref_int_array, int_list.data (), sizeof (int) * cnt);
attr_string += '\0';
*attr_str_len = attr_string.length();
*attr_str = XNEWVEC (char, attr_string.length ());
memcpy (*attr_str, attr_string.data (), attr_string.length ());
}
return MATCH_YES;
}
@ -2052,21 +2111,21 @@ static match
gfc_match_omp_init (gfc_omp_namelist **list)
{
bool target = false, targetsync = false;
char *pref_str = NULL;
int pref_str_len = 0;
int *pref_int_array = NULL;
char *fr_int_array = NULL;
char *attr_str = NULL;
int attr_str_len = 0;
match m;
locus old_loc = gfc_current_locus;
do {
if (gfc_match ("prefer_type ( ") == MATCH_YES)
{
if (pref_str)
if (fr_int_array)
{
gfc_error ("Duplicate %<prefer_type%> modifier at %C");
return MATCH_ERROR;
}
m = gfc_match_omp_prefer_type (&pref_str, &pref_str_len,
&pref_int_array);
m = gfc_match_omp_prefer_type (&fr_int_array, &attr_str,
&attr_str_len);
if (m != MATCH_YES)
return m;
if (gfc_match (", ") == MATCH_YES)
@ -2084,7 +2143,7 @@ gfc_match_omp_init (gfc_omp_namelist **list)
if (gfc_match (": ") == MATCH_YES)
break;
gfc_char_t c = gfc_peek_char ();
if (!pref_str
if (!fr_int_array
&& (c == ')'
|| (gfc_current_form != FORM_FREE
&& (c == '_' || ISALPHA (c)))))
@ -2103,7 +2162,7 @@ gfc_match_omp_init (gfc_omp_namelist **list)
if (gfc_match (": ") == MATCH_YES)
break;
gfc_char_t c = gfc_peek_char ();
if (!pref_str
if (!fr_int_array
&& (c == ')'
|| (gfc_current_form != FORM_FREE
&& (c == '_' || ISALPHA (c)))))
@ -2114,7 +2173,7 @@ gfc_match_omp_init (gfc_omp_namelist **list)
gfc_error ("Expected %<,%> or %<:%> at %C");
return MATCH_ERROR;
}
if (pref_str)
if (fr_int_array)
{
gfc_error ("Expected %<target%> or %<targetsync%> at %C");
return MATCH_ERROR;
@ -2131,9 +2190,9 @@ gfc_match_omp_init (gfc_omp_namelist **list)
{
n->u.init.target = target;
n->u.init.targetsync = targetsync;
n->u.init.str = pref_str;
n->u.init.len = pref_str_len;
n->u2.interop_int = pref_int_array;
n->u.init.attr = attr_str;
n->u.init.len = attr_str_len;
n->u2.init_interop_fr = fr_int_array;
}
return MATCH_YES;
}

View file

@ -29,4 +29,7 @@ along with GCC; see the file COPYING3. If not see
extern bool omp_runtime_api_procname (const char *name);
extern bool omp_runtime_api_call (const_tree fndecl);
extern int omp_get_fr_id_from_name (const char *);
extern const char *omp_get_name_from_fr_id (int);
#endif

View file

@ -3385,6 +3385,35 @@ omp_runtime_api_call (const_tree fndecl)
return omp_runtime_api_procname (IDENTIFIER_POINTER (declname));
}
/* See "Additional Definitions for the OpenMP API Specification" document;
associated IDs are 1, 2, ... */
static const char* omp_interop_fr_str[] = {"cuda", "cuda_driver", "opencl",
"sycl", "hip", "level_zero", "hsa"};
/* Returns the foreign-runtime ID if found or 0 otherwise. */
int
omp_get_fr_id_from_name (const char *str)
{
static_assert (GOMP_INTEROP_IFR_LAST == ARRAY_SIZE (omp_interop_fr_str), "");
for (unsigned i = 0; i < ARRAY_SIZE (omp_interop_fr_str); ++i)
if (!strcmp (str, omp_interop_fr_str[i]))
return i + 1;
return 0;
}
/* Returns the string value to a foreign-runtime integer value or NULL if value
is not known. */
const char *
omp_get_name_from_fr_id (int fr_id)
{
if (fr_id < 1 || fr_id > (int) ARRAY_SIZE (omp_interop_fr_str))
return NULL;
return omp_interop_fr_str[fr_id-1];
}
namespace omp_addr_tokenizer {
/* We scan an expression by recursive descent, and build a vector of

View file

@ -28,6 +28,8 @@ implicit none
!$omp requires reverse_offload
integer(omp_interop_fr_kind), parameter :: ifr_array(2) = [omp_ifr_cuda, omp_ifr_hip]
integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5
integer :: x
@ -37,7 +39,7 @@ integer :: x
!$omp& destroy(obj2, obj3) depend(inout: x) use(obj4, obj5) device(device_num: 0)
!$omp assume contains(interop)
!$omp interop init(prefer_type("cu"//char(1)//"da") : obj3)
!$omp interop init(prefer_type("cu"//char(1)//"da") : obj3) ! { dg-warning "Unknown foreign runtime identifier 'cu\\\\x01da'" }
!$omp end assume
!$omp interop init(prefer_type("cu"//char(0)//"da") : obj3) ! { dg-error "Unexpected null character in character literal" }
@ -52,11 +54,29 @@ integer :: x
!$omp interop init ( target , prefer_type( { fr("hsa"), attr("ompx_nothing") , fr("hsa" ) }) :obj1) ! { dg-error "Duplicated 'fr' preference-selector-name" }
!$omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1)
!$omp interop init ( prefer_type( sin(3.3) : obj1) ! { dg-error "Expected constant integer expression or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(4) }) : obj1) ! { dg-error "Expected constant integer identifier or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(4_"cuda") }) : obj1) ! { dg-error "Expected constant integer identifier or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1) ! { dg-warning "Unknown foreign runtime identifier '20'" }
!$omp interop init ( prefer_type( sin(3.3) : obj1) ! { dg-error "Expected constant scalar integer expression or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(4 ) }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(4_"cuda" ) }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(c_char_"cuda") }) : obj1) ! OK
!$omp interop init ( prefer_type( {fr(1_"cuda") }) : obj1) ! OK
!$omp interop init ( prefer_type( {fr(1_"cuda" ) }) : obj1) ! OK
!$omp interop init ( prefer_type( {fr(omp_ifr_level_zero ) }, {fr(omp_ifr_hip)}) : obj1) ! OK
!$omp interop init ( prefer_type( {fr(omp_ifr_level_zero + 1) }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(x) }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(ifr_array ) }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(ifr_array(1) ) }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( omp_ifr_level_zero, omp_ifr_hip ) : obj1) ! OK
!$omp interop init ( prefer_type( omp_ifr_level_zero +1 ) : obj1) ! OK
!$omp interop init ( prefer_type( x ) : obj1) ! { dg-error "Expected constant scalar integer expression or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( ifr_array ) : obj1) ! { dg-error "Expected constant scalar integer expression or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( ifr_array(2) ) : obj1) ! OK
!$omp interop init ( prefer_type( 4, omp_ifr_hip*4) : obj1) ! { dg-warning "Unknown foreign runtime identifier '20'" }
!$omp interop init ( prefer_type( 4, 1, 3) : obj1)
!$omp interop init ( prefer_type( {fr("cuda","sycl") }, {fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } , {fr(omp_ifr_hip) }) : obj1)
!$omp interop init ( prefer_type( {fr("cuda","sycl"), attr("ompx_1", "ompx_2"), attr("ompx_3") }, {attr("ompx_4", "ompx_5"),fr(omp_ifr_hsa,omp_ifr_level_zero)} ) : obj1)
!$omp interop init ( prefer_type( { fr("cuda","sycl"), attr("ompx_1") }, {fr(omp_ifr_hsa,omp_ifr_level_zero)} , {attr("ompx_a") } ) : obj1)
end

View file

@ -26,7 +26,7 @@ implicit none
integer(omp_interop_kind) :: obj1, obj2, obj3, obj4, obj5
integer :: x
!$omp interop init ( prefer_type( {fr(1_"") }) : obj1) ! { dg-error "Expected constant integer identifier or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(1_"") }) : obj1) ! { dg-error "Expected scalar integer parameter or non-empty default-kind character literal" }
!$omp interop init ( prefer_type( {fr(1_"hip") , attr(omp_ifr_cuda) }) : obj1) ! { dg-error "Expected default-kind character literal" }
!$omp interop init ( prefer_type( {fr(1_"hip") , attr("myooption") }) : obj1) ! { dg-error "Character literal at .1. must start with 'ompx_'" }

View file

@ -33,7 +33,7 @@ integer :: x
!$omp& destroy(obj2, obj3) depend(inout: x) use(obj4, obj5) device(device_num: 0)
!$omp assume contains(interop)
!$omp interop init(prefer_type("cu"//char(1)//"da") : obj3)
!$omp interop init(prefer_type("cu"//char(1)//"da") : obj3) ! { dg-warning "Unknown foreign runtime identifier 'cu\\\\x01da'" }
!$omp end assume
!$omp interop init(obj1, obj2, obj1), use(obj4) destroy(obj4)

View file

@ -388,6 +388,11 @@ enum gomp_map_kind
#define GOMP_REQUIRES_REVERSE_OFFLOAD 0x80
#define GOMP_REQUIRES_TARGET_USED 0x200
/* Interop foreign-runtime data. */
#define GOMP_INTEROP_IFR_LAST 7
#define GOMP_INTEROP_IFR_SEPARATOR -1
#define GOMP_INTEROP_IFR_NONE -2
/* HSA specific data structures. */
/* Identifiers of device-specific target arguments. */