On Fri, Aug 20, 2021 at 09:18:32PM +0200, Marcel Vollweiler wrote: > --- a/gcc/c/c-parser.c > +++ b/gcc/c/c-parser.c > @@ -15864,37 +15864,81 @@ c_parser_omp_clause_map (c_parser *parser, tree > list) > } > > /* OpenMP 4.0: > - device ( expression ) */ > +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> > device ( expression )
Please remove all the >>>>>s. > + > + OpenMP 5.0: > + device ( [device-modifier :] integer-expression ) > + > + device-modifier: > + ancestor | device_num */ > > + /* A requires directive with the reverse_offload clause must be > + specified. */ > + if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0) > + { > + c_parser_error (parser, "a %<requires%> directive with the " > + "%<reverse_offload%> clause must be " > + "specified"); [BI think this diagnostics is confusing, it tells the user that it has to do something but doesn't tell why. It is also not a parser error. So I think it should be instead error_at (tok->location, "%<ancestor%> device modifier not " "preceded by %<requires%> directive " "with %<reverse_offload%> clause"); > + parens.skip_until_found_close (parser); > + return list; > + } > + ancestor = true; > + } > + if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) > + { > + c_parser_error (parser, "expected integer expression"); > + return list; > } > > + check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device"); > + > + c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE); > + > + OMP_CLAUSE_DEVICE_ID (c) = t; > + OMP_CLAUSE_CHAIN (c) = list; > + OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor; > + > + list = c; > return list; > } > > diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c > index 5349ef1..b4d8d81 100644 > --- a/gcc/c/c-typeck.c > +++ b/gcc/c/c-typeck.c > @@ -15139,6 +15139,22 @@ c_finish_omp_clauses (tree clauses, enum > c_omp_region_type ort) > case OMP_CLAUSE_COLLAPSE: > case OMP_CLAUSE_FINAL: > case OMP_CLAUSE_DEVICE: > + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE > + && OMP_CLAUSE_DEVICE_ANCESTOR (c)) > + { > + t = OMP_CLAUSE_DEVICE_ID (c); > + if (TREE_CODE (t) == INTEGER_CST > + && wi::to_widest (t) != 1) > + { > + error_at (OMP_CLAUSE_LOCATION (c), > + "the %<device%> clause expression must evaluate to " > + "%<1%>"); > + remove = true; > + break; > + } > + } > + /* FALLTHRU */ For the C FE, I'd suggest to move this to the c_parser_omp_clause_device routine like other similar checking is done there too. And you can use if (TREE_CODE (t) == INTEGER_CST && !integer_onep (t)) > + error_at (tok->location, "a %<requires%> directive with the " > + "%<reverse_offload%> clause must be " > + "specified"); See above. > @@ -38562,6 +38601,7 @@ cp_parser_omp_clause_device (cp_parser *parser, tree > list, > c = build_omp_clause (location, OMP_CLAUSE_DEVICE); > OMP_CLAUSE_DEVICE_ID (c) = t; > OMP_CLAUSE_CHAIN (c) = list; > + OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor; But in C++ the INTEGER_CST checking shouldn't be done here, because the argument could be type or value dependent. > --- a/gcc/cp/semantics.c > +++ b/gcc/cp/semantics.c > @@ -7334,6 +7334,15 @@ finish_omp_clauses (tree clauses, enum > c_omp_region_type ort) > "%<device%> id must be integral"); > remove = true; > } > + else if (OMP_CLAUSE_DEVICE_ANCESTOR (c) > + && TREE_CODE (t) == INTEGER_CST > + && wi::to_widest (t) != 1) !integer_onep (t) > + if (!(gfc_current_ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)) > + { > + gfc_error ("a %<requires%> directive with the " > + "%<reverse_offload%> clause must be " > + "specified at %C"); See above. > + else if (gfc_match ("%e )", &c->device) == MATCH_YES) > + { > + } > + else Better != MATCH_YES and drop the {} else ? > + { > + gfc_error ("Expected integer expression or a single device-" > + "modifier %<device_num%> or %<ancestor%> at %C"); > + break; > + } > + continue; > + } > if ((mask & OMP_CLAUSE_DEVICE) > && openacc > && gfc_match ("device ( ") == MATCH_YES > + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE > + && OMP_CLAUSE_DEVICE_ANCESTOR (c)) > + { > + if (code != OMP_TARGET) > + { > + error_at (OMP_CLAUSE_LOCATION (c), > + "%<device%> clause with %<ancestor%> is only " > + "allowed on %<target%> construct"); > + remove = true; > + } Formatting, {/} are correctly indented, but error_at and remove should be indented 2 columns to the right from that, not 4 columns. Also, it should have break; there too, so that it doesn't fallthrough to the next one: > + > + tree clauses = *orig_list_p; > + for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses)) > + if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE > + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE > + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE > + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP > + && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP > + ) > + { > + error_at (OMP_CLAUSE_LOCATION (c), > + "with %<ancestor%>, only the %<device%>, " > + "%<firstprivate%>, %<private%>, %<defaultmap%>, " > + "and %<map%> clauses may appear on the " > + "construct"); > + remove = true; > + } > + } > + /* Fall through. */ > + > @@ -4001,6 +4011,20 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool > *handled_ops_p, > "OpenMP runtime API call %qD in a region with " > "%<order(concurrent)%> clause", fndecl); > } > + if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET > + && gimple_omp_target_kind (ctx->stmt) == > + GF_OMP_TARGET_KIND_REGION) Formatting. Neither == nor = should be at the end of lines. So, if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET && (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)) > + { > + tree c = > + omp_find_clause (gimple_omp_target_clauses (ctx->stmt), > + OMP_CLAUSE_DEVICE); And probably use a tree tgt_clauses = gimple_omp_target_clauses (ctx->stmt); temporary to make tree c = omp_find_clause (tgt_clauses, OMP_CLAUSE_DEVICE); fit nicely. > + if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c)) > + { > + error_at (gimple_location (stmt), > + "OpenMP runtime API call %qD in a region with " > + "%<device(ancestor)%> clause", fndecl); > + } Single statement in if body shouldn't be wrapped with {}s. > + } > } > } > } > diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-1.c > b/gcc/testsuite/c-c++-common/gomp/target-device-1.c > new file mode 100644 > index 0000000..dafa643 > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/gomp/target-device-1.c > @@ -0,0 +1,34 @@ > +/* { dg-do compile } */ > + > +void > +foo (void) > +{ > + /* Test to ensure that 'device_num' is parsed correctly in device clauses. > */ > + > + int n; Better use foo (int n) such that it isn't an uninitialized use. Or initialize n to something. > + > + #pragma omp target device (1) > + ; > + > + #pragma omp target device (n) > + ; > + > + #pragma omp target device (n + 1) > + ; > + > +end > \ No newline at end of file Please avoid these in all the tests. Otherwise LGTM. Jakub