Hi! I've committed following patch to implement OpenMP 4.5 declare target construct.
In addition, I've fixed omp declare simd handling, where it would in free form incorrectly accept free form SUBROUTINE FOO(A) !$OMP DECLARE SIMDLINEAR(A) INTEGER :: A END SUBROUTINE (no space between SIMD and following clause name). Tested on x86_64-linux, committed to gomp-4_5-branch. 2016-06-08 Jakub Jelinek <ja...@redhat.com> * gfortran.h (symbol_attribute): Add omp_declare_target_link bitfield. (struct gfc_omp_namelist): Add u.common field. (struct gfc_common_head): Change omp_declare_target into bitfield. Add omp_declare_target_link bitfield. (gfc_add_omp_declare_target_link): New prototype. * openmp.c (gfc_match_omp_to_link): New function. (gfc_match_omp_clauses): Use it for to and link clauses in declare target construct. (OMP_DECLARE_TARGET_CLAUSES): Define. (gfc_match_omp_declare_target): Rewritten for OpenMP 4.5. * symbol.c (check_conflict): Handle omp_declare_target_link. (gfc_add_omp_declare_target_link): New function. (gfc_copy_attr): Copy omp_declare_target_link. * module.c (enum ab_attribute): Add AB_OMP_DECLARE_TARGET_LINK. (attr_bits): Add AB_OMP_DECLARE_TARGET_LINK entry. (mio_symbol_attribute): Save and restore omp_declare_target_link bit. * f95-lang.c (gfc_attribute_table): Add "omp declare target link". * trans-decl.c (add_attributes_to_decl): Add "omp declare target link" instead of "omp declare target" for omp_declare_target_link. * trans-common.c (build_common_decl): Likewise. * openmp.c (gfc_match_omp_declare_simd): If not using the form with (proc-name), require space before first clause. testsuite/ * gfortran.dg/gomp/declare-target-1.f90: New test. * gfortran.dg/gomp/declare-target-2.f90: New test. --- gcc/fortran/gfortran.h.jj 2016-05-25 18:23:54.000000000 +0200 +++ gcc/fortran/gfortran.h 2016-06-07 15:29:18.170184003 +0200 @@ -849,6 +849,7 @@ typedef struct /* Mentioned in OMP DECLARE TARGET. */ unsigned omp_declare_target:1; + unsigned omp_declare_target_link:1; /* Mentioned in OACC DECLARE. */ unsigned oacc_declare_create:1; @@ -1157,6 +1158,7 @@ typedef struct gfc_omp_namelist gfc_omp_depend_op depend_op; gfc_omp_map_op map_op; gfc_omp_linear_op linear_op; + struct gfc_common_head *common; } u; struct gfc_omp_namelist_udr *udr; struct gfc_omp_namelist *next; @@ -1561,7 +1563,9 @@ struct gfc_undo_change_set typedef struct gfc_common_head { locus where; - char use_assoc, saved, threadprivate, omp_declare_target; + char use_assoc, saved, threadprivate; + unsigned char omp_declare_target : 1; + unsigned char omp_declare_target_link : 1; char name[GFC_MAX_SYMBOL_LEN + 1]; struct gfc_symbol *head; const char* binding_label; @@ -2840,6 +2844,8 @@ bool gfc_add_result (symbol_attribute *, bool gfc_add_save (symbol_attribute *, save_state, const char *, locus *); bool gfc_add_threadprivate (symbol_attribute *, const char *, locus *); bool gfc_add_omp_declare_target (symbol_attribute *, const char *, locus *); +bool gfc_add_omp_declare_target_link (symbol_attribute *, const char *, + locus *); bool gfc_add_saved_common (symbol_attribute *, locus *); bool gfc_add_target (symbol_attribute *, locus *); bool gfc_add_dummy (symbol_attribute *, const char *, locus *); --- gcc/fortran/openmp.c.jj 2016-05-31 19:33:55.000000000 +0200 +++ gcc/fortran/openmp.c 2016-06-08 16:10:55.309586149 +0200 @@ -340,6 +340,96 @@ cleanup: return MATCH_ERROR; } +/* Match a variable/procedure/common block list and construct a namelist + from it. */ + +static match +gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list) +{ + gfc_omp_namelist *head, *tail, *p; + locus old_loc, cur_loc; + char n[GFC_MAX_SYMBOL_LEN+1]; + gfc_symbol *sym; + match m; + gfc_symtree *st; + + head = tail = NULL; + + old_loc = gfc_current_locus; + + m = gfc_match (str); + if (m != MATCH_YES) + return m; + + for (;;) + { + cur_loc = gfc_current_locus; + m = gfc_match_symbol (&sym, 1); + switch (m) + { + case MATCH_YES: + p = gfc_get_omp_namelist (); + if (head == NULL) + head = tail = p; + else + { + tail->next = p; + tail = tail->next; + } + tail->sym = sym; + tail->where = cur_loc; + goto next_item; + case MATCH_NO: + break; + case MATCH_ERROR: + goto cleanup; + } + + m = gfc_match (" / %n /", n); + if (m == MATCH_ERROR) + goto cleanup; + if (m == MATCH_NO) + goto syntax; + + st = gfc_find_symtree (gfc_current_ns->common_root, n); + if (st == NULL) + { + gfc_error ("COMMON block /%s/ not found at %C", n); + goto cleanup; + } + p = gfc_get_omp_namelist (); + if (head == NULL) + head = tail = p; + else + { + tail->next = p; + tail = tail->next; + } + tail->u.common = st->n.common; + tail->where = cur_loc; + + next_item: + if (gfc_match_char (')') == MATCH_YES) + break; + if (gfc_match_char (',') != MATCH_YES) + goto syntax; + } + + while (*list) + list = &(*list)->next; + + *list = head; + return MATCH_YES; + +syntax: + gfc_error ("Syntax error in OpenMP variable list at %C"); + +cleanup: + gfc_free_omp_namelist (head); + gfc_current_locus = old_loc; + return MATCH_ERROR; +} + /* Match depend(sink : ...) construct a namelist from it. */ static match @@ -1249,6 +1339,12 @@ gfc_match_omp_clauses (gfc_omp_clauses * &c->lists[OMP_LIST_LINK]) == MATCH_YES)) continue; + else if ((mask & OMP_CLAUSE_LINK) + && !openacc + && (gfc_match_omp_to_link ("link (", + &c->lists[OMP_LIST_LINK]) + == MATCH_YES)) + continue; break; case 'm': if ((mask & OMP_CLAUSE_MAP) @@ -1688,7 +1784,13 @@ gfc_match_omp_clauses (gfc_omp_clauses * && match_oacc_expr_list ("tile (", &c->tile_list, true) == MATCH_YES) continue; - if ((mask & OMP_CLAUSE_TO) + if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK)) + { + if (gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]) + == MATCH_YES) + continue; + } + else if ((mask & OMP_CLAUSE_TO) && gfc_match_omp_variable_list ("to (", &c->lists[OMP_LIST_TO], false, NULL, &head, true) == MATCH_YES) @@ -2324,6 +2426,8 @@ cleanup: (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE) #define OMP_ORDERED_CLAUSES \ (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD) +#define OMP_DECLARE_TARGET_CLAUSES \ + (omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK) static match @@ -2457,16 +2561,17 @@ gfc_match_omp_declare_simd (void) gfc_symbol *proc_name; gfc_omp_clauses *c; gfc_omp_declare_simd *ods; + bool needs_space = false; switch (gfc_match (" ( %s ) ", &proc_name)) { case MATCH_YES: break; - case MATCH_NO: proc_name = NULL; break; + case MATCH_NO: proc_name = NULL; needs_space = true; break; case MATCH_ERROR: return MATCH_ERROR; } if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true, - false) != MATCH_YES) + needs_space) != MATCH_YES) return MATCH_ERROR; ods = gfc_get_omp_declare_simd (); @@ -2874,26 +2979,15 @@ match gfc_match_omp_declare_target (void) { locus old_loc; - char n[GFC_MAX_SYMBOL_LEN+1]; - gfc_symbol *sym; match m; - gfc_symtree *st; + gfc_omp_clauses *c = NULL; + int list; + gfc_omp_namelist *n; + gfc_symbol *s; old_loc = gfc_current_locus; - m = gfc_match (" ("); - if (gfc_current_ns->proc_name - && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY - && m == MATCH_YES) - { - gfc_error ("Only the !$OMP DECLARE TARGET form without " - "list is allowed in interface block at %C"); - goto cleanup; - } - - if (m == MATCH_NO - && gfc_current_ns->proc_name && gfc_match_omp_eos () == MATCH_YES) { if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr, @@ -2903,58 +2997,111 @@ gfc_match_omp_declare_target (void) return MATCH_YES; } - if (m != MATCH_YES) - return m; + if (gfc_current_ns->proc_name + && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY) + { + gfc_error ("Only the !$OMP DECLARE TARGET form without " + "clauses is allowed in interface block at %C"); + goto cleanup; + } - for (;;) + m = gfc_match (" ("); + if (m == MATCH_YES) { - m = gfc_match_symbol (&sym, 0); - switch (m) + c = gfc_get_omp_clauses (); + gfc_current_locus = old_loc; + m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_TO]); + if (m != MATCH_YES) + goto syntax; + if (gfc_match_omp_eos () != MATCH_YES) { - case MATCH_YES: - if (sym->attr.in_common) - gfc_error_now ("OMP DECLARE TARGET on a variable at %C is an " - "element of a COMMON block"); - else if (!gfc_add_omp_declare_target (&sym->attr, sym->name, - &sym->declared_at)) - goto cleanup; - goto next_item; - case MATCH_NO: - break; - case MATCH_ERROR: + gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C"); goto cleanup; } + } + else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES) != MATCH_YES) + return MATCH_ERROR; - m = gfc_match (" / %n /", n); - if (m == MATCH_ERROR) - goto cleanup; - if (m == MATCH_NO || n[0] == '\0') - goto syntax; + gfc_buffer_error (false); - st = gfc_find_symtree (gfc_current_ns->common_root, n); - if (st == NULL) + for (list = OMP_LIST_TO; list != OMP_LIST_NUM; + list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM)) + for (n = c->lists[list]; n; n = n->next) + if (n->sym) + n->sym->mark = 0; + else if (n->u.common->head) + n->u.common->head->mark = 0; + + for (list = OMP_LIST_TO; list != OMP_LIST_NUM; + list = (list == OMP_LIST_TO ? OMP_LIST_LINK : OMP_LIST_NUM)) + for (n = c->lists[list]; n; n = n->next) + if (n->sym) + { + if (n->sym->attr.in_common) + gfc_error_now ("OMP DECLARE TARGET variable at %L is an " + "element of a COMMON block", &n->where); + else if (n->sym->attr.omp_declare_target + && n->sym->attr.omp_declare_target_link + && list != OMP_LIST_LINK) + gfc_error_now ("OMP DECLARE TARGET variable at %L previously " + "mentioned in LINK clause and later in TO clause", + &n->where); + else if (n->sym->attr.omp_declare_target + && !n->sym->attr.omp_declare_target_link + && list == OMP_LIST_LINK) + gfc_error_now ("OMP DECLARE TARGET variable at %L previously " + "mentioned in TO clause and later in LINK clause", + &n->where); + else if (n->sym->mark) + gfc_error_now ("Variable at %L mentioned multiple times in " + "clauses of the same OMP DECLARE TARGET directive", + &n->where); + else if (gfc_add_omp_declare_target (&n->sym->attr, n->sym->name, + &n->sym->declared_at)) + { + if (list == OMP_LIST_LINK) + gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name, + &n->sym->declared_at); + } + n->sym->mark = 1; + } + else if (n->u.common->omp_declare_target + && n->u.common->omp_declare_target_link + && list != OMP_LIST_LINK) + gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously " + "mentioned in LINK clause and later in TO clause", + &n->where); + else if (n->u.common->omp_declare_target + && !n->u.common->omp_declare_target_link + && list == OMP_LIST_LINK) + gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously " + "mentioned in TO clause and later in LINK clause", + &n->where); + else if (n->u.common->head && n->u.common->head->mark) + gfc_error_now ("COMMON at %L mentioned multiple times in " + "clauses of the same OMP DECLARE TARGET directive", + &n->where); + else { - gfc_error ("COMMON block /%s/ not found at %C", n); - goto cleanup; + n->u.common->omp_declare_target = 1; + n->u.common->omp_declare_target_link = (list == OMP_LIST_LINK); + for (s = n->u.common->head; s; s = s->common_next) + { + s->mark = 1; + if (gfc_add_omp_declare_target (&s->attr, s->name, + &s->declared_at)) + { + if (list == OMP_LIST_LINK) + gfc_add_omp_declare_target_link (&s->attr, s->name, + &s->declared_at); + } + } } - st->n.common->omp_declare_target = 1; - for (sym = st->n.common->head; sym; sym = sym->common_next) - if (!gfc_add_omp_declare_target (&sym->attr, sym->name, - &sym->declared_at)) - goto cleanup; - next_item: - if (gfc_match_char (')') == MATCH_YES) - break; - if (gfc_match_char (',') != MATCH_YES) - goto syntax; - } + gfc_buffer_error (true); - if (gfc_match_omp_eos () != MATCH_YES) - { - gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C"); - goto cleanup; - } + if (c) + gfc_free_omp_clauses (c); return MATCH_YES; syntax: @@ -2962,6 +3109,8 @@ syntax: cleanup: gfc_current_locus = old_loc; + if (c) + gfc_free_omp_clauses (c); return MATCH_ERROR; } --- gcc/fortran/symbol.c.jj 2016-05-04 18:37:23.000000000 +0200 +++ gcc/fortran/symbol.c 2016-06-07 15:39:07.098546711 +0200 @@ -375,6 +375,7 @@ check_conflict (symbol_attribute *attr, *contiguous = "CONTIGUOUS", *generic = "GENERIC"; static const char *threadprivate = "THREADPRIVATE"; static const char *omp_declare_target = "OMP DECLARE TARGET"; + static const char *omp_declare_target_link = "OMP DECLARE TARGET LINK"; static const char *oacc_declare_copyin = "OACC DECLARE COPYIN"; static const char *oacc_declare_create = "OACC DECLARE CREATE"; static const char *oacc_declare_deviceptr = "OACC DECLARE DEVICEPTR"; @@ -472,6 +473,7 @@ check_conflict (symbol_attribute *attr, conf (dummy, intrinsic); conf (dummy, threadprivate); conf (dummy, omp_declare_target); + conf (dummy, omp_declare_target_link); conf (pointer, target); conf (pointer, intrinsic); conf (pointer, elemental); @@ -516,6 +518,7 @@ check_conflict (symbol_attribute *attr, conf (in_equivalence, allocatable); conf (in_equivalence, threadprivate); conf (in_equivalence, omp_declare_target); + conf (in_equivalence, omp_declare_target_link); conf (in_equivalence, oacc_declare_create); conf (in_equivalence, oacc_declare_copyin); conf (in_equivalence, oacc_declare_deviceptr); @@ -524,6 +527,8 @@ check_conflict (symbol_attribute *attr, conf (dummy, result); conf (entry, result); conf (generic, result); + conf (generic, omp_declare_target); + conf (generic, omp_declare_target_link); conf (function, subroutine); @@ -569,6 +574,7 @@ check_conflict (symbol_attribute *attr, conf (cray_pointee, in_equivalence); conf (cray_pointee, threadprivate); conf (cray_pointee, omp_declare_target); + conf (cray_pointee, omp_declare_target_link); conf (cray_pointee, oacc_declare_create); conf (cray_pointee, oacc_declare_copyin); conf (cray_pointee, oacc_declare_deviceptr); @@ -625,8 +631,11 @@ check_conflict (symbol_attribute *attr, conf (procedure, entry) conf (proc_pointer, abstract) + conf (proc_pointer, omp_declare_target) + conf (proc_pointer, omp_declare_target_link) conf (entry, omp_declare_target) + conf (entry, omp_declare_target_link) conf (entry, oacc_declare_create) conf (entry, oacc_declare_copyin) conf (entry, oacc_declare_deviceptr) @@ -668,6 +677,7 @@ check_conflict (symbol_attribute *attr, conf2 (subroutine); conf2 (threadprivate); conf2 (omp_declare_target); + conf2 (omp_declare_target_link); conf2 (oacc_declare_create); conf2 (oacc_declare_copyin); conf2 (oacc_declare_deviceptr); @@ -718,6 +728,8 @@ check_conflict (symbol_attribute *attr, if (!attr->proc_pointer) conf2 (in_common); + conf2 (omp_declare_target_link); + switch (attr->proc) { case PROC_ST_FUNCTION: @@ -754,6 +766,7 @@ check_conflict (symbol_attribute *attr, conf2 (threadprivate); conf2 (result); conf2 (omp_declare_target); + conf2 (omp_declare_target_link); conf2 (oacc_declare_create); conf2 (oacc_declare_copyin); conf2 (oacc_declare_deviceptr); @@ -1269,6 +1282,22 @@ gfc_add_omp_declare_target (symbol_attri bool +gfc_add_omp_declare_target_link (symbol_attribute *attr, const char *name, + locus *where) +{ + + if (check_used (attr, name, where)) + return false; + + if (attr->omp_declare_target_link) + return true; + + attr->omp_declare_target_link = 1; + return check_conflict (attr, name, where); +} + + +bool gfc_add_oacc_declare_create (symbol_attribute *attr, const char *name, locus *where) { @@ -1905,6 +1934,9 @@ gfc_copy_attr (symbol_attribute *dest, s if (src->omp_declare_target && !gfc_add_omp_declare_target (dest, NULL, where)) goto fail; + if (src->omp_declare_target_link + && !gfc_add_omp_declare_target_link (dest, NULL, where)) + goto fail; if (src->oacc_declare_create && !gfc_add_oacc_declare_create (dest, NULL, where)) goto fail; --- gcc/fortran/module.c.jj 2016-05-04 18:37:30.000000000 +0200 +++ gcc/fortran/module.c 2016-06-08 12:35:22.606491558 +0200 @@ -1988,7 +1988,8 @@ enum ab_attribute AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY, AB_OMP_DECLARE_TARGET, AB_ARRAY_OUTER_DEPENDENCY, AB_MODULE_PROCEDURE, AB_OACC_DECLARE_CREATE, AB_OACC_DECLARE_COPYIN, AB_OACC_DECLARE_DEVICEPTR, - AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK + AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK, + AB_OMP_DECLARE_TARGET_LINK }; static const mstring attr_bits[] = @@ -2051,6 +2052,7 @@ static const mstring attr_bits[] = minit ("OACC_DECLARE_DEVICEPTR", AB_OACC_DECLARE_DEVICEPTR), minit ("OACC_DECLARE_DEVICE_RESIDENT", AB_OACC_DECLARE_DEVICE_RESIDENT), minit ("OACC_DECLARE_LINK", AB_OACC_DECLARE_LINK), + minit ("OMP_DECLARE_TARGET_LINK", AB_OMP_DECLARE_TARGET_LINK), minit (NULL, -1) }; @@ -2250,6 +2252,8 @@ mio_symbol_attribute (symbol_attribute * MIO_NAME (ab_attribute) (AB_OACC_DECLARE_DEVICE_RESIDENT, attr_bits); if (attr->oacc_declare_link) MIO_NAME (ab_attribute) (AB_OACC_DECLARE_LINK, attr_bits); + if (attr->omp_declare_target_link) + MIO_NAME (ab_attribute) (AB_OMP_DECLARE_TARGET_LINK, attr_bits); mio_rparen (); @@ -2419,6 +2423,9 @@ mio_symbol_attribute (symbol_attribute * case AB_OMP_DECLARE_TARGET: attr->omp_declare_target = 1; break; + case AB_OMP_DECLARE_TARGET_LINK: + attr->omp_declare_target_link = 1; + break; case AB_ARRAY_OUTER_DEPENDENCY: attr->array_outer_dependency =1; break; --- gcc/fortran/f95-lang.c.jj 2016-05-19 18:26:41.000000000 +0200 +++ gcc/fortran/f95-lang.c 2016-06-08 14:12:39.153003811 +0200 @@ -93,6 +93,8 @@ static const struct attribute_spec gfc_a affects_type_identity } */ { "omp declare target", 0, 0, true, false, false, gfc_handle_omp_declare_target_attribute, false }, + { "omp declare target link", 0, 0, true, false, false, + gfc_handle_omp_declare_target_attribute, false }, { "oacc function", 0, -1, true, false, false, gfc_handle_omp_declare_target_attribute, false }, { NULL, 0, 0, false, false, false, NULL, false } --- gcc/fortran/trans-decl.c.jj 2016-05-04 18:37:33.000000000 +0200 +++ gcc/fortran/trans-decl.c 2016-06-07 16:40:01.086039305 +0200 @@ -1306,7 +1306,10 @@ add_attributes_to_decl (symbol_attribute list = chainon (list, attr); } - if (sym_attr.omp_declare_target) + if (sym_attr.omp_declare_target_link) + list = tree_cons (get_identifier ("omp declare target link"), + NULL_TREE, list); + else if (sym_attr.omp_declare_target) list = tree_cons (get_identifier ("omp declare target"), NULL_TREE, list); --- gcc/fortran/trans-common.c.jj 2016-05-04 18:37:25.000000000 +0200 +++ gcc/fortran/trans-common.c 2016-06-07 15:50:38.401564413 +0200 @@ -457,7 +457,11 @@ build_common_decl (gfc_common_head *com, if (com->threadprivate) set_decl_tls_model (decl, decl_default_tls_model (decl)); - if (com->omp_declare_target) + if (com->omp_declare_target_link) + DECL_ATTRIBUTES (decl) + = tree_cons (get_identifier ("omp declare target link"), + NULL_TREE, DECL_ATTRIBUTES (decl)); + else if (com->omp_declare_target) DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("omp declare target"), NULL_TREE, DECL_ATTRIBUTES (decl)); --- gcc/testsuite/gfortran.dg/gomp/declare-target-1.f90.jj 2016-06-08 14:24:47.821457897 +0200 +++ gcc/testsuite/gfortran.dg/gomp/declare-target-1.f90 2016-06-08 14:27:32.000000000 +0200 @@ -0,0 +1,27 @@ +! { dg-do compile } + +module declare_target_1 + !$omp declare target to (var_1, var_4) link (var_2, var_3) & + !$omp & link (var_5) to (var_6) + integer :: var_1, var_2, var_3, var_4, var_5, var_6 + interface + subroutine foo + !$omp declare target + end subroutine + end interface +end +subroutine bar + !$omp declare target + integer, save :: var_9 + !$omp declare target link (var_8) to (baz, var_7) link (var_9) to (var_10) + integer, save :: var_7, var_8, var_10 + integer :: var_11, var_12, var_13, var_14 + common /c1/ var_11, var_12 + common /c2/ var_13 + common /c3/ var_14 + !$omp declare target (baz, var_7, var_10, /c1/) + !$omp declare target to (/c2/) + !$omp declare target link (/c3/) + !$omp declare target (bar) + call baz +end subroutine --- gcc/testsuite/gfortran.dg/gomp/declare-target-2.f90.jj 2016-06-08 15:39:59.901462888 +0200 +++ gcc/testsuite/gfortran.dg/gomp/declare-target-2.f90 2016-06-08 15:48:01.000000000 +0200 @@ -0,0 +1,51 @@ +! { dg-do compile } + +module declare_target_2 + !$omp declare target to (a) link (a) ! { dg-error "TO clause and later in LINK" } + !$omp declare target (b) + !$omp declare target link (b) ! { dg-error "TO clause and later in LINK" } + !$omp declare target link (f) + !$omp declare target to (f) ! { dg-error "LINK clause and later in TO" } + !$omp declare target(c, c) ! { dg-error "mentioned multiple times in clauses of the same" } + !$omp declare target to (d) to (d) ! { dg-error "mentioned multiple times in clauses of the same" } + !$omp declare target link (e, e) ! { dg-error "mentioned multiple times in clauses of the same" } + integer, save :: a, b, c, d, e, f + interface + integer function f1 (a) + !$omp declare target (f1) ! { dg-error "form without clauses is allowed in interface block" } + integer :: a + end function + end interface + interface + integer function f2 (a) + !$omp declare target to (f2) ! { dg-error "form without clauses is allowed in interface block" } + integer :: a + end function + end interface +end +subroutine bar + !$omp declare target link (baz) ! { dg-error "isn.t SAVEd" } + call baz ! { dg-error "attribute conflicts" } +end subroutine +subroutine foo ! { dg-error "attribute conflicts" } + integer :: g, h, i, j, k, l, m, n, o, p, q + common /c1/ g, h + common /c2/ i, j + common /c3/ k, l + common /c4/ m, n + common /c5/ o, p, q + !$omp declare target to (g) ! { dg-error "is an element of a COMMON block" } + !$omp declare target link (foo) + !$omp declare target to (/c2/) + !$omp declare target (/c2/) + !$omp declare target to(/c2/) + !$omp declare target link(/c2/) ! { dg-error "TO clause and later in LINK" } + !$omp declare target link(/c3/) + !$omp declare target (/c3/) ! { dg-error "LINK clause and later in TO" } + !$omp declare target (/c4/, /c4/) ! { dg-error "mentioned multiple times in clauses of the same" } + !$omp declare target to (/c4/) to(/c4/) ! { dg-error "mentioned multiple times in clauses of the same" } + !$omp declare target link (/c5/) + !$omp declare target link (/c5/) + !$omp declare target link(/c5/)link(/c5/) ! { dg-error "mentioned multiple times in clauses of the same" } + !$omp declare target link(/c5/,/c5/) ! { dg-error "mentioned multiple times in clauses of the same" } +end subroutine Jakub