This patch actually does not touch linemap but I will appreciate Dodji's comments about the approach. The problem is that in case of long lines, the column hint of 120 might be too small, thus we do not have enough locations within one line to point to a higher column (like 132 in the testcase). Giving as column hint the length of the line seems the right fix.
The other issue that triggers with this testcase is that, even though the column hint allows having line 6 + column 132, since we never generate a location except for 6:0, if a new map is created for the new line, then it will consider that the last location was 6:0 and the new map for line 7 will start at location+1, hence, no offset within line 6 can be represented. My fix here is to create a dummy location for line_len -1 (the last column in the line). This forces the next map to start after this last column's location. I'm not sure if this latter fix is the approach we want to take. If so, then we may want to change linemap.c itself to force new maps to reserve enough locations for any offset in the line instead of doing last_location+1. If not, perhaps the alternative implementation that encodes offsets explicitly throughout the diagnostics machinery would be better. In fact, diagnostic_info already contains an override_column member: struct diagnostic_info { text_info message; location_t location; unsigned int override_column; .... but I don't see a way to change that from within the function that formats %L and %C: static bool gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec, int precision ATTRIBUTE_UNUSED, bool wide ATTRIBUTE_UNUSED, bool plus ATTRIBUTE_UNUSED, bool hash ATTRIBUTE_UNUSED) unless we move override_column to text_info. In fact, diagnostic_info.text_info already contains a locus, which is a pointer to diagnostic_info.location. In any case, the current patch fixes these ICEs and I couldn't trigger new ones. Bootstrapped and regression tested. OK for Fortran? gcc/fortran/ChangeLog: 2014-12-02 Manuel López-Ibáñez <m...@gcc.gnu.org> * scanner.c (gfc_next_char_literal): Use gfc_warning_now. (load_file): Use the line length as the column hint for linemap_line_start. Reserve a location for the highest column of the line. gcc/testsuite/ChangeLog: 2014-12-02 Manuel López-Ibáñez <m...@gcc.gnu.org> * gfortran.dg/line_length_5.f90: New test.
Index: gcc/testsuite/gfortran.dg/line_length_5.f90 =================================================================== --- gcc/testsuite/gfortran.dg/line_length_5.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/line_length_5.f90 (revision 0) @@ -0,0 +1,7 @@ +! { dg-do compile } +! { dg-options "-Wline-truncation" } +print *, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +end + + print *, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +! { dg-warning "Line truncated" " " { target *-*-* } 3 } Index: gcc/fortran/scanner.c =================================================================== --- gcc/fortran/scanner.c (revision 218192) +++ gcc/fortran/scanner.c (working copy) @@ -1054,11 +1054,12 @@ restart: int maxlen = gfc_option.free_line_length; gfc_char_t *current_nextc = gfc_current_locus.nextc; gfc_current_locus.lb->truncated = 0; gfc_current_locus.nextc = gfc_current_locus.lb->line + maxlen; - gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus); + gfc_warning_now (OPT_Wline_truncation, + "Line truncated at %L", &gfc_current_locus); gfc_current_locus.nextc = current_nextc; } if (c != '&') goto done; @@ -1192,11 +1193,12 @@ restart: /* Check to see if the continuation line was truncated. */ if (warn_line_truncation && gfc_current_locus.lb != NULL && gfc_current_locus.lb->truncated) { gfc_current_locus.lb->truncated = 0; - gfc_warning_now_1 ("Line truncated at %L", &gfc_current_locus); + gfc_warning_now (OPT_Wline_truncation, + "Line truncated at %L", &gfc_current_locus); } prev_openmp_flag = openmp_flag; continue_flag = 1; old_loc = gfc_current_locus; @@ -2041,11 +2043,17 @@ load_file (const char *realfilename, con b = XCNEWVAR (gfc_linebuf, gfc_linebuf_header_size + (len + 1) * sizeof (gfc_char_t)); b->location - = linemap_line_start (line_table, current_file->line++, 120); + = linemap_line_start (line_table, current_file->line++, line_len); + /* ??? We add the location for the maximum column possible here, + because otherwise if the next call creates a new line-map, it + will not reserve space for any offset. */ + gcc_assert (line_len > 0); + linemap_position_for_column (line_table, line_len - 1); + b->file = current_file; b->truncated = trunc; wide_strcpy (b->line, line); if (line_head == NULL)