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

Reply via email to