From 67821e3a9e007c34a85bbc3b934031b57eafc903 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Sun, 5 Aug 2001 17:31:25 +0000 Subject: [PATCH] re PR preprocessor/3081 (Preprocessor merges 2 first lines when -imacros is being used) PR preprocessor/3081 * c-lex.c (map): New. (cb_file_change): Update map and use it. (cb_def_pragma, cb_define, cb_undef): Use map and line. (c_lex): Update to use map. * cpperror.c (print_location): Move to using logical line numbers. * cppfiles.c (stack_include_file): Update for new _cpp_do_file_change. (cpp_make_system_header): Similarly. (_cpp_execute_include): Stop line numbering hacks. Store the line we will return to. * cpphash.h (CPP_BUF_LINE): Remove. (struct cpp_buffer): Remove lineno and pseudo_newlines. Add map and return_to_line. (_cpp_do_file_change): Update. * cppinit.c (cpp_start_read): Update line kludge. * cpplex.c (handle_newline): Don't update lineno and pseudo_newlines. (trigraph_ok): Use logical line numbers for diagnostics. (skip_block_comment): Likewise. (skip_whitespace): Likewise. (skip_line_comment): Use pfile->line instead. (_cpp_lex_token): Update to use logical line numbering exclusively. Handle BOL locally. Accept new lines in directives, but keep pfile->line decremented. Diagnostics use logical lines. Update directive handling. * cpplib.c (SEEN_EOL): New. (skip_rest_of_line, check_eol): Use it. (end_directive): Increase line number when accepting the newline at the end of a directive. (run_directive): Simplify. (do_line): Bad LC_LEAVEs become LC_RENAMEs. Update. (_cpp_do_file_change): Update to take buffer line number as an argument, and store the current map in the cpp_reader. Remove line number kludges. (_cpp_do__Pragma): Restore output position after a _Pragma. (cpp_push_buffer): Don't set output line or lineno. (_cpp_pop_buffer): Transfer more info from a faked buffer. Remove line kludge. Set output_line. * cppmacro.c (builtin_macro): Update handling of __LINE__. (parse_arg): Use logical lines. (save_lookahead_token): Save EOFs too now. * cppmain.c (struct printer): Fix comments. (printer_init): Simplify, let caller do errors. (scan_translation_unit, check_multiline_token, dump_macro): Update. (maybe_print_line): Simplify. (print_line): Don't print a linemarker if -P. (cb_define, cb_undef, cb_def_pragma, cb_ident, cb_include): Update. (cb_file_change): Simplify. * line-map.h (LAST_SOURCE_LINE): Fix. (CURRENT_LINE_MAP): New. * gcc.dg/cpp/19951025-1.c: Revert. * gcc.dg/cpp/directiv.c: We no longer process directives that interrupt macro arguments. From-SVN: r44650 --- gcc/ChangeLog | 52 +++++++++ gcc/c-lex.c | 24 ++-- gcc/cpperror.c | 20 ++-- gcc/cppfiles.c | 9 +- gcc/cpphash.h | 16 +-- gcc/cppinit.c | 8 +- gcc/cpplex.c | 128 +++++++++++----------- gcc/cpplib.c | 85 +++++++------- gcc/cppmacro.c | 32 +++--- gcc/cppmain.c | 152 ++++++++++++-------------- gcc/line-map.h | 5 +- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.dg/cpp/19951025-1.c | 4 +- gcc/testsuite/gcc.dg/cpp/directiv.c | 7 -- 14 files changed, 296 insertions(+), 252 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5679160c2d3..70f07e38545 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,55 @@ +2001-08-05 Neil Booth + + PR preprocessor/3081 + * c-lex.c (map): New. + (cb_file_change): Update map and use it. + (cb_def_pragma, cb_define, cb_undef): Use map and line. + (c_lex): Update to use map. + * cpperror.c (print_location): Move to using logical line numbers. + * cppfiles.c (stack_include_file): Update for new _cpp_do_file_change. + (cpp_make_system_header): Similarly. + (_cpp_execute_include): Stop line numbering hacks. Store the + line we will return to. + * cpphash.h (CPP_BUF_LINE): Remove. + (struct cpp_buffer): Remove lineno and pseudo_newlines. + Add map and return_to_line. + (_cpp_do_file_change): Update. + * cppinit.c (cpp_start_read): Update line kludge. + * cpplex.c (handle_newline): Don't update lineno and pseudo_newlines. + (trigraph_ok): Use logical line numbers for diagnostics. + (skip_block_comment): Likewise. + (skip_whitespace): Likewise. + (skip_line_comment): Use pfile->line instead. + (_cpp_lex_token): Update to use logical line numbering exclusively. + Handle BOL locally. Accept new lines in directives, but keep + pfile->line decremented. Diagnostics use logical lines. Update + directive handling. + * cpplib.c (SEEN_EOL): New. + (skip_rest_of_line, check_eol): Use it. + (end_directive): Increase line number when accepting the newline + at the end of a directive. + (run_directive): Simplify. + (do_line): Bad LC_LEAVEs become LC_RENAMEs. Update. + (_cpp_do_file_change): Update to take buffer line number as an + argument, and store the current map in the cpp_reader. Remove + line number kludges. + (_cpp_do__Pragma): Restore output position after a _Pragma. + (cpp_push_buffer): Don't set output line or lineno. + (_cpp_pop_buffer): Transfer more info from a faked buffer. + Remove line kludge. Set output_line. + * cppmacro.c (builtin_macro): Update handling of __LINE__. + (parse_arg): Use logical lines. + (save_lookahead_token): Save EOFs too now. + * cppmain.c (struct printer): Fix comments. + (printer_init): Simplify, let caller do errors. + (scan_translation_unit, check_multiline_token, dump_macro): Update. + (maybe_print_line): Simplify. + (print_line): Don't print a linemarker if -P. + (cb_define, cb_undef, cb_def_pragma, cb_ident, cb_include): Update. + (cb_file_change): Simplify. + * line-map.h (LAST_SOURCE_LINE): Fix. + (CURRENT_LINE_MAP): New. + 2001-08-05 Bernd Schmidt * doloop.c (doloop_modify_runtime): Properly compute number of diff --git a/gcc/c-lex.c b/gcc/c-lex.c index 89e17021fac..971d9cd14a7 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -57,6 +57,9 @@ Boston, MA 02111-1307, USA. */ /* The input filename as understood by CPP, where "" represents stdin. */ static const char *cpp_filename; +/* The current line map. */ +static 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; @@ -301,9 +304,10 @@ cb_file_change (pfile, fc) } update_header_times (fc->map->to_file); + map = fc->map; in_system_header = fc->sysp != 0; - input_filename = fc->map->to_file; - lineno = SOURCE_LINE (fc->map, fc->line); /* Do we need this? */ + input_filename = map->to_file; + lineno = SOURCE_LINE (map, fc->line); /* Hook for C++. */ extract_interface_info (); @@ -312,7 +316,7 @@ cb_file_change (pfile, fc) static void cb_def_pragma (pfile, line) cpp_reader *pfile; - unsigned int line ATTRIBUTE_UNUSED; + unsigned int line; { /* Issue a warning message if we have been asked to do so. Ignore unknown pragmas in system headers unless an explicit @@ -328,7 +332,7 @@ cb_def_pragma (pfile, line) if (s.type == CPP_NAME) name = cpp_token_as_text (pfile, &s); - lineno = cpp_get_line (parse_in)->line; + lineno = SOURCE_LINE (map, line); if (name) warning ("ignoring #pragma %s %s", space, name); else @@ -340,21 +344,21 @@ cb_def_pragma (pfile, line) static void cb_define (pfile, line, node) cpp_reader *pfile; - unsigned int line ATTRIBUTE_UNUSED; + unsigned int line; cpp_hashnode *node; { - (*debug_hooks->define) (cpp_get_line (pfile)->line, + (*debug_hooks->define) (SOURCE_LINE (map, line), (const char *) cpp_macro_definition (pfile, node)); } /* #undef callback for DWARF and DWARF2 debug info. */ static void cb_undef (pfile, line, node) - cpp_reader *pfile; - unsigned int line ATTRIBUTE_UNUSED; + cpp_reader *pfile ATTRIBUTE_UNUSED; + unsigned int line; cpp_hashnode *node; { - (*debug_hooks->undef) (cpp_get_line (pfile)->line, + (*debug_hooks->undef) (SOURCE_LINE (map, line), (const char *) NODE_NAME (node)); } @@ -763,7 +767,7 @@ c_lex (value) /* The C++ front end does horrible things with the current line number. To ensure an accurate line number, we must reset it every time we return a token. */ - lineno = cpp_get_line (parse_in)->line; + lineno = SOURCE_LINE (map, cpp_get_line (parse_in)->line); *value = NULL_TREE; type = tok.type; diff --git a/gcc/cpperror.c b/gcc/cpperror.c index f10198288f0..4ed4de6273a 100644 --- a/gcc/cpperror.c +++ b/gcc/cpperror.c @@ -108,23 +108,17 @@ print_location (pfile, filename, pos) { struct line_map *map; - line = pfile->line; if (type == BUF_PRAGMA) - { - buffer = buffer->prev; - col = CPP_BUF_COL (buffer); - } + buffer = buffer->prev; - map = lookup_line (&pfile->line_maps, line); if (pos == 0) - { - pos = cpp_get_line (pfile); - line = SOURCE_LINE (map, line); - } - else - line = pos->line; - col = pos->col; + pos = cpp_get_line (pfile); + map = lookup_line (&pfile->line_maps, pos->line); + line = SOURCE_LINE (map, pos->line); + if (filename == 0) + filename = map->to_file; + col = pos->col; if (col == 0) col = 1; diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index fb01145d8cd..8af65c8925f 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -337,9 +337,7 @@ stack_include_file (pfile, inc) pfile->include_depth++; /* Generate the call back. */ - fp->lineno = 0; - _cpp_do_file_change (pfile, LC_ENTER); - fp->lineno = 1; + _cpp_do_file_change (pfile, LC_ENTER, 1); } /* Read the file referenced by INC into the file cache. @@ -579,7 +577,8 @@ cpp_make_system_header (pfile, syshdr, externc) if (syshdr) flags = 1 + (externc != 0); pfile->buffer->sysp = flags; - _cpp_do_file_change (pfile, LC_RENAME); + _cpp_do_file_change (pfile, LC_RENAME, + SOURCE_LINE (pfile->map, pfile->line)); } /* Report on all files that might benefit from a multiple include guard. @@ -679,8 +678,8 @@ _cpp_execute_include (pfile, header, type) if (header->type == CPP_HEADER_NAME) pfile->system_include_depth++; + pfile->buffer->return_to_line = SOURCE_LINE (pfile->map, pfile->line); stack_include_file (pfile, inc); - pfile->line++; /* Fake the '\n' at the end of #include. */ if (type == IT_IMPORT) _cpp_never_reread (inc); diff --git a/gcc/cpphash.h b/gcc/cpphash.h index 1abeb574990..1ba4282561b 100644 --- a/gcc/cpphash.h +++ b/gcc/cpphash.h @@ -35,7 +35,6 @@ struct directive; /* Deliberately incomplete. */ #define CPP_OPTION(PFILE, OPTION) ((PFILE)->opts.OPTION) #define CPP_BUFFER(PFILE) ((PFILE)->buffer) -#define CPP_BUF_LINE(BUF) ((BUF)->lineno) #define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base + (BUF)->col_adjust) #define CPP_BUF_COL(BUF) CPP_BUF_COLUMN(BUF, (BUF)->cur) @@ -194,8 +193,10 @@ struct cpp_buffer /* Token column position adjustment owing to tabs in whitespace. */ unsigned int col_adjust; - /* Line number at line_base (above). */ - unsigned int lineno; + /* The line of the buffer that we return to after a #include. + Strictly this is redundant, since it can be calculated from the + line maps, but it is clearest to save it here. */ + unsigned int return_to_line; /* Contains PREV_WHITE and/or AVOID_LPASTE. */ unsigned char saved_flags; @@ -251,12 +252,10 @@ struct cpp_reader /* Lexer state. */ struct lexer_state state; - /* Source line tracking. Subtract pseudo_newlines from the actual - line number to get the line number of preprocessed output. Used - for escaped newlines and macro args that cross multiple lines. */ + /* Source line tracking. */ struct line_maps line_maps; + struct line_map *map; unsigned int line; - unsigned int pseudo_newlines; /* The position of the last lexed token and last lexed directive. */ cpp_lexer_pos lexer_pos; @@ -446,7 +445,8 @@ extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *)); extern void _cpp_do__Pragma PARAMS ((cpp_reader *)); extern void _cpp_init_directives PARAMS ((cpp_reader *)); extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *)); -extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum lc_reason)); +extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum lc_reason, + unsigned int)); extern void _cpp_pop_buffer PARAMS ((cpp_reader *)); /* Utility routines and macros. */ diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 6d4c7a0aa34..f1b6b24f0aa 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -949,10 +949,10 @@ cpp_start_read (pfile, fname) p = q; } - /* This was zero when the initial buffer was stacked; so we must - make up for a non-existent new line, as well as the intervening - macro definitions, by setting it to 1. */ - pfile->line = 1; + /* Hopefully a short-term kludge. We stacked the main file at line + zero. The intervening macro definitions have messed up line + numbering, so we need to restore it. */ + pfile->lexer_pos.output_line = pfile->line = 0; /* The -imacros files can be scanned now, but the -include files have to be pushed onto the buffer stack and processed later, diff --git a/gcc/cpplex.c b/gcc/cpplex.c index e0002beac45..f9c4bb9ab0c 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -132,11 +132,8 @@ handle_newline (pfile, newline_char) cppchar_t next = EOF; pfile->line++; - pfile->pseudo_newlines++; - buffer = pfile->buffer; buffer->col_adjust = 0; - buffer->lineno++; buffer->line_base = buffer->cur; /* Handle CR-LF and LF-CR combinations, get the next character. */ @@ -173,15 +170,16 @@ trigraph_ok (pfile, from_char) if (CPP_OPTION (pfile, warn_trigraphs) && !pfile->state.lexing_comment) { cpp_buffer *buffer = pfile->buffer; + if (accept) - cpp_warning_with_line (pfile, buffer->lineno, CPP_BUF_COL (buffer) - 2, + cpp_warning_with_line (pfile, pfile->line, CPP_BUF_COL (buffer) - 2, "trigraph ??%c converted to %c", (int) from_char, (int) _cpp_trigraph_map[from_char]); else if (buffer->cur != buffer->last_Wtrigraphs) { buffer->last_Wtrigraphs = buffer->cur; - cpp_warning_with_line (pfile, buffer->lineno, + cpp_warning_with_line (pfile, pfile->line, CPP_BUF_COL (buffer) - 2, "trigraph ??%c ignored", (int) from_char); } @@ -344,8 +342,8 @@ skip_block_comment (pfile) { prevc = c, c = *buffer->cur++; if (c != '/') - cpp_warning_with_line (pfile, CPP_BUF_LINE (buffer), - CPP_BUF_COL (buffer), + cpp_warning_with_line (pfile, pfile->line, + CPP_BUF_COL (buffer) - 2, "\"/*\" within comment"); } goto next_char; @@ -373,7 +371,7 @@ skip_line_comment (pfile) cpp_reader *pfile; { cpp_buffer *buffer = pfile->buffer; - unsigned int orig_lineno = buffer->lineno; + unsigned int orig_line = pfile->line; cppchar_t c; pfile->state.lexing_comment = 1; @@ -391,7 +389,7 @@ skip_line_comment (pfile) pfile->state.lexing_comment = 0; buffer->read_ahead = c; /* Leave any newline for caller. */ - return orig_lineno != buffer->lineno; + return orig_line != pfile->line; } /* pfile->buffer->cur is one beyond the \t character. Update @@ -437,7 +435,7 @@ skip_whitespace (pfile, c) } } else if (pfile->state.in_directive && CPP_PEDANTIC (pfile)) - cpp_pedwarn_with_line (pfile, CPP_BUF_LINE (buffer), + cpp_pedwarn_with_line (pfile, pfile->line, CPP_BUF_COL (buffer), "%s in preprocessing directive", c == '\f' ? "form feed" : "vertical tab"); @@ -865,17 +863,16 @@ _cpp_lex_token (pfile, result) cppchar_t c; cpp_buffer *buffer; const unsigned char *comment_start; - unsigned char bol; + int bol; - skip: - bol = pfile->state.next_bol; - done_directive: + next_token: buffer = pfile->buffer; - pfile->state.next_bol = 0; result->flags = buffer->saved_flags; buffer->saved_flags = 0; + bol = (buffer->cur <= buffer->line_base + 1 + && pfile->lexer_pos.output_line == pfile->line); next_char: - pfile->lexer_pos.line = buffer->lineno; + pfile->lexer_pos.line = pfile->line; result->line = pfile->line; next_char2: pfile->lexer_pos.col = CPP_BUF_COLUMN (buffer, buffer->cur); @@ -893,22 +890,29 @@ _cpp_lex_token (pfile, result) switch (c) { case EOF: - if (!pfile->state.in_directive) + /* To prevent bogus diagnostics, only pop the buffer when + in-progress directives and arguments have been taken care of. + Decrement the line to terminate an in-progress directive. */ + if (pfile->state.in_directive) + pfile->line--; + else if (! pfile->state.parsing_args) { unsigned char ret = pfile->buffer->return_at_eof; /* Non-empty files should end in a newline. Don't warn for command line and _Pragma buffers. */ - if (pfile->lexer_pos.col != 0 && !buffer->from_stage3) - cpp_pedwarn (pfile, "no newline at end of file"); + if (pfile->lexer_pos.col != 0) + { + /* Account for the missing \n. */ + pfile->line++; + if (!buffer->from_stage3) + cpp_pedwarn (pfile, "no newline at end of file"); + } + _cpp_pop_buffer (pfile); if (pfile->buffer && !ret) - { - bol = 1; - goto done_directive; - } + goto next_token; } - pfile->state.next_bol = 1; result->type = CPP_EOF; return; @@ -918,36 +922,41 @@ _cpp_lex_token (pfile, result) goto next_char2; case '\n': case '\r': - if (!pfile->state.in_directive) + if (pfile->state.in_directive) { - handle_newline (pfile, c); - if (!pfile->state.parsing_args) - pfile->pseudo_newlines = 0; - bol = 1; - pfile->lexer_pos.output_line = buffer->lineno; - /* This is a new line, so clear any white space flag. - Newlines in arguments are white space (6.10.3.10); - parse_arg takes care of that. */ - result->flags &= ~(PREV_WHITE | AVOID_LPASTE); - goto next_char; + result->type = CPP_EOF; + if (pfile->state.parsing_args) + buffer->read_ahead = c; + else + { + handle_newline (pfile, c); + /* Decrementing pfile->line allows directives to + recognise that the newline has been seen, and also + means that diagnostics don't point to the next line. */ + pfile->lexer_pos.output_line = pfile->line--; + } + return; } - /* Don't let directives spill over to the next line. */ - buffer->read_ahead = c; - pfile->state.next_bol = 1; - result->type = CPP_EOF; - /* Don't break; pfile->state.skipping might be true. */ - return; + handle_newline (pfile, c); + /* This is a new line, so clear any white space flag. Newlines + in arguments are white space (6.10.3.10); parse_arg takes + care of that. */ + result->flags &= ~(PREV_WHITE | AVOID_LPASTE); + bol = 1; + if (pfile->state.parsing_args != 2) + pfile->lexer_pos.output_line = pfile->line; + goto next_char; case '?': case '\\': /* These could start an escaped newline, or '?' a trigraph. Let skip_escaped_newlines do all the work. */ { - unsigned int lineno = buffer->lineno; + unsigned int line = pfile->line; c = skip_escaped_newlines (buffer, c); - if (lineno != buffer->lineno) + if (line != pfile->line) /* We had at least one escaped newline of some sort, and the next character is in buffer->read_ahead. Update the token's line and column. */ @@ -1026,9 +1035,7 @@ _cpp_lex_token (pfile, result) if (c == '*') { if (skip_block_comment (pfile)) - cpp_error_with_line (pfile, pfile->lexer_pos.line, - pfile->lexer_pos.col, - "unterminated comment"); + cpp_error (pfile, "unterminated comment"); } else { @@ -1212,26 +1219,21 @@ _cpp_lex_token (pfile, result) macro invocation, and proceed to process the directive. */ if (pfile->state.parsing_args) { + pfile->lexer_pos.output_line = pfile->line; if (pfile->state.parsing_args == 2) - cpp_error (pfile, - "directives may not be used inside a macro argument"); - - /* Put a '#' in lookahead, return CPP_EOF for parse_arg. */ - buffer->extra_char = buffer->read_ahead; - buffer->read_ahead = '#'; - pfile->state.next_bol = 1; - result->type = CPP_EOF; - - /* Get whitespace right - newline_in_args sets it. */ - if (pfile->lexer_pos.col == 1) - result->flags &= ~(PREV_WHITE | AVOID_LPASTE); + { + cpp_error (pfile, + "directives may not be used inside a macro argument"); + result->type = CPP_EOF; + } } - else + /* in_directive can be true inside a _Pragma. */ + else if (!pfile->state.in_directive) { - /* This is the hash introducing a directive. */ + /* This is the hash introducing a directive. If the return + value is false, it is an assembler #. */ if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE)) - goto done_directive; /* bol still 1. */ - /* This is in fact an assembler #. */ + goto next_token; } break; @@ -1283,7 +1285,7 @@ _cpp_lex_token (pfile, result) } if (!pfile->state.in_directive && pfile->state.skipping) - goto skip; + goto next_char; /* If not in a directive, this token invalidates controlling macros. */ if (!pfile->state.in_directive) diff --git a/gcc/cpplib.c b/gcc/cpplib.c index d46fb93154d..5932a44d1d5 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -178,6 +178,8 @@ DIRECTIVE_TABLE #undef D #undef DIRECTIVE_TABLE +#define SEEN_EOL() (pfile->lexer_pos.output_line > pfile->line) + /* Skip any remaining tokens in a directive. */ static void skip_rest_of_line (pfile) @@ -194,7 +196,7 @@ skip_rest_of_line (pfile) _cpp_pop_context (pfile); /* Sweep up all tokens remaining on the line. */ - while (!pfile->state.next_bol) + while (! SEEN_EOL ()) _cpp_lex_token (pfile, &token); } @@ -203,7 +205,7 @@ static void check_eol (pfile) cpp_reader *pfile; { - if (!pfile->state.next_bol) + if (! SEEN_EOL ()) { cpp_token token; @@ -240,7 +242,11 @@ end_directive (pfile, skip_line) { /* We don't skip for an assembler #. */ if (skip_line) - skip_rest_of_line (pfile); + { + skip_rest_of_line (pfile); + /* "Accept" the newline now. */ + pfile->line++; + } /* Restore state. */ pfile->la_write = pfile->la_saved; @@ -395,19 +401,9 @@ run_directive (pfile, dir_no, type, buf, count) const char *buf; size_t count; { - unsigned int output_line = pfile->lexer_pos.output_line; cpp_buffer *buffer; buffer = cpp_push_buffer (pfile, (const U_CHAR *) buf, count, type, 0, 1); - - if (dir_no == T_PRAGMA) - { - /* A kludge to avoid line markers for _Pragma. */ - pfile->lexer_pos.output_line = output_line; - /* Avoid interpretation of directives in a _Pragma string. */ - pfile->state.next_bol = 0; - } - start_directive (pfile); pfile->state.prevent_expansion++; pfile->directive = &dtable[dir_no]; @@ -779,8 +775,11 @@ do_line (pfile) else if (reason == LC_LEAVE) { if (buffer->type != BUF_FAKE) - cpp_warning (pfile, "file \"%s\" left but not entered", - buffer->nominal_fname); + { + cpp_warning (pfile, "file \"%s\" left but not entered", + buffer->nominal_fname); + reason = LC_RENAME; + } else { _cpp_pop_buffer (pfile); @@ -789,9 +788,6 @@ do_line (pfile) if (strcmp (buffer->nominal_fname, fname)) cpp_warning (pfile, "expected to return to file \"%s\"", buffer->nominal_fname); - if (buffer->lineno + 1 != new_lineno) - cpp_warning (pfile, "expected to return to line number %u", - buffer->lineno + 1); if (buffer->sysp != sysp) cpp_warning (pfile, "header flags for \"%s\" have changed", buffer->nominal_fname); @@ -810,30 +806,29 @@ do_line (pfile) } end_directive (pfile, 1); - buffer->lineno = new_lineno - 1; - _cpp_do_file_change (pfile, reason); + _cpp_do_file_change (pfile, reason, new_lineno); } -/* Arrange the file_change callback. It is assumed that the next line - is given by incrementing buffer->lineno and pfile->line. */ +/* Arrange the file_change callback. pfile->line has changed to + FILE_LINE of the current buffer, for reason REASON. */ void -_cpp_do_file_change (pfile, reason) +_cpp_do_file_change (pfile, reason, file_line) cpp_reader *pfile; enum lc_reason reason; + unsigned int file_line; { cpp_buffer *buffer; - struct line_map *map; buffer = pfile->buffer; - map = add_line_map (&pfile->line_maps, reason, - pfile->line + 1, buffer->nominal_fname, buffer->lineno + 1); + pfile->map = add_line_map (&pfile->line_maps, reason, + pfile->line, buffer->nominal_fname, file_line); if (pfile->cb.file_change) { cpp_file_change fc; - fc.map = map; - fc.line = pfile->line + 1; + fc.map = pfile->map; + fc.line = pfile->line; fc.reason = reason; fc.sysp = buffer->sysp; fc.externc = CPP_OPTION (pfile, cplusplus) && buffer->sysp == 2; @@ -1195,16 +1190,19 @@ _cpp_do__Pragma (pfile) cpp_token string; unsigned char *buffer; unsigned int len; + cpp_lexer_pos orig_pos; + orig_pos = pfile->lexer_pos; if (get__Pragma_string (pfile, &string)) + cpp_error (pfile, "_Pragma takes a parenthesized string literal"); + else { - cpp_error (pfile, "_Pragma takes a parenthesized string literal"); - return; + buffer = destringize (&string.val.str, &len); + run_directive (pfile, T_PRAGMA, BUF_PRAGMA, (char *) buffer, len); + free ((PTR) buffer); + pfile->lexer_pos = orig_pos; + pfile->line = pfile->lexer_pos.line; } - - buffer = destringize (&string.val.str, &len); - run_directive (pfile, T_PRAGMA, BUF_PRAGMA, (char *) buffer, len); - free ((PTR) buffer); } /* Just ignore #sccs, on systems where we define it at all. */ @@ -1815,8 +1813,6 @@ cpp_push_buffer (pfile, buffer, len, type, filename, return_at_eof) /* Preprocessed files, builtins, _Pragma and command line options don't do trigraph and escaped newline processing. */ new->from_stage3 = type != BUF_FILE || CPP_OPTION (pfile, preprocessed); - - pfile->lexer_pos.output_line = 1; } if (*filename == '\0') @@ -1827,7 +1823,6 @@ cpp_push_buffer (pfile, buffer, len, type, filename, return_at_eof) new->prev = pfile->buffer; new->pfile = pfile; new->include_stack_listed = 0; - new->lineno = 1; new->return_at_eof = return_at_eof; pfile->state.next_bol = 1; @@ -1857,7 +1852,11 @@ _cpp_pop_buffer (pfile) "unterminated #%s", dtable[ifs->type].name); if (buffer->type == BUF_FAKE) - buffer->prev->cur = buffer->cur; + { + buffer->prev->cur = buffer->cur; + buffer->prev->line_base = buffer->line_base; + buffer->prev->read_ahead = buffer->read_ahead; + } else if (buffer->type == BUF_FILE) _cpp_pop_file_buffer (pfile, buffer); @@ -1877,8 +1876,7 @@ _cpp_pop_buffer (pfile) if (pfile->directive == &dtable[T_LINE]) break; - pfile->line--; /* We have a '\n' at the end of #include. */ - _cpp_do_file_change (pfile, LC_LEAVE); + _cpp_do_file_change (pfile, LC_LEAVE, pfile->buffer->return_to_line); if (pfile->buffer->type == BUF_FILE) break; @@ -1888,7 +1886,12 @@ _cpp_pop_buffer (pfile) obstack_free (&pfile->buffer_ob, buffer); - pfile->state.skipping = 0; /* In case missing #endif. */ + /* The output line can fall out of sync if we missed the final + newline from the previous buffer, for example because of an + unterminated comment. Similarly, skipping needs to be cleared in + case of a missing #endif. */ + pfile->lexer_pos.output_line = pfile->line; + pfile->state.skipping = 0; } void diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index d45a949c629..1618e7e102f 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -175,7 +175,8 @@ builtin_macro (pfile, token) /* 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. */ - make_number_token (pfile, token, cpp_get_line (pfile)->line); + make_number_token (pfile, token, + SOURCE_LINE (pfile->map, cpp_get_line (pfile)->line)); break; case BT_STDC: @@ -484,9 +485,9 @@ parse_arg (pfile, arg, variadic) } /* Newlines in arguments are white space (6.10.3.10). */ - line = pfile->lexer_pos.output_line; + line = pfile->line; cpp_get_token (pfile, token); - if (line != pfile->lexer_pos.output_line) + if (line != pfile->line) token->flags |= PREV_WHITE; result = token->type; @@ -1027,22 +1028,19 @@ save_lookahead_token (pfile, token) cpp_reader *pfile; const cpp_token *token; { - if (token->type != CPP_EOF) + cpp_lookahead *la = pfile->la_write; + cpp_token_with_pos *twp; + + if (la->count == la->cap) { - cpp_lookahead *la = pfile->la_write; - cpp_token_with_pos *twp; - - if (la->count == la->cap) - { - la->cap += la->cap + 8; - la->tokens = (cpp_token_with_pos *) - xrealloc (la->tokens, la->cap * sizeof (cpp_token_with_pos)); - } - - twp = &la->tokens[la->count++]; - twp->token = *token; - twp->pos = *cpp_get_line (pfile); + la->cap += la->cap + 8; + la->tokens = (cpp_token_with_pos *) + xrealloc (la->tokens, la->cap * sizeof (cpp_token_with_pos)); } + + twp = &la->tokens[la->count++]; + twp->token = *token; + twp->pos = *cpp_get_line (pfile); } static void diff --git a/gcc/cppmain.c b/gcc/cppmain.c index 63026102600..86d245ab9f1 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -30,12 +30,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. cpp_get_token back into a text file. */ struct printer { - FILE *outf; /* stream to write to. */ - const char *last_fname; /* previous file name. */ - const char *syshdr_flags; /* system header flags, if any. */ - unsigned int lineno; /* line currently being written. */ - unsigned char printed; /* nonzero if something output at lineno. */ - struct line_map *map; /* logical to physical line mappings. */ + FILE *outf; /* Stream to write to. */ + const char *filename; /* Name of current file. */ + const char *syshdr_flags; /* System header flags, if any. */ + unsigned int line; /* Line currently being written. */ + unsigned char printed; /* Nonzero if something output at line. */ + struct line_map *map; /* Logical to physical line mappings. */ }; int main PARAMS ((int, char **)); @@ -46,10 +46,10 @@ static void setup_callbacks PARAMS ((void)); /* General output routines. */ static void scan_translation_unit PARAMS ((cpp_reader *)); static void check_multiline_token PARAMS ((cpp_string *)); -static int printer_init PARAMS ((cpp_reader *)); +static void printer_init PARAMS ((void)); static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *)); -static void print_line PARAMS ((const char *)); +static void print_line PARAMS ((unsigned int, const char *)); static void maybe_print_line PARAMS ((unsigned int)); /* Callback routines for the parser. Most of these are active only @@ -144,8 +144,12 @@ do_preprocessing (argc, argv) /* Open the output now. We must do so even if no_output is on, because there may be other output than from the actual preprocessing (e.g. from -dM). */ - if (printer_init (pfile)) - return; + printer_init (); + if (print.outf == NULL) + { + cpp_notice_from_errno (pfile, options->out_fname); + return; + } setup_callbacks (); @@ -216,7 +220,7 @@ scan_translation_unit (pfile) break; line = cpp_get_line (pfile)->output_line; - if (print.lineno != line) + if (print.line != line) { unsigned int col = cpp_get_line (pfile)->col; @@ -253,7 +257,7 @@ scan_translation_unit (pfile) } } -/* Adjust print.lineno for newlines embedded in tokens. */ +/* Adjust print.line for newlines embedded in tokens. */ static void check_multiline_token (str) cpp_string *str; @@ -262,85 +266,69 @@ check_multiline_token (str) for (i = 0; i < str->len; i++) if (str->text[i] == '\n') - print.lineno++; + print.line++; } /* Initialize a cpp_printer structure. As a side effect, open the - output file. */ -static int -printer_init (pfile) - cpp_reader *pfile; + output file. If print.outf is NULL an error occurred. */ +static void +printer_init () { - print.last_fname = 0; - print.lineno = 0; + /* Setting print.line to -1 here guarantees that the first token of + the file will cause a linemarker to be output by maybe_print_line. */ + print.line = (unsigned int) -1; print.printed = 0; + print.map = 0; if (options->out_fname[0] == '\0') print.outf = stdout; else - { - print.outf = fopen (options->out_fname, "w"); - if (! print.outf) - { - cpp_notice_from_errno (pfile, options->out_fname); - return 1; - } - } - - return 0; + print.outf = fopen (options->out_fname, "w"); } -/* Newline-terminate any output line currently in progress. If - appropriate, write the current line number to the output, or pad - with newlines so the output line matches the current line. */ +/* If the token read on logical line LINE needs to be output on a + 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 (line) unsigned int line; { - /* End the previous line of text (probably only needed until we get - multi-line tokens fixed). */ + /* End the previous line of text. */ if (print.printed) { putc ('\n', print.outf); - print.lineno++; + print.line++; print.printed = 0; } - if (options->no_line_commands) + if (line >= print.line && line < print.line + 8) { - print.lineno = line; - return; - } - - /* print.lineno is zero if this is the first token of the file. We - handle this specially, so that a first line of "# 1 "foo.c" in - file foo.i outputs just the foo.c line, and not a foo.i line. */ - if (line >= print.lineno && line < print.lineno + 8 && print.lineno) - { - while (line > print.lineno) + while (line > print.line) { putc ('\n', print.outf); - print.lineno++; + print.line++; } } else - { - print.lineno = line; - print_line (""); - } + print_line (line, ""); } static void -print_line (special_flags) - const char *special_flags; +print_line (line, special_flags) + unsigned int line; + const char *special_flags; { /* End any previous line of text. */ if (print.printed) putc ('\n', print.outf); print.printed = 0; - fprintf (print.outf, "# %u \"%s\"%s%s\n", - print.lineno, print.last_fname, special_flags, print.syshdr_flags); + print.line = line; + if (! options->no_line_commands) + fprintf (print.outf, "# %u \"%s\"%s%s\n", + SOURCE_LINE (print.map, print.line), + print.filename, special_flags, print.syshdr_flags); } /* Callbacks. */ @@ -348,21 +336,21 @@ print_line (special_flags) static void cb_ident (pfile, line, str) cpp_reader *pfile ATTRIBUTE_UNUSED; - unsigned int line ATTRIBUTE_UNUSED; + unsigned int line; const cpp_string * str; { - maybe_print_line (cpp_get_line (pfile)->output_line); + maybe_print_line (line); fprintf (print.outf, "#ident \"%s\"\n", str->text); - print.lineno++; + print.line++; } static void cb_define (pfile, line, node) cpp_reader *pfile; - unsigned int line ATTRIBUTE_UNUSED; + unsigned int line; cpp_hashnode *node; { - maybe_print_line (cpp_get_line (pfile)->output_line); + maybe_print_line (line); fputs ("#define ", print.outf); /* -dD command line option. */ @@ -372,30 +360,30 @@ cb_define (pfile, line, node) fputs ((const char *) NODE_NAME (node), print.outf); putc ('\n', print.outf); - print.lineno++; + print.line++; } static void cb_undef (pfile, line, node) - cpp_reader *pfile; - unsigned int line ATTRIBUTE_UNUSED; + cpp_reader *pfile ATTRIBUTE_UNUSED; + unsigned int line; cpp_hashnode *node; { - maybe_print_line (cpp_get_line (pfile)->output_line); + maybe_print_line (line); fprintf (print.outf, "#undef %s\n", NODE_NAME (node)); - print.lineno++; + print.line++; } static void cb_include (pfile, line, dir, header) - cpp_reader *pfile ATTRIBUTE_UNUSED; - unsigned int line ATTRIBUTE_UNUSED; + cpp_reader *pfile; + unsigned int line; const unsigned char *dir; const cpp_token *header; { - maybe_print_line (cpp_get_line (pfile)->output_line); + maybe_print_line (line); fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header)); - print.lineno++; + print.line++; } static void @@ -403,12 +391,16 @@ cb_file_change (pfile, fc) cpp_reader *pfile ATTRIBUTE_UNUSED; const cpp_file_change *fc; { - /* Bring current file to correct line (except first file). */ - if (fc->reason == LC_ENTER && !MAIN_FILE_P (fc->map)) - maybe_print_line (SOURCE_LINE (fc->map - 1, fc->line - 1)); + bool first_time = print.map == NULL; + + /* Bring current file to correct line. We handle the first file + change callback specially, so that a first line of "# 1 "foo.c" + in file foo.i outputs just the foo.c line, and not a foo.i line. */ + if (fc->reason == LC_ENTER && !first_time) + maybe_print_line (fc->line - 1); print.map = fc->map; - print.last_fname = fc->map->to_file; + print.filename = fc->map->to_file; if (fc->externc) print.syshdr_flags = " 3 4"; else if (fc->sysp) @@ -416,18 +408,16 @@ cb_file_change (pfile, fc) else print.syshdr_flags = ""; - if (print.lineno) + if (!first_time) { const char *flags = ""; - print.lineno = SOURCE_LINE (fc->map, fc->line); if (fc->reason == LC_ENTER) flags = " 1"; else if (fc->reason == LC_LEAVE) flags = " 2"; - if (! options->no_line_commands) - print_line (flags); + print_line (fc->line, flags); } } @@ -436,12 +426,12 @@ cb_file_change (pfile, fc) static void cb_def_pragma (pfile, line) cpp_reader *pfile; - unsigned int line ATTRIBUTE_UNUSED; + unsigned int line; { - maybe_print_line (cpp_get_line (pfile)->output_line); + maybe_print_line (line); fputs ("#pragma ", print.outf); cpp_output_line (pfile, print.outf); - print.lineno++; + print.line++; } /* Dump out the hash table. */ @@ -456,7 +446,7 @@ dump_macro (pfile, node, v) fputs ("#define ", print.outf); fputs ((const char *) cpp_macro_definition (pfile, node), print.outf); putc ('\n', print.outf); - print.lineno++; + print.line++; } return 1; diff --git a/gcc/line-map.h b/gcc/line-map.h index 1f9a47da42a..b6c934435d3 100644 --- a/gcc/line-map.h +++ b/gcc/line-map.h @@ -75,9 +75,12 @@ extern struct line_map *lookup_line /* 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), (MAP)[1].from_line - 1) /* Non-zero if the map is at the bottom of the include stack. */ #define MAIN_FILE_P(MAP) ((MAP)->included_from < 0) +/* The current line map. */ +#define CURRENT_LINE_MAP(MAPS) ((MAPS)->maps + (MAPS)->used - 1) + #endif /* !GCC_LINE_MAP_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d0813ca70be..512f5393813 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2001-08-05 Neil Booth + + * gcc.dg/cpp/19951025-1.c: Revert. + * gcc.dg/cpp/directiv.c: We no longer process directives that + interrupt macro arguments. + 2001-08-03 Zack Weinberg * gcc.dg/bconstp-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/cpp/19951025-1.c b/gcc/testsuite/gcc.dg/cpp/19951025-1.c index ca21a227c13..283b5f53f1a 100644 --- a/gcc/testsuite/gcc.dg/cpp/19951025-1.c +++ b/gcc/testsuite/gcc.dg/cpp/19951025-1.c @@ -1,4 +1,4 @@ /* { dg-do preprocess } */ -/* { dg-error "include expects" "" { target *-*-* } 5 } */ -/* { dg-error "newline at end" "" { target *-*-* } 5 } */ +/* { dg-error "include expects" "" { target *-*-* } 4 } */ +/* { dg-error "newline at end" "" { target *-*-* } 4 } */ #include /\ diff --git a/gcc/testsuite/gcc.dg/cpp/directiv.c b/gcc/testsuite/gcc.dg/cpp/directiv.c index 2cb772d1233..622f7a3471a 100644 --- a/gcc/testsuite/gcc.dg/cpp/directiv.c +++ b/gcc/testsuite/gcc.dg/cpp/directiv.c @@ -31,13 +31,6 @@ EMPTY #define bar func (2 /* { dg-error "unterminated" "" { target *-*-* } 32 } */ #define foobar /* { dg-error "directives may not" } */ -/* For tidiness, I think the directive should still be processed - above. Certainly, continuing to try to find the closing ')' can - lead to some really confusing error messages. Hence this test. */ -#ifndef foobar -#error It is nice if the directive is processed! -#endif - /* Check newlines end directives, even in function-like macro invocations. 6.10 paragraph 1.