diff options
author | Tobias Burnus <tburnus@baylibre.com> | 2024-10-19 10:18:30 +0200 |
---|---|---|
committer | Tobias Burnus <tburnus@baylibre.com> | 2024-10-19 10:34:44 +0200 |
commit | ffdfc5b045d7364f76d1f41022b2286108898699 (patch) | |
tree | de3af0304f6511ae8fe18f45bb8a0c555f6eb9d6 /gcc/fortran/expr.cc | |
parent | 4f9b1735ab5eaf93d07d65c81d83cd123a8f3478 (diff) | |
download | gcc-ffdfc5b045d7364f76d1f41022b2286108898699.zip gcc-ffdfc5b045d7364f76d1f41022b2286108898699.tar.gz gcc-ffdfc5b045d7364f76d1f41022b2286108898699.tar.bz2 |
Fortran: Add range-based diagnostic
GCC's diagnostic engine gained a while ago support for ranges, i.e. instead
of pointing at a single character '^', it can also have a '~~~~^~~~~~' range.
This patch adds support for this and adds 9 users for it, which covers the
most common cases. A single '^' can be still useful. Some location data in
gfortran is rather bad - often the matching pattern includes whitespace such
that the before or after location points to the beginning/end of the
whitespace, which can be far of especially when comments and/or continuation
lines are involed. Otherwise, often a '^' still sufficient, albeit wrong
location data only becomes obvious once starting to use ranges.
The 'locus' is extended to support two ways to store the data; hereby
gfc_current_locus always contains the old format (at least during parsing)
and gfc_current_locus shall not be used in trans*.cc. The latter permits
a nice cleanup to just use input_location. Otherwise, the new format is
only used when switching to ranges.
The only reason to convert from location_t to locus occurs in trans*.cc
for the gfc_error (etc.) diagnostic and for gfc_trans_runtime_check; there
are 5 currently 5 such cases. For gfc_* diagnostic, we could think of
another letter besides %L or a modifier like '%lL', if deemed useful.
In any case, the new format is just:
locus->u.location = linemap_position_for_loc_and_offset (line_table,
loc->u.lb->location, loc->nextc - loc->u.lb->line);
locus->nextc = (gfc_char_t *) -1; /* Marker for new format. */
i.e. using the existing location_t location in in the linebuffer (which
points to column 0) and add as offset the actually used column number.
As location_t handles ranges, we just use it also to store them via:
location = make_location (caret, begin, end)
There are a few convenience macros/functions but that's all.
Alongside, a few minor fixes were done: linemap_location_before_p replaces
a line-number based comparison, which does not handle multiple statements
in the same line that ';' allows for.
gcc/fortran/ChangeLog:
* data.cc (gfc_assign_data_value): Use linemap_location_before_p
and GFC_LOCUS_IS_SET.
* decl.cc (gfc_verify_c_interop_param): Make better translatable.
(build_sym, variable_decl, gfc_match_formal_arglist,
gfc_match_subroutine): Add range-based locations, use it in
diagnostic and gobble whitespace for better locations.
* error.cc (gfc_get_location_with_offset): Handle new format.
(gfc_get_location_range): New.
* expr.cc (gfc_check_assign): Use GFC_LOCUS_IS_SET.
* frontend-passes.cc (check_locus_code, check_locus_expr):
Likewise.
(runtime_error_ne): Use GFC_LOCUS_IS_SET.
* gfortran.h (locus): Change lb to union with lb and location.
(GFC_LOCUS_IS_SET): Define.
(gfc_get_location_range): New prototype.
(gfc_new_symbol, gfc_get_symbol, gfc_get_sym_tree,
gfc_get_ha_symbol, gfc_get_ha_sym_tree): Take optional locus
argument.
* io.cc (io_constraint): Use GFC_LOCUS_IS_SET.
* match.cc (gfc_match_sym_tree): Use range locus.
* openmp.cc (gfc_match_omp_variable_list,
gfc_match_omp_doacross_sink): Likewise.
* parse.cc (next_free): Update for locus struct change.
* primary.cc (gfc_match_varspec): Likewise.
(match_variable): Use range locus.
* resolve.cc (find_array_spec): Use GFC_LOCUS_IS_SET.
* scanner.cc (gfc_at_eof, gfc_at_bol, gfc_start_source_files,
gfc_advance_line, gfc_define_undef_line, skip_fixed_comments,
gfc_gobble_whitespace, include_stmt, gfc_new_file): Update
for locus struct change.
* symbol.cc (gfc_new_symbol, gfc_get_sym_tree, gfc_get_symbol,
gfc_get_ha_sym_tree, gfc_get_ha_symbol): Take optional locus.
* trans-array.cc (gfc_trans_array_constructor_value): Use %L not %C.
(gfc_trans_g77_array, gfc_trans_dummy_array_bias,
gfc_trans_class_array, gfc_trans_deferred_array): Replace
gfc_{save,set,restore}_backend_locus by directly using
input_location.
* trans-common.cc (build_equiv_decl, get_init_field): Likewise.
* trans-decl.cc (gfc_get_extern_function_decl, build_function_decl,
build_entry_thunks, gfc_null_and_pass_deferred_len,
gfc_trans_deferred_vars, gfc_trans_use_stmts, finish_oacc_declare,
gfc_generate_block_data): Likewise.
* trans-expr.cc (gfc_copy_class_to_class, gfc_conv_expr): Changes
to avoid gfc_current_locus.
* trans-io.cc (set_error_locus): Likewise.
* trans-openmp.cc (gfc_trans_omp_workshare): Use input_locus directly.
* trans-stmt.cc (gfc_trans_if_1): Likewise and use GFC_LOCUS_IS_SET.
* trans-types.cc (gfc_get_union_type, gfc_get_derived_type): Likewise.
* trans.cc (gfc_locus_from_location): New.
(trans_runtime_error_vararg, gfc_trans_runtime_check): Use location_t
for file + line data.
(gfc_current_backend_file, gfc_save_backend_locus,
gfc_set_backend_locus, gfc_restore_backend_locus): Remove.
(trans_code): Use input_location directly, don't set gfc_current_locus.
* trans.h (gfc_save_backend_locus, gfc_set_backend_locus,
gfc_restore_backend_locus): Remove prototypes.
(gfc_locus_from_location): Add prototype.
gcc/testsuite/ChangeLog:
* gfortran.dg/bounds_check_25.f90: Update expected column
in the diagnostic.
* gfortran.dg/goacc/pr92793-1.f90: Likewise.
* gfortran.dg/gomp/allocate-14.f90: Likewise.
* gfortran.dg/gomp/polymorphic-mapping.f90: Likewise.
* gfortran.dg/gomp/reduction5.f90: Likewise.
* gfortran.dg/gomp/reduction6.f90: Likewise.
Diffstat (limited to 'gcc/fortran/expr.cc')
-rw-r--r-- | gcc/fortran/expr.cc | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index 36baa9b..65bb9f1 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -3912,7 +3912,8 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform, if (lvalue->ts.type == BT_LOGICAL && rvalue->ts.type == BT_LOGICAL) return true; - where = lvalue->where.lb ? &lvalue->where : &rvalue->where; + where = (GFC_LOCUS_IS_SET (lvalue->where) + ? &lvalue->where : &rvalue->where); gfc_error ("Incompatible types in DATA statement at %L; attempted " "conversion of %s to %s", where, gfc_typename (rvalue), gfc_typename (lvalue)); |