https://gcc.gnu.org/g:fd345f3a126a9a32898f897f8074d14fcc535668

commit fd345f3a126a9a32898f897f8074d14fcc535668
Author: Tobias Burnus <tbur...@baylibre.com>
Date:   Thu Jan 23 22:43:48 2025 +0100

    Fortran: Unify gfc_get_location handling; fix expr->ts bug
    
    This commit reduces code duplication by moving gfc_get_location
    from trans.cc to error.cc.  The gcc_assert is now used more often
    and reveald a bug in gfc_match_array_constructor where the union
    expr->ts.u.derived of a derived type is partially overwritten by
    the assignment expr->ts.u.cl->... as a ts.type == BT_CHARACTER check
    was missing.
    
    gcc/fortran/ChangeLog:
    
            * array.cc (gfc_match_array_constructor): Only update the
            character length if the expression is of character type.
            * error.cc (gfc_get_location_with_offset): New; split off
            from ...
            (gfc_format_decoder): ... here; call it.
            * gfortran.h (gfc_get_location_with_offset): New prototype.
            (gfc_get_location): New inline function.
            * trans.cc (gfc_get_location): Remove function definition.
            * trans.h (gfc_get_location): Remove declaration.
    
    (cherry picked from commit c20c9d8408f0ff4677acbd96f4803c191bd13ac6)

Diff:
---
 gcc/fortran/ChangeLog.omp | 15 +++++++++++++++
 gcc/fortran/array.cc      |  2 +-
 gcc/fortran/error.cc      | 34 ++++++++++++++++++++++++----------
 gcc/fortran/gfortran.h    |  7 +++++++
 gcc/fortran/trans.cc      | 12 ------------
 gcc/fortran/trans.h       |  4 ----
 6 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp
index d74e26213801..9e1893e7dc01 100644
--- a/gcc/fortran/ChangeLog.omp
+++ b/gcc/fortran/ChangeLog.omp
@@ -1,3 +1,18 @@
+2025-01-23  Tobias Burnus  <tbur...@baylibre.com>
+
+       Backported from master:
+       2024-10-12  Tobias Burnus  <tbur...@baylibre.com>
+
+       * array.cc (gfc_match_array_constructor): Only update the
+       character length if the expression is of character type.
+       * error.cc (gfc_get_location_with_offset): New; split off
+       from ...
+       (gfc_format_decoder): ... here; call it.
+       * gfortran.h (gfc_get_location_with_offset): New prototype.
+       (gfc_get_location): New inline function.
+       * trans.cc (gfc_get_location): Remove function definition.
+       * trans.h (gfc_get_location): Remove declaration.
+
 2025-01-23  Tobias Burnus  <tbur...@baylibre.com>
 
        Backported from master:
diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc
index e9934f1491b2..1233847a51f0 100644
--- a/gcc/fortran/array.cc
+++ b/gcc/fortran/array.cc
@@ -1370,7 +1370,7 @@ done:
     expr = gfc_get_array_expr (BT_UNKNOWN, 0, &where);
 
   expr->value.constructor = head;
-  if (expr->ts.u.cl)
+  if (expr->ts.type == BT_CHARACTER && expr->ts.u.cl)
     expr->ts.u.cl->length_from_typespec = seen_ts;
 
   *result = expr;
diff --git a/gcc/fortran/error.cc b/gcc/fortran/error.cc
index 65e38b0e8667..d2a99ab3950f 100644
--- a/gcc/fortran/error.cc
+++ b/gcc/fortran/error.cc
@@ -49,6 +49,21 @@ static gfc_error_buffer error_buffer;
 static output_buffer *pp_error_buffer, *pp_warning_buffer;
 static int warningcount_buffered, werrorcount_buffered;
 
+
+/* Return a location_t suitable for 'tree' for a gfortran locus.  During
+   parsing in gfortran, loc->lb->location contains only the line number
+   and LOCATION_COLUMN is 0; hence, the column has to be added when generating
+   locations for 'tree'.  */
+
+location_t
+gfc_get_location_with_offset (locus *loc, unsigned offset)
+{
+  gcc_checking_assert (loc->nextc >= loc->lb->line);
+  return linemap_position_for_loc_and_offset (line_table, loc->lb->location,
+                                             loc->nextc - loc->lb->line
+                                             + offset);
+}
+
 /* Return buffered_p.  */
 bool
 gfc_buffered_p (void)
@@ -1127,6 +1142,7 @@ gfc_format_decoder (pretty_printer *pp, text_info *text, 
const char *spec,
                    int precision, bool wide, bool set_locus, bool hash,
                    bool *quoted, const char **buffer_ptr)
 {
+  unsigned offset = 0;
   switch (*spec)
     {
     case 'C':
@@ -1135,21 +1151,19 @@ gfc_format_decoder (pretty_printer *pp, text_info 
*text, const char *spec,
        static const char *result[2] = { "(1)", "(2)" };
        locus *loc;
        if (*spec == 'C')
-         loc = &gfc_current_locus;
+         {
+           loc = &gfc_current_locus;
+           /* Point %C first offending character not the last good one. */
+           if (*loc->nextc != '\0')
+             offset++;
+         }
        else
          loc = va_arg (*text->m_args_ptr, locus *);
-       gcc_assert (loc->nextc - loc->lb->line >= 0);
-       unsigned int offset = loc->nextc - loc->lb->line;
-       if (*spec == 'C' && *loc->nextc != '\0')
-         /* Point %C first offending character not the last good one. */
-         offset++;
+
        /* If location[0] != UNKNOWN_LOCATION means that we already
           processed one of %C/%L.  */
        int loc_num = text->get_location (0) == UNKNOWN_LOCATION ? 0 : 1;
-       location_t src_loc
-         = linemap_position_for_loc_and_offset (line_table,
-                                                loc->lb->location,
-                                                offset);
+       location_t src_loc = gfc_get_location_with_offset (loc, offset);
        text->set_location (loc_num, src_loc, SHOW_RANGE_WITH_CARET);
        /* Colorize the markers to match the color choices of
           diagnostic_show_locus (the initial location has a color given
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 34dcb4e44c7b..ed1acf667b4f 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3479,6 +3479,13 @@ const char * gfc_get_string (const char *, ...) 
ATTRIBUTE_PRINTF_1;
 bool gfc_find_sym_in_expr (gfc_symbol *, gfc_expr *);
 
 /* error.cc */
+location_t gfc_get_location_with_offset (locus *, unsigned);
+inline location_t
+gfc_get_location (locus *loc)
+{
+  return gfc_get_location_with_offset (loc, 0);
+}
+
 void gfc_error_init_1 (void);
 void gfc_diagnostics_init (void);
 void gfc_diagnostics_finish (void);
diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc
index 342b65092b02..4d8e3ad05c99 100644
--- a/gcc/fortran/trans.cc
+++ b/gcc/fortran/trans.cc
@@ -47,18 +47,6 @@ static gfc_file *gfc_current_backend_file;
 const char gfc_msg_fault[] = N_("Array reference out of bounds");
 
 
-/* Return a location_t suitable for 'tree' for a gfortran locus.  The way the
-   parser works in gfortran, loc->lb->location contains only the line number
-   and LOCATION_COLUMN is 0; hence, the column has to be added when generating
-   locations for 'tree'.  Cf. error.cc's gfc_format_decoder.  */
-
-location_t
-gfc_get_location (locus *loc)
-{
-  return linemap_position_for_loc_and_offset (line_table, loc->lb->location,
-                                             loc->nextc - loc->lb->line);
-}
-
 /* Advance along TREE_CHAIN n times.  */
 
 tree
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index b3be47b835a5..6c6c5029ff93 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -685,10 +685,6 @@ void gfc_finish_decl_attrs (tree, symbol_attribute *);
 /* Allocate the lang-specific part of a decl node.  */
 void gfc_allocate_lang_decl (tree);
 
-/* Get the location suitable for the ME from a gfortran locus; required to get
-   the column number right.  */
-location_t gfc_get_location (locus *);
-
 /* Advance along a TREE_CHAIN.  */
 tree gfc_advance_chain (tree, int);

Reply via email to