diff options
-rw-r--r-- | gcc/ChangeLog | 79 | ||||
-rw-r--r-- | gcc/c-lex.c | 38 | ||||
-rw-r--r-- | gcc/c-ppoutput.c | 99 | ||||
-rw-r--r-- | gcc/cpperror.c | 46 | ||||
-rw-r--r-- | gcc/cppfiles.c | 18 | ||||
-rw-r--r-- | gcc/cpphash.h | 32 | ||||
-rw-r--r-- | gcc/cppinit.c | 2 | ||||
-rw-r--r-- | gcc/cpplex.c | 28 | ||||
-rw-r--r-- | gcc/cpplib.c | 33 | ||||
-rw-r--r-- | gcc/cpplib.h | 6 | ||||
-rw-r--r-- | gcc/cppmacro.c | 12 | ||||
-rw-r--r-- | gcc/cpptrad.c | 23 | ||||
-rw-r--r-- | gcc/line-map.c | 98 | ||||
-rw-r--r-- | gcc/line-map.h | 96 |
14 files changed, 423 insertions, 187 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4dab854..2921e53 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,82 @@ + +2004-02-11 Per Bothner <per@bothner.com> + + Represent column numbers using line-map's source_location. + The "next available source_location" is now managed internally by + line-maps.c rather than by clients. + * line-map.h (struct line_map): New field column_bits. + <from_line>: Rename field to start_location. + (struct line_maps): New fields highest_location and max_column_hint. + (linemap_check_files_exited): New declaration. + (linemap_line_start): New declaration. + (linemap_add): Remove from_line parameter; use highest_location field. + (SOURCE_LINE, LAST_SOURCE_LINE): Modify to use column_bits. + (SOURCE_COLUMN, LAST_SOURCE_LINE_LOCATION): New macros. + (CURRENT_LINE_MAP): Remove macro. + (linemap_position_for_column): New inline function. + * line-map.c (linemap_init): Clear new fields. + (linemap_check_files_exited): New function, extracted from ... + (linemap_free): Use linemap_check_files_exited. + (linemap_add): Remove from_line parameter. Various updates. + (linemap_line_start): New function. + (linemap_lookeup): Update for new field names. + * cpphash.h (struct cpp_reader) <map>: Field removed. Because + linemap_position_for_column may unpredictably change the current map, + it is cleaner and simpler for us to not cache it in cpp_reader. + (struct cpp_buffer): New sysp field. + Changed warned_cplusplus_comments and from_stage3 to bitfields. + * cppinit.c (cpp_read_min_file): pfile->map no longer exists. + * cpplib.c (do_line, do_linemarker, _cpp_do_file_change): Get + current map using linemap_lookup. + (do_linemarker): Also set buffer's sysp field. + (destringize_and_run): No longer need to decrement current line. + * cppfiles.c (_cpp_stack_file): Set sysp from and in buffer. + (search_path_head, open_file_failed): Use buffer's sysp. + (cpp_make_system_header): Get current map using linemap_lookup. + Also set buffer's sysp flag. + * cppmacro.c (_cpp_builtin_macro_text): Likewise use linemap_lookup. + * cpphash.h (CPP_INCREMENT_LINE): New macro. + (struct cpp_buffer): Moved fields saved_cur, saved_rlimit to ... + (struct cpp_reader): ... and adding saved_line_base field. + * cpptrad.c (_cpp_overlay_buffer, _cpp_remove_overlay): + Update accordingly. Don't adjust line. + (_cpp_scan_out_logical_line): Use CPP_INCREMENT_LINE. + * cpphash.c (CPP_IN_SYSTEM_HEADER): Replaced macro by ... + (cpp_in_system_header): ... new inline function, using buffer's sysp. + * cpperror.c (_cpp_begin_message): Update to use cpp_in_system_header. + * cpplex.c (_cpp_lex_direct): Likewise. + * cppmacro.c (_cpp_builtin_macro_text): Likewise. + * cppmacro.c (_cpp_create_definition): Use buffer's sysp field. + * cpplib.h (struct cpp_token): Rename line field to src_loc. + Remove col field as it is now subsumed by src_loc. + * cpperror.c: Update various field, parameter, and macro names. + (print_location): If col==0, try SOURCE_COLUMN of line. + (cpp_error): Use cur_token's src_loc field, rather than line+col. + * cpplib.c (do_diagnostic): Token's src_loc fields replaces line+col. + * cpplex.c (_cpp_process_line_notes, _cpp_lex_direct, + _cpp_skip_block_comment): Use CPP_INCREMENT_LINE. + (_cpp_temp_token): Replace cpp_token's line+col fields by src_loc. + (_cpp_get_fresh_line): Don't need to adjust line for missing newline. + (_cpp_lex_direct): Use linemap_position_for_column. + * c-ppoutput.c (maybe_print_line, print_line): Don't take map + parameter. Instead get it from the line_table global. Adjust callers. + (print): Remove map field. Replace line field to src_line. + (init_pp_output, account_for_newlines, maybe_print_line): Adjust. + (cb_line_change): Use SOURCE_COLUMN. Minor optimizations. + (pp_file_change): Use MAIN_FILE_P since we cannot checked print.map. + Use LAST_SOURCE_LINE_LOCATION to "catch up" after #include. + * cpptrad.c (copy_comment): Rename variable. + * c-lex.c (map): Remove static variable, for same reason we removed + cpp_reader's map field. + (cb_line_change, cb_def_pragma, cb_define, cb_undef): Hence we need + to call linemap_lookup. + (cb_line_change): Token's line field replaced by src_loc. + (fe_file_change): Use MAINFILE_P and LAST_SOURCE_LINE macros. + Don't save new_map. + + * cpphash.h, cpperror.c, cpplib.h: Some renames of fileline to + source_location. + 2004-02-11 Hartmut Penner <hpenner@de.ibm.com> * config/rs6000/altivec.md (*movv4si_internal): At least one diff --git a/gcc/c-lex.c b/gcc/c-lex.c index aba571f..cbd5573 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -42,9 +42,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "splay-tree.h" #include "debug.h" -/* The current line map. */ -static const struct line_map *map; - /* We may keep statistics about how long which files took to compile. */ static int header_time, body_time; static splay_tree file_info_tree; @@ -194,28 +191,27 @@ static void cb_line_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const cpp_token *token, int parsing_args) { - if (token->type == CPP_EOF || parsing_args) - return; - - input_line = SOURCE_LINE (map, token->line); + if (token->type != CPP_EOF && !parsing_args) + { + source_location loc = token->src_loc; + const struct line_map *map = linemap_lookup (&line_table, loc); + input_line = SOURCE_LINE (map, loc); + } } void fe_file_change (const struct line_map *new_map) { if (new_map == NULL) - { - map = NULL; - return; - } + return; if (new_map->reason == LC_ENTER) { /* Don't stack the main buffer on the input stack; we already did in compile_file. */ - if (map != NULL) + if (! MAIN_FILE_P (new_map)) { - int included_at = SOURCE_LINE (new_map - 1, new_map->from_line - 1); + int included_at = LAST_SOURCE_LINE (new_map - 1); input_line = included_at; push_srcloc (new_map->to_file, 1); @@ -250,20 +246,20 @@ fe_file_change (const struct line_map *new_map) in_system_header = new_map->sysp != 0; input_filename = new_map->to_file; input_line = new_map->to_line; - map = new_map; /* Hook for C++. */ extract_interface_info (); } static void -cb_def_pragma (cpp_reader *pfile, unsigned int line) +cb_def_pragma (cpp_reader *pfile, source_location loc) { /* Issue a warning message if we have been asked to do so. Ignore unknown pragmas in system headers unless an explicit -Wunknown-pragmas has been given. */ if (warn_unknown_pragmas > in_system_header) { + const struct line_map *map = linemap_lookup (&line_table, loc); const unsigned char *space, *name; const cpp_token *s; @@ -277,25 +273,27 @@ cb_def_pragma (cpp_reader *pfile, unsigned int line) name = cpp_token_as_text (pfile, s); } - input_line = SOURCE_LINE (map, line); + input_line = SOURCE_LINE (map, loc); warning ("ignoring #pragma %s %s", space, name); } } /* #define callback for DWARF and DWARF2 debug info. */ static void -cb_define (cpp_reader *pfile, unsigned int line, cpp_hashnode *node) +cb_define (cpp_reader *pfile, source_location loc, cpp_hashnode *node) { - (*debug_hooks->define) (SOURCE_LINE (map, line), + const struct line_map *map = linemap_lookup (&line_table, loc); + (*debug_hooks->define) (SOURCE_LINE (map, loc), (const char *) cpp_macro_definition (pfile, node)); } /* #undef callback for DWARF and DWARF2 debug info. */ static void -cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, unsigned int line, +cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location loc, cpp_hashnode *node) { - (*debug_hooks->undef) (SOURCE_LINE (map, line), + const struct line_map *map = linemap_lookup (&line_table, loc); + (*debug_hooks->undef) (SOURCE_LINE (map, loc), (const char *) NODE_NAME (node)); } diff --git a/gcc/c-ppoutput.c b/gcc/c-ppoutput.c index 6b5aa99..2d32445 100644 --- a/gcc/c-ppoutput.c +++ b/gcc/c-ppoutput.c @@ -32,10 +32,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static struct { FILE *outf; /* Stream to write to. */ - const struct line_map *map; /* Logical to physical line mappings. */ const cpp_token *prev; /* Previous token. */ const cpp_token *source; /* Source token for spacing. */ - fileline line; /* Line currently being written. */ + int src_line; /* Line number currently being written. */ unsigned char printed; /* Nonzero if something output at line. */ } print; @@ -45,8 +44,8 @@ static void scan_translation_unit_trad (cpp_reader *); static void account_for_newlines (const unsigned char *, size_t); static int dump_macro (cpp_reader *, cpp_hashnode *, void *); -static void print_line (const struct line_map *, fileline, const char *); -static void maybe_print_line (const struct line_map *, fileline); +static void print_line (source_location, const char *); +static void maybe_print_line (source_location); /* Callback routines for the parser. Most of these are active only in specific modes. */ @@ -112,13 +111,12 @@ init_pp_output (FILE *out_stream) cb->undef = cb_undef; } - /* Initialize the print structure. Setting print.line to -1 here is + /* Initialize the print structure. Setting print.src_line to -1 here is a trick to guarantee that the first token of the file will cause a linemarker to be output by maybe_print_line. */ - print.line = (fileline) -1; + print.src_line = -1; print.printed = 0; print.prev = 0; - print.map = 0; print.outf = out_stream; } @@ -171,13 +169,13 @@ scan_translation_unit (cpp_reader *pfile) } } -/* Adjust print.line for newlines embedded in output. */ +/* Adjust print.src_line for newlines embedded in output. */ static void account_for_newlines (const unsigned char *str, size_t len) { while (len--) if (*str++ == '\n') - print.line++; + print.src_line++; } /* Writes out a traditionally preprocessed file. */ @@ -187,7 +185,7 @@ scan_translation_unit_trad (cpp_reader *pfile) while (_cpp_read_logical_line_trad (pfile)) { size_t len = pfile->out.cur - pfile->out.base; - maybe_print_line (print.map, pfile->out.first_line); + maybe_print_line (pfile->out.first_line); fwrite (pfile->out.base, 1, len, print.outf); print.printed = 1; if (!CPP_OPTION (pfile, discard_comments)) @@ -199,52 +197,56 @@ scan_translation_unit_trad (cpp_reader *pfile) different line to the current one, output the required newlines or a line marker, and return 1. Otherwise return 0. */ static void -maybe_print_line (const struct line_map *map, fileline line) +maybe_print_line (source_location src_loc) { + const struct line_map *map = linemap_lookup (&line_table, src_loc); + int src_line = SOURCE_LINE (map, src_loc); /* End the previous line of text. */ if (print.printed) { putc ('\n', print.outf); - print.line++; + print.src_line++; print.printed = 0; } - if (line >= print.line && line < print.line + 8) + if (src_line >= print.src_line && src_line < print.src_line + 8) { - while (line > print.line) + while (src_line > print.src_line) { putc ('\n', print.outf); - print.line++; + print.src_line++; } } else - print_line (map, line, ""); + print_line (src_loc, ""); } /* Output a line marker for logical line LINE. Special flags are "1" or "2" indicating entering or leaving a file. */ static void -print_line (const struct line_map *map, fileline line, const char *special_flags) +print_line (source_location src_loc, const char *special_flags) { /* End any previous line of text. */ if (print.printed) putc ('\n', print.outf); print.printed = 0; - print.line = line; if (!flag_no_line_commands) { + const struct line_map *map = linemap_lookup (&line_table, src_loc); + size_t to_file_len = strlen (map->to_file); unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1); unsigned char *p; + print.src_line = SOURCE_LINE (map, src_loc); + /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */ p = cpp_quote_string (to_file_quoted, (unsigned char *)map->to_file, to_file_len); *p = '\0'; - fprintf (print.outf, "# %u \"%s\"%s", - SOURCE_LINE (map, print.line), + fprintf (print.outf, "# %u \"%s\"%s", print.src_line, to_file_quoted, special_flags); if (map->sysp == 2) @@ -262,10 +264,12 @@ static void cb_line_change (cpp_reader *pfile, const cpp_token *token, int parsing_args) { + source_location src_loc = token->src_loc; + if (token->type == CPP_EOF || parsing_args) return; - maybe_print_line (print.map, token->line); + maybe_print_line (src_loc); print.prev = 0; print.source = 0; @@ -276,14 +280,12 @@ cb_line_change (cpp_reader *pfile, const cpp_token *token, ought to care. Some things do care; the fault lies with them. */ if (!CPP_OPTION (pfile, traditional)) { + const struct line_map *map = linemap_lookup (&line_table, src_loc); + int spaces = SOURCE_COLUMN (map, src_loc) - 2; print.printed = 1; - if (token->col > 2) - { - unsigned int spaces = token->col - 2; - while (spaces--) - putc (' ', print.outf); - } + while (-- spaces >= 0) + putc (' ', print.outf); } } @@ -291,15 +293,15 @@ static void cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line, const cpp_string *str) { - maybe_print_line (print.map, line); + maybe_print_line (line); fprintf (print.outf, "#ident \"%s\"\n", str->text); - print.line++; + print.src_line++; } static void cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node) { - maybe_print_line (print.map, line); + maybe_print_line (line); fputs ("#define ", print.outf); /* 'D' is whole definition; 'N' is name only. */ @@ -310,28 +312,28 @@ cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node) fputs ((const char *) NODE_NAME (node), print.outf); putc ('\n', print.outf); - print.line++; + print.src_line++; } static void -cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line, +cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line, cpp_hashnode *node) { - maybe_print_line (print.map, line); + maybe_print_line (line); fprintf (print.outf, "#undef %s\n", NODE_NAME (node)); - print.line++; + print.src_line++; } static void -cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line, +cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line, const unsigned char *dir, const char *header, int angle_brackets) { - maybe_print_line (print.map, line); + maybe_print_line (line); if (angle_brackets) fprintf (print.outf, "#%s <%s>\n", dir, header); else fprintf (print.outf, "#%s \"%s\"\n", dir, header); - print.line++; + print.src_line++; } /* Callback called when -fworking-director and -E to emit working @@ -351,8 +353,7 @@ pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir) } /* The file name, line number or system header flags have changed, as - described in MAP. From this point on, the old print.map might be - pointing to freed memory, and so must not be dereferenced. */ + described in MAP. */ void pp_file_change (const struct line_map *map) @@ -365,37 +366,37 @@ pp_file_change (const struct line_map *map) if (map != NULL) { /* First time? */ - if (print.map == NULL) + if (MAIN_FILE_P (map)) { /* Avoid printing foo.i when the main file is foo.c. */ if (!cpp_get_options (parse_in)->preprocessed) - print_line (map, map->from_line, flags); + print_line (map->start_location, flags); } else { /* Bring current file to correct line when entering a new file. */ if (map->reason == LC_ENTER) - maybe_print_line (map - 1, map->from_line - 1); - + { + const struct line_map *from = INCLUDED_FROM (&line_table, map); + maybe_print_line (LAST_SOURCE_LINE_LOCATION (from)); + } if (map->reason == LC_ENTER) flags = " 1"; else if (map->reason == LC_LEAVE) flags = " 2"; - print_line (map, map->from_line, flags); + print_line (map->start_location, flags); } } - - print.map = map; } /* Copy a #pragma directive to the preprocessed output. */ static void cb_def_pragma (cpp_reader *pfile, fileline line) { - maybe_print_line (print.map, line); + maybe_print_line (line); fputs ("#pragma ", print.outf); cpp_output_line (pfile, print.outf); - print.line++; + print.src_line++; } /* Dump out the hash table. */ @@ -408,7 +409,7 @@ dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED) fputs ((const char *) cpp_macro_definition (pfile, node), print.outf); putc ('\n', print.outf); - print.line++; + print.src_line++; } return 1; diff --git a/gcc/cpperror.c b/gcc/cpperror.c index 776f6e8..d572380 100644 --- a/gcc/cpperror.c +++ b/gcc/cpperror.c @@ -29,14 +29,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cpphash.h" #include "intl.h" -static void print_location (cpp_reader *, fileline, unsigned int); +static void print_location (cpp_reader *, source_location, unsigned int); /* Print the logical file location (LINE, COL) in preparation for a diagnostic. Outputs the #include chain if it has changed. A line of zero suppresses the include stack, and outputs the program name instead. */ static void -print_location (cpp_reader *pfile, fileline line, unsigned int col) +print_location (cpp_reader *pfile, source_location line, unsigned int col) { if (line == 0) fprintf (stderr, "%s: ", progname); @@ -50,7 +50,11 @@ print_location (cpp_reader *pfile, fileline line, unsigned int col) lin = SOURCE_LINE (map, line); if (col == 0) - col = 1; + { + col = SOURCE_COLUMN (map, line); + if (col == 0) + col = 1; + } if (lin == 0) fprintf (stderr, "%s:", map->to_file); @@ -64,13 +68,18 @@ print_location (cpp_reader *pfile, fileline line, unsigned int col) } /* Set up for a diagnostic: print the file and line, bump the error - counter, etc. LINE is the logical line number; zero means to print + counter, etc. SRC_LOC is the logical line number; zero means to print at the location of the previously lexed token, which tends to be - the correct place by default. Returns 0 if the error has been - suppressed. */ + the correct place by default. The column number can be specified either + using COLUMN or (if COLUMN==0) extracting SOURCE_COLUMN from SRC_LOC. + (This may seem redundant, but is useful when pre-scanning (cleaning) a line, + when we haven't yet verified whether the current line_map has a + big enough max_column_hint.) + + Returns 0 if the error has been suppressed. */ int -_cpp_begin_message (cpp_reader *pfile, int code, fileline line, - unsigned int column) +_cpp_begin_message (cpp_reader *pfile, int code, + source_location src_loc, unsigned int column) { int level = CPP_DL_EXTRACT (code); @@ -78,7 +87,7 @@ _cpp_begin_message (cpp_reader *pfile, int code, fileline line, { case CPP_DL_WARNING: case CPP_DL_PEDWARN: - if (CPP_IN_SYSTEM_HEADER (pfile) + if (cpp_in_system_header (pfile) && ! CPP_OPTION (pfile, warn_system_headers)) return 0; /* Fall through. */ @@ -105,7 +114,7 @@ _cpp_begin_message (cpp_reader *pfile, int code, fileline line, break; } - print_location (pfile, line, column); + print_location (pfile, src_loc, column); if (CPP_DL_WARNING_P (level)) fputs (_("warning: "), stderr); else if (level == CPP_DL_ICE) @@ -125,8 +134,7 @@ _cpp_begin_message (cpp_reader *pfile, int code, fileline line, void cpp_error (cpp_reader * pfile, int level, const char *msgid, ...) { - fileline line; - unsigned int column; + source_location src_loc; va_list ap; va_start (ap, msgid); @@ -134,18 +142,16 @@ cpp_error (cpp_reader * pfile, int level, const char *msgid, ...) if (CPP_OPTION (pfile, traditional)) { if (pfile->state.in_directive) - line = pfile->directive_line; + src_loc = pfile->directive_line; else - line = pfile->line; - column = 0; + src_loc = pfile->line; } else { - line = pfile->cur_token[-1].line; - column = pfile->cur_token[-1].col; + src_loc = pfile->cur_token[-1].src_loc; } - if (_cpp_begin_message (pfile, level, line, column)) + if (_cpp_begin_message (pfile, level, src_loc, 0)) v_message (msgid, ap); va_end (ap); @@ -154,14 +160,14 @@ cpp_error (cpp_reader * pfile, int level, const char *msgid, ...) /* Print an error at a specific location. */ void cpp_error_with_line (cpp_reader *pfile, int level, - fileline line, unsigned int column, + source_location src_loc, unsigned int column, const char *msgid, ...) { va_list ap; va_start (ap, msgid); - if (_cpp_begin_message (pfile, level, line, column)) + if (_cpp_begin_message (pfile, level, src_loc, column)) v_message (msgid, ap); va_end (ap); diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index c886c89..862be9f 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -640,8 +640,10 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import) if (!should_stack_file (pfile, file, import)) return false; - sysp = MAX ((pfile->map ? pfile->map->sysp : 0), - (file->dir ? file->dir->sysp : 0)); + if (pfile->buffer == NULL || file->dir == NULL) + sysp = 0; + else + sysp = MAX (pfile->buffer->sysp, file->dir->sysp); /* Add the file to the dependencies on its first inclusion. */ if (CPP_OPTION (pfile, deps.style) > !!sysp && !file->stack_count) @@ -658,6 +660,7 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import) buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size, CPP_OPTION (pfile, preprocessed)); buffer->file = file; + buffer->sysp = sysp; /* Initialize controlling macro state. */ pfile->mi_valid = true; @@ -707,7 +710,8 @@ search_path_head (cpp_reader *pfile, const char *fname, int angle_brackets, else if (pfile->quote_ignores_source_dir) dir = pfile->quote_include; else - return make_cpp_dir (pfile, dir_name_of_file (file), pfile->map->sysp); + return make_cpp_dir (pfile, dir_name_of_file (file), + pfile->buffer ? pfile->buffer->sysp : 0); if (dir == NULL) cpp_error (pfile, CPP_DL_ERROR, @@ -756,7 +760,7 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, static void open_file_failed (cpp_reader *pfile, _cpp_file *file) { - int sysp = pfile->map ? pfile->map->sysp: 0; + int sysp = pfile->line > 1 && pfile->buffer ? pfile->buffer->sysp : 0; bool print_dep = CPP_OPTION (pfile, deps.style) > !!sysp; errno = file->err_no; @@ -936,12 +940,14 @@ void cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc) { int flags = 0; + const struct line_map *map = linemap_lookup (pfile->line_table, pfile->line); /* 1 = system header, 2 = system header to be treated as C. */ if (syshdr) flags = 1 + (externc != 0); - _cpp_do_file_change (pfile, LC_RENAME, pfile->map->to_file, - SOURCE_LINE (pfile->map, pfile->line), flags); + pfile->buffer->sysp = flags; + _cpp_do_file_change (pfile, LC_RENAME, map->to_file, + SOURCE_LINE (map, pfile->line), flags); } /* Allow the client to change the current file. Used by the front end diff --git a/gcc/cpphash.h b/gcc/cpphash.h index 6606746..d704c09 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -64,6 +64,13 @@ typedef unsigned char uchar; #define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base) #define CPP_BUF_COL(BUF) CPP_BUF_COLUMN(BUF, (BUF)->cur) +#define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \ + const struct line_map *map \ + = linemap_lookup (PFILE->line_table, PFILE->line); \ + unsigned int line = SOURCE_LINE (map, PFILE->line) + 1; \ + PFILE->line = linemap_line_start (PFILE->line_table, line, COLS_HINT); \ + } while (0) + /* Maximum nesting of cpp_buffers. We use a static limit, partly for efficiency, and partly to limit runaway recursion. */ #define CPP_STACK_MAX 200 @@ -296,24 +303,25 @@ struct cpp_buffer The warning happens only for C89 extended mode with -pedantic on, or for -Wtraditional, and only once per file (otherwise it would be far too noisy). */ - unsigned char warned_cplusplus_comments; + unsigned int warned_cplusplus_comments : 1; /* True if we don't process trigraphs and escaped newlines. True for preprocessed input, command line directives, and _Pragma buffers. */ - unsigned char from_stage3; + unsigned int from_stage3 : 1; /* Nonzero means that the directory to start searching for "" include files has been calculated and stored in "dir" below. */ unsigned char search_cached; + /* One for a system header, two for a C system header file that therefore + needs to be extern "C" protected in C++, and zero otherwise. */ + unsigned char sysp; + /* The directory of the this buffer's file. Its NAME member is not allocated, so we don't need to worry about freeing it. */ struct cpp_dir dir; - /* Used for buffer overlays by cpptrad.c. */ - const uchar *saved_cur, *saved_rlimit; - /* Descriptor for converting from the input character set to the source character set. */ struct cset_converter input_cset_desc; @@ -335,7 +343,6 @@ struct cpp_reader /* Source line tracking. */ struct line_maps *line_table; - const struct line_map *map; fileline line; /* The line of the '#' of the current directive. */ @@ -455,6 +462,9 @@ struct cpp_reader fileline first_line; } out; + /* Used for buffer overlays by cpptrad.c. */ + const uchar *saved_cur, *saved_rlimit, *saved_line_base; + /* Used to save the original line number during traditional preprocessing. */ unsigned int saved_line; @@ -493,12 +503,18 @@ extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; /* Macros. */ -#define CPP_IN_SYSTEM_HEADER(PFILE) ((PFILE)->map && (PFILE)->map->sysp) +static inline int cpp_in_system_header (cpp_reader *); +static inline int +cpp_in_system_header (cpp_reader *pfile) +{ + return pfile->buffer ? pfile->buffer->sysp : 0; +} #define CPP_PEDANTIC(PF) CPP_OPTION (PF, pedantic) #define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, warn_traditional) /* In cpperror.c */ -extern int _cpp_begin_message (cpp_reader *, int, fileline, unsigned int); +extern int _cpp_begin_message (cpp_reader *, int, + source_location, unsigned int); /* In cppmacro.c */ extern void _cpp_free_definition (cpp_hashnode *); diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 0fc9c68..ed91b0e 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -479,7 +479,7 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname) if (CPP_OPTION (pfile, preprocessed)) { read_original_filename (pfile); - fname = pfile->map->to_file; + fname = pfile->line_table->maps[pfile->line_table->used-1].to_file; } return fname; } diff --git a/gcc/cpplex.c b/gcc/cpplex.c index 783732f..c53a9965 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -282,7 +282,7 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment) } buffer->line_base = note->pos; - pfile->line++; + CPP_INCREMENT_LINE (pfile, 0); } else if (_cpp_trigraph_map[note->type]) { @@ -349,12 +349,16 @@ _cpp_skip_block_comment (cpp_reader *pfile) } else if (c == '\n') { + unsigned int cols; buffer->cur = cur - 1; _cpp_process_line_notes (pfile, true); if (buffer->next_line >= buffer->rlimit) return true; _cpp_clean_line (pfile); - pfile->line++; + + cols = buffer->next_line - buffer->line_base; + CPP_INCREMENT_LINE (pfile, cols); + cur = buffer->cur; } } @@ -680,8 +684,7 @@ _cpp_temp_token (cpp_reader *pfile) } result = pfile->cur_token++; - result->line = old->line; - result->col = old->col; + result->src_loc = old->src_loc; return result; } @@ -772,7 +775,7 @@ _cpp_get_fresh_line (cpp_reader *pfile) { /* Only warn once. */ buffer->next_line = buffer->rlimit; - cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line - 1, + cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line, CPP_BUF_COLUMN (buffer, buffer->cur), "no newline at end of file"); } @@ -822,7 +825,7 @@ _cpp_lex_direct (cpp_reader *pfile) if (!pfile->state.in_directive) { /* Tell the compiler the line number of the EOF token. */ - result->line = pfile->line; + result->src_loc = pfile->line; result->flags = BOL; } return result; @@ -839,17 +842,19 @@ _cpp_lex_direct (cpp_reader *pfile) } buffer = pfile->buffer; update_tokens_line: - result->line = pfile->line; + result->src_loc = pfile->line; skipped_white: if (buffer->cur >= buffer->notes[buffer->cur_note].pos && !pfile->overlaid_buffer) { _cpp_process_line_notes (pfile, false); - result->line = pfile->line; + result->src_loc = pfile->line; } c = *buffer->cur++; - result->col = CPP_BUF_COLUMN (buffer, buffer->cur); + + result->src_loc = linemap_position_for_column (pfile->line_table, + CPP_BUF_COLUMN (buffer, buffer->cur)); switch (c) { @@ -859,7 +864,8 @@ _cpp_lex_direct (cpp_reader *pfile) goto skipped_white; case '\n': - pfile->line++; + if (buffer->cur < buffer->rlimit) + CPP_INCREMENT_LINE (pfile, 0); buffer->need_line = true; goto fresh_line; @@ -916,7 +922,7 @@ _cpp_lex_direct (cpp_reader *pfile) cpp_error (pfile, CPP_DL_ERROR, "unterminated comment"); } else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments) - || CPP_IN_SYSTEM_HEADER (pfile))) + || cpp_in_system_header (pfile))) { /* Warn about comments only if pedantically GNUC89, and not in system headers. */ diff --git a/gcc/cpplib.c b/gcc/cpplib.c index fa16859..3165351 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -777,8 +777,9 @@ strtoul_for_line (const uchar *str, unsigned int len, long unsigned int *nump) static void do_line (cpp_reader *pfile) { + const struct line_map *map = linemap_lookup (pfile->line_table, pfile->line); const cpp_token *token; - const char *new_file = pfile->map->to_file; + const char *new_file = map->to_file; unsigned long new_lineno; /* C99 raised the minimum limit on #line numbers. */ @@ -816,7 +817,7 @@ do_line (cpp_reader *pfile) skip_rest_of_line (pfile); _cpp_do_file_change (pfile, LC_RENAME, new_file, new_lineno, - pfile->map->sysp); + map->sysp); } /* Interpret the # 44 "file" [flags] notation, which has slightly @@ -825,10 +826,11 @@ do_line (cpp_reader *pfile) static void do_linemarker (cpp_reader *pfile) { + const struct line_map *map = linemap_lookup (pfile->line_table, pfile->line); const cpp_token *token; - const char *new_file = pfile->map->to_file; + const char *new_file = map->to_file; unsigned long new_lineno; - unsigned int new_sysp = pfile->map->sysp; + unsigned int new_sysp = map->sysp; enum lc_reason reason = LC_RENAME; int flag; @@ -876,6 +878,7 @@ do_linemarker (cpp_reader *pfile) flag = read_flag (pfile, flag); if (flag == 4) new_sysp = 2; + pfile->buffer->sysp = new_sysp; } check_eol (pfile); @@ -900,11 +903,15 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason, const char *to_file, unsigned int file_line, unsigned int sysp) { - pfile->map = linemap_add (pfile->line_table, reason, sysp, - pfile->line, to_file, file_line); + const struct line_map *map = linemap_add (pfile->line_table, reason, sysp, + to_file, file_line); + if (map == NULL) + pfile->line = 0; + else + pfile->line = linemap_line_start (pfile->line_table, map->to_line, 127); if (pfile->cb.file_change) - pfile->cb.file_change (pfile, pfile->map); + pfile->cb.file_change (pfile, map); } /* Report a warning or error detected by the program we are @@ -912,9 +919,7 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason, static void do_diagnostic (cpp_reader *pfile, int code, int print_dir) { - if (_cpp_begin_message (pfile, code, - pfile->cur_token[-1].line, - pfile->cur_token[-1].col)) + if (_cpp_begin_message (pfile, code, pfile->cur_token[-1].src_loc, 0)) { if (print_dir) fprintf (stderr, "#%s ", pfile->directive->name); @@ -1340,7 +1345,6 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in) pfile->context = saved_context; pfile->cur_token = saved_cur_token; pfile->cur_run = saved_cur_run; - pfile->line--; } /* See above comment. For the moment, we'd like @@ -1903,13 +1907,6 @@ cpp_get_callbacks (cpp_reader *pfile) return &pfile->cb; } -/* The line map set. */ -const struct line_maps * -cpp_get_line_maps (cpp_reader *pfile) -{ - return pfile->line_table; -} - /* Copy the given callbacks structure to our own. */ void cpp_set_callbacks (cpp_reader *pfile, cpp_callbacks *cb) diff --git a/gcc/cpplib.h b/gcc/cpplib.h index fd512b6..1183821 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -174,8 +174,7 @@ struct cpp_string occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */ struct cpp_token { - fileline line; /* Logical line of first char of token. */ - unsigned short col; /* Column of first char of token. */ + source_location src_loc; /* Location of first char of token. */ ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */ unsigned char flags; /* flags - see above */ @@ -527,7 +526,6 @@ extern void cpp_set_include_chains (cpp_reader *, cpp_dir *, cpp_dir *, int); through the pointer returned from cpp_get_callbacks, or set them with cpp_set_callbacks. */ extern cpp_options *cpp_get_options (cpp_reader *); -extern const struct line_maps *cpp_get_line_maps (cpp_reader *); extern cpp_callbacks *cpp_get_callbacks (cpp_reader *); extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *); @@ -685,7 +683,7 @@ extern void cpp_errno (cpp_reader *, int, const char *msgid); /* Same as cpp_error, except additionally specifies a position as a (translation unit) physical line and physical column. If the line is zero, then no location is printed. */ -extern void cpp_error_with_line (cpp_reader *, int, fileline, unsigned, +extern void cpp_error_with_line (cpp_reader *, int, source_location, unsigned, const char *msgid, ...) ATTRIBUTE_PRINTF_5; /* In cpplex.c */ diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index c797100..f396a9d 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -116,6 +116,7 @@ static const char * const monthnames[] = const uchar * _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) { + const struct line_map *map; const uchar *result = NULL; unsigned int number = 1; @@ -132,7 +133,7 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) unsigned int len; const char *name; uchar *buf; - const struct line_map *map = pfile->map; + map = linemap_lookup (pfile->line_table, pfile->line); if (node->value.builtin == BT_BASE_FILE) while (! MAIN_FILE_P (map)) @@ -157,14 +158,15 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) break; case BT_SPECLINE: + map = linemap_lookup (pfile->line_table, pfile->line); /* If __LINE__ is embedded in a macro, it must expand to the line of the macro's invocation, not its definition. Otherwise things like assert() will not work properly. */ if (CPP_OPTION (pfile, traditional)) number = pfile->line; else - number = pfile->cur_token[-1].line; - number = SOURCE_LINE (pfile->map, number); + number = pfile->cur_token[-1].src_loc; + number = SOURCE_LINE (map, number); break; /* __STDC__ has the value 1 under normal circumstances. @@ -174,7 +176,7 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) value 0. */ case BT_STDC: { - if (CPP_IN_SYSTEM_HEADER (pfile) + if (cpp_in_system_header (pfile) && CPP_OPTION (pfile, stdc_0_in_system_headers) && !CPP_OPTION (pfile,std)) number = 0; @@ -1488,7 +1490,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) macro->count = 0; macro->fun_like = 0; /* To suppress some diagnostics. */ - macro->syshdr = pfile->map->sysp != 0; + macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; if (CPP_OPTION (pfile, traditional)) ok = _cpp_create_trad_definition (pfile, macro); diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c index 6315b10..f6dc99d 100644 --- a/gcc/cpptrad.c +++ b/gcc/cpptrad.c @@ -148,7 +148,7 @@ static const uchar * copy_comment (cpp_reader *pfile, const uchar *cur, int in_define) { bool unterminated, copy = false; - unsigned int from_line = pfile->line; + source_location src_loc = pfile->line; cpp_buffer *buffer = pfile->buffer; buffer->cur = cur; @@ -158,7 +158,7 @@ copy_comment (cpp_reader *pfile, const uchar *cur, int in_define) unterminated = _cpp_skip_block_comment (pfile); if (unterminated) - cpp_error_with_line (pfile, CPP_DL_ERROR, from_line, 0, + cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0, "unterminated comment"); /* Comments in directives become spaces so that tokens are properly @@ -268,13 +268,14 @@ _cpp_overlay_buffer (cpp_reader *pfile, const uchar *start, size_t len) cpp_buffer *buffer = pfile->buffer; pfile->overlaid_buffer = buffer; - buffer->saved_cur = buffer->cur; - buffer->saved_rlimit = buffer->rlimit; - /* Prevent the ISO lexer from scanning a fresh line. */ - pfile->saved_line = pfile->line--; + pfile->saved_cur = buffer->cur; + pfile->saved_rlimit = buffer->rlimit; + pfile->saved_line_base = buffer->next_line; + pfile->saved_line = pfile->line; buffer->need_line = false; buffer->cur = start; + buffer->line_base = start; buffer->rlimit = start + len; } @@ -284,12 +285,12 @@ _cpp_remove_overlay (cpp_reader *pfile) { cpp_buffer *buffer = pfile->overlaid_buffer; - buffer->cur = buffer->saved_cur; - buffer->rlimit = buffer->saved_rlimit; + buffer->cur = pfile->saved_cur; + buffer->rlimit = pfile->saved_rlimit; + buffer->line_base = pfile->saved_line_base; buffer->need_line = true; pfile->overlaid_buffer = NULL; - pfile->line = pfile->saved_line; } /* Reads a logical line into the output buffer. Returns TRUE if there @@ -404,7 +405,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro) pfile->out.cur = out - 1; pfile->buffer->cur = cur; pfile->buffer->need_line = true; - pfile->line++; + CPP_INCREMENT_LINE (pfile, 0); if ((lex_state == ls_fun_open || lex_state == ls_fun_close) && !pfile->state.in_directive @@ -605,7 +606,7 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro) /* Null directive. Ignore it and don't invalidate the MI optimization. */ pfile->buffer->need_line = true; - pfile->line++; + CPP_INCREMENT_LINE (pfile, 0); result = false; goto done; } diff --git a/gcc/line-map.c b/gcc/line-map.c index be8cf27..a7398bb 100644 --- a/gcc/line-map.c +++ b/gcc/line-map.c @@ -39,8 +39,24 @@ linemap_init (struct line_maps *set) set->trace_includes = false; set->depth = 0; set->cache = 0; + set->highest_location = 0; + set->max_column_hint = 0; } +/* Check for and warn about line_maps entered but not exited. */ + +void +linemap_check_files_exited (struct line_maps *set) +{ + struct line_map *map; + /* Depending upon whether we are handling preprocessed input or + not, this can be a user error or an ICE. */ + for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map); + map = INCLUDED_FROM (set, map)) + fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n", + map->to_file); +} + /* Free a line map set. */ void @@ -48,14 +64,7 @@ linemap_free (struct line_maps *set) { if (set->maps) { - struct line_map *map; - - /* Depending upon whether we are handling preprocessed input or - not, this can be a user error or an ICE. */ - for (map = CURRENT_LINE_MAP (set); ! MAIN_FILE_P (map); - map = INCLUDED_FROM (set, map)) - fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n", - map->to_file); + linemap_check_files_exited (set); free (set->maps); } @@ -72,16 +81,17 @@ linemap_free (struct line_maps *set) FROM_LINE should be monotonic increasing across calls to this function. A call to this function can relocate the previous set of + A call to this function can relocate the previous set of maps, so any stored line_map pointers should not be used. */ const struct line_map * linemap_add (struct line_maps *set, enum lc_reason reason, - unsigned int sysp, source_location from_line, - const char *to_file, unsigned int to_line) + unsigned int sysp, const char *to_file, unsigned int to_line) { struct line_map *map; + source_location start_location = set->highest_location + 1; - if (set->used && from_line < set->maps[set->used - 1].from_line) + if (set->used && start_location < set->maps[set->used - 1].start_location) abort (); if (set->used == set->allocated) @@ -131,17 +141,20 @@ linemap_add (struct line_maps *set, enum lc_reason reason, if (error || to_file == NULL) { to_file = from->to_file; - to_line = LAST_SOURCE_LINE (from) + 1; + to_line = SOURCE_LINE (from, from[1].start_location); sysp = from->sysp; } } map->reason = reason; map->sysp = sysp; - map->from_line = from_line; + map->start_location = start_location; map->to_file = to_file; map->to_line = to_line; set->cache = set->used++; + map->column_bits = 0; + set->highest_location = start_location; + set->max_column_hint = 0; if (reason == LC_ENTER) { @@ -161,6 +174,59 @@ linemap_add (struct line_maps *set, enum lc_reason reason, return map; } +source_location +linemap_line_start (struct line_maps *set, unsigned int to_line, + unsigned int max_column_hint) +{ + struct line_map *map = &set->maps[set->used - 1]; + source_location highest = set->highest_location; + source_location r; + unsigned int last_line = SOURCE_LINE (map, highest); + int line_delta = to_line - last_line; + bool add_map = false; + if (line_delta < 0 + || (line_delta > 10 && line_delta * map->column_bits > 1000) + || (max_column_hint >= (1U << map->column_bits)) + || (max_column_hint <= 80 && map->column_bits >= 10)) + { + add_map = true; + } + else + max_column_hint = set->max_column_hint; + if (add_map) + { + int column_bits; + if (max_column_hint > 1000000 || highest > 0xC0000000) + { + max_column_hint = 0; + if (highest >0xF0000000) + return 0; + column_bits = 0; + } + else + { + column_bits = 7; + while (max_column_hint >= (1U << column_bits)) + column_bits++; + max_column_hint = 1U << column_bits; + } + if (line_delta < 0 + || last_line != map->to_line + || SOURCE_COLUMN (map, highest) >= (1U << column_bits)) + map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp, + map->to_file, to_line); + map->column_bits = column_bits; + r = map->start_location; + } + else + r = highest - SOURCE_COLUMN (map, highest) + + (line_delta << map->column_bits); + if (r > set->highest_location) + set->highest_location = r; + set->max_column_hint = max_column_hint; + return r; +} + /* Given a logical line, returns the map from which the corresponding (source file, line) pair can be deduced. Since the set is built chronologically, the logical lines are monotonic increasing, and so @@ -177,9 +243,9 @@ linemap_lookup (struct line_maps *set, source_location line) cached = &set->maps[mn]; /* We should get a segfault if no line_maps have been added yet. */ - if (line >= cached->from_line) + if (line >= cached->start_location) { - if (mn + 1 == mx || line < cached[1].from_line) + if (mn + 1 == mx || line < cached[1].start_location) return cached; } else @@ -191,7 +257,7 @@ linemap_lookup (struct line_maps *set, source_location line) while (mx - mn > 1) { md = (mn + mx) / 2; - if (set->maps[md].from_line > line) + if (set->maps[md].start_location > line) mx = md; else mn = md; diff --git a/gcc/line-map.h b/gcc/line-map.h index 2780583..6f09fcf 100644 --- a/gcc/line-map.h +++ b/gcc/line-map.h @@ -30,28 +30,35 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (e.g. a #line directive in C). */ enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME}; -/* A logical line number, i,e, an "index" into a line_map. */ +/* A logical line/column number, i.e. an "index" into a line_map. */ /* Long-term, we want to use this to replace struct location_s (in input.h), and effectively typedef source_location location_t. */ typedef unsigned int source_location; typedef source_location fileline; /* deprecated name */ -/* The logical line FROM_LINE maps to physical source file TO_FILE at - line TO_LINE, and subsequently one-to-one until the next line_map - structure in the set. INCLUDED_FROM is an index into the set that - gives the line mapping at whose end the current one was included. - File(s) at the bottom of the include stack have this set to -1. - REASON is the reason for creation of this line map, SYSP is one for - a system header, two for a C system header file that therefore - needs to be extern "C" protected in C++, and zero otherwise. */ +/* Physical source file TO_FILE at line TO_LINE at column 0 is represented + by the logical START_LOCATION. TO_LINE+L at column C is represented by + START_LOCATION+(L*(1<<column_bits))+C, as long as C<(1<<column_bits), + and the result_location is less than the next line_map's start_location. + (The top line is line 1 and the leftmost column is column 1; line/column 0 + means "entire file/line" or "unknown line/column" or "not applicable".) + INCLUDED_FROM is an index into the set that gives the line mapping + at whose end the current one was included. File(s) at the bottom + of the include stack have this set to -1. REASON is the reason for + creation of this line map, SYSP is one for a system header, two for + a C system header file that therefore needs to be extern "C" + protected in C++, and zero otherwise. */ struct line_map { const char *to_file; unsigned int to_line; - source_location from_line; + source_location start_location; int included_from; ENUM_BITFIELD (lc_reason) reason : CHAR_BIT; + /* The sysp field isn't really needed now that it's in cpp_buffer. */ unsigned char sysp; + /* Number of the low-order source_location bits used for a column number. */ + unsigned int column_bits : 8; }; /* A set of chronological line_map structures. */ @@ -73,6 +80,13 @@ struct line_maps /* If true, prints an include trace a la -H. */ bool trace_includes; + + /* Highest source_location "given out". */ + source_location highest_location; + + /* The maximum column number we can quickly allocate. Higher numbers + may require allocating a new line_map. */ + unsigned int max_column_hint; }; /* Initialize a line map set. */ @@ -81,6 +95,19 @@ extern void linemap_init (struct line_maps *); /* Free a line map set. */ extern void linemap_free (struct line_maps *); +/* Check for and warn about line_maps entered but not exited. */ + +extern void linemap_check_files_exited (struct line_maps *); + +/* Return a source_location for the start (i.e. column==0) of + (physical) line TO_LINE in the current source file (as in the + most recent linemap_add). MAX_COLUMN_HINT is the highest column + number we expect to use in this line (but it does not change + the highest_location). */ + +extern source_location linemap_line_start +(struct line_maps *, unsigned int, unsigned int); + /* Add a mapping of logical source line to physical source file and line number. @@ -90,12 +117,12 @@ extern void linemap_free (struct line_maps *); TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their natural values considering the file we are returning to. - FROM_LINE should be monotonic increasing across calls to this + START_LOCATION should be monotonic increasing across calls to this function. A call to this function can relocate the previous set of maps, so any stored line_map pointers should not be used. */ extern const struct line_map *linemap_add (struct line_maps *, enum lc_reason, unsigned int sysp, - source_location from_line, const char *to_file, unsigned int to_line); + const char *to_file, unsigned int to_line); /* Given a logical line, returns the map from which the corresponding (source file, line) pair can be deduced. */ @@ -108,12 +135,21 @@ extern const struct line_map *linemap_lookup extern void linemap_print_containing_files (struct line_maps *, const struct line_map *); -/* Converts a map and logical line to source line. */ -#define SOURCE_LINE(MAP, LINE) ((LINE) + (MAP)->to_line - (MAP)->from_line) +/* Converts a map and a source_location to source line. */ +#define SOURCE_LINE(MAP, LINE) \ + ((((LINE) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line) + +#define SOURCE_COLUMN(MAP, LINE) \ + (((LINE) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1)) /* Returns the last source line within a map. This is the (last) line of the #include, or other directive, that caused a map change. */ -#define LAST_SOURCE_LINE(MAP) SOURCE_LINE ((MAP), (MAP)[1].from_line - 1) +#define LAST_SOURCE_LINE(MAP) \ + SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP)) +#define LAST_SOURCE_LINE_LOCATION(MAP) \ + ((((MAP)[1].start_location - 2 - (MAP)->start_location) \ + & ~((1 << (MAP)->column_bits) - 1)) \ + + (MAP)->start_location) /* Returns the map a given map was included from. */ #define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from]) @@ -121,8 +157,32 @@ extern void linemap_print_containing_files (struct line_maps *, /* Nonzero if the map is at the bottom of the include stack. */ #define MAIN_FILE_P(MAP) ((MAP)->included_from < 0) -/* The current line map. Saves a call to lookup_line if the caller is - sure he is in the scope of the current map. */ -#define CURRENT_LINE_MAP(MAPS) ((MAPS)->maps + (MAPS)->used - 1) +/* Get a source position that for the same line as the most recent + linemap_line_start, but with the specified TO_COLUMN column number. */ +static inline source_location +linemap_position_for_column (struct line_maps *set, unsigned int to_column) +{ + struct line_map *map = &set->maps[set->used - 1]; + source_location r = set->highest_location; + if (__builtin_expect (to_column > set->max_column_hint, 0)) + { + if (r >= 0xC000000 || to_column > 1000000) /* FIXME */ + { + /* Running low on source_locations - disable column numbers. */ + return r - SOURCE_COLUMN (map, r); + } + else + { + r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50); + map = &set->maps[set->used - 1]; + r = set->highest_location; + } + } + r = r - SOURCE_COLUMN (map, r) + to_column; + if (r >= set->highest_location) + set->highest_location = r; + return r; +} + #endif /* !GCC_LINE_MAP_H */ |