diff options
author | Neil Booth <neil@daikokuya.demon.co.uk> | 2001-09-16 11:23:56 +0000 |
---|---|---|
committer | Neil Booth <neil@gcc.gnu.org> | 2001-09-16 11:23:56 +0000 |
commit | 18a9d8ff7f06fbdc3ea635c8d55ea4023bad0dd8 (patch) | |
tree | b5637b92895c1d89a6ebec87518678bddc00a55f | |
parent | 27553bf3253625f6c3e56d36599b9e7cf188bfe8 (diff) | |
download | gcc-18a9d8ff7f06fbdc3ea635c8d55ea4023bad0dd8.zip gcc-18a9d8ff7f06fbdc3ea635c8d55ea4023bad0dd8.tar.gz gcc-18a9d8ff7f06fbdc3ea635c8d55ea4023bad0dd8.tar.bz2 |
cppmain.c (scan_translation_unit): Don't worry about putting a space after hashes.
* cppmain.c (scan_translation_unit): Don't worry about
putting a space after hashes.
* cpplib.c (directive_diagnostics): New.
(_cpp_handle_directive): Update to use directive_diagnostics.
(run_directive): Don't toggle prevent_expansion.
(do_line): Backup in case of the line extension.
* cpplib.h (cpp_lexer_pos): Remove.
* cppmacro.c (_cpp_create_definition): Precede a leading #
with whitespace.
* gcc.dg/cpp/line5.c: New testcase.
From-SVN: r45645
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cpplib.c | 206 | ||||
-rw-r--r-- | gcc/cpplib.h | 8 | ||||
-rw-r--r-- | gcc/cppmacro.c | 8 | ||||
-rw-r--r-- | gcc/cppmain.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/line5.c | 15 |
7 files changed, 145 insertions, 115 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e36dcc2..4f0ad86 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2001-09-16 Neil Booth <neil@daikokuya.demon.co.uk> + + * cppmain.c (scan_translation_unit): Don't worry about + putting a space after hashes. + * cpplib.c (directive_diagnostics): New. + (_cpp_handle_directive): Update to use directive_diagnostics. + (run_directive): Don't toggle prevent_expansion. + (do_line): Backup in case of the line extension. + * cpplib.h (cpp_lexer_pos): Remove. + * cppmacro.c (_cpp_create_definition): Precede a leading # + with whitespace. + 2001-09-15 Richard Henderson <rth@redhat.com> * c-typeck.c (comptypes): Handle zero-length arrays properly. diff --git a/gcc/cpplib.c b/gcc/cpplib.c index e8065f6..b3eb24d 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -82,6 +82,8 @@ static void skip_rest_of_line PARAMS ((cpp_reader *)); static void check_eol PARAMS ((cpp_reader *)); static void start_directive PARAMS ((cpp_reader *)); static void end_directive PARAMS ((cpp_reader *, int)); +static void directive_diagnostics + PARAMS ((cpp_reader *, const directive *, int)); static void run_directive PARAMS ((cpp_reader *, int, const char *, size_t)); static int glue_header_name PARAMS ((cpp_reader *, cpp_token *)); @@ -248,8 +250,57 @@ end_directive (pfile, skip_line) pfile->directive = 0; } -/* Check if a token's name matches that of a known directive. Put in - this file to save exporting dtable and other unneeded information. */ +/* Output diagnostics for a directive DIR. INDENTED is non-zero if + the '#' was indented. */ + +static void +directive_diagnostics (pfile, dir, indented) + cpp_reader *pfile; + const directive *dir; + int indented; +{ + if (pfile->state.line_extension) + { + if (CPP_PEDANTIC (pfile) + && ! pfile->state.skipping) + cpp_pedwarn (pfile, "style of line directive is a GCC extension"); + } + else + { + /* Issue -pedantic warnings for extensions. */ + if (CPP_PEDANTIC (pfile) + && ! pfile->state.skipping + && dir->origin == EXTENSION) + cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name); + + /* Traditionally, a directive is ignored unless its # is in + column 1. Therefore in code intended to work with K+R + compilers, directives added by C89 must have their # + indented, and directives present in traditional C must not. + This is true even of directives in skipped conditional + blocks. */ + if (CPP_WTRADITIONAL (pfile)) + { + if (dir == &dtable[T_ELIF]) + cpp_warning (pfile, "suggest not using #elif in traditional C"); + else if (indented && dir->origin == KANDR) + cpp_warning (pfile, + "traditional C ignores #%s with the # indented", + dir->name); + else if (!indented && dir->origin != KANDR) + cpp_warning (pfile, + "suggest hiding #%s from traditional C with an indented #", + dir->name); + } + } +} + +/* Check if we have a known directive. INDENTED is non-zero if the + '#' of the directive was indented. This function is in this file + to save unnecessarily exporting dtable etc. to cpplex.c. Returns + non-zero if the line of tokens has been handled, zero if we should + continue processing the line. */ + int _cpp_handle_directive (pfile, indented) cpp_reader *pfile; @@ -260,125 +311,80 @@ _cpp_handle_directive (pfile, indented) int skip = 1; start_directive (pfile); - - /* Lex the directive name directly. */ _cpp_lex_token (pfile, &dname); if (dname.type == CPP_NAME) { - unsigned int index = dname.val.node->directive_index; - if (index) - dir = &dtable[index - 1]; + if (dname.val.node->directive_index) + dir = &dtable[dname.val.node->directive_index - 1]; } - else if (dname.type == CPP_NUMBER) + /* We do not recognise the # followed by a number extension in + assembler code. */ + else if (dname.type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM) { - /* # followed by a number is equivalent to #line. Do not - recognize this form in assembly language source files or - skipped conditional groups. Complain about this form if - we're being pedantic, but not if this is regurgitated input - (preprocessed or fed back in by the C++ frontend). */ - if (! pfile->state.skipping && CPP_OPTION (pfile, lang) != CLK_ASM) - { - dir = &dtable[T_LINE]; - pfile->state.line_extension = 1; - _cpp_backup_tokens (pfile, 1); - if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed)) - cpp_pedwarn (pfile, "# followed by integer"); - } + dir = &dtable[T_LINE]; + pfile->state.line_extension = 1; } - pfile->directive = dir; if (dir) { - /* Make sure we lex headers correctly, whether skipping or not. */ - pfile->state.angled_headers = dir->flags & INCL; - - /* If we are rescanning preprocessed input, only directives tagged - with IN_I are honored, and the warnings below are suppressed. */ - if (CPP_OPTION (pfile, preprocessed)) + /* If we have a directive that is not an opening conditional, + invalidate any control macro. */ + if (! (dir->flags & IF_COND)) + pfile->mi_valid = false; + + /* Kluge alert. In order to be sure that code like this + + #define HASH # + HASH define foo bar + + does not cause '#define foo bar' to get executed when + compiled with -save-temps, we recognize directives in + -fpreprocessed mode only if the # is in column 1. cppmacro.c + puts a space in fron of any '#' at the start of a macro. */ + if (CPP_OPTION (pfile, preprocessed) + && (indented || !(dir->flags & IN_I))) { - /* Kluge alert. In order to be sure that code like this - #define HASH # - HASH define foo bar - does not cause '#define foo bar' to get executed when - compiled with -save-temps, we recognize directives in - -fpreprocessed mode only if the # is in column 1 and the - directive name starts in column 2. This output can only - be generated by the directive callbacks in cppmain.c (see - also the special case in scan_buffer). */ - if (dir->flags & IN_I && !indented && !(dname.flags & PREV_WHITE)) - (*dir->handler) (pfile); - /* That check misses '# 123' linemarkers. Let them through too. */ - else if (dname.type == CPP_NUMBER) - (*dir->handler) (pfile); - else - { - /* We don't want to process this directive. Put back the - tokens so caller will see them (and issue an error, - probably). */ - _cpp_backup_tokens (pfile, 1); - skip = 0; - } + skip = 0; + dir = 0; } else { - /* Traditionally, a directive is ignored unless its # is in - column 1. Therefore in code intended to work with K+R - compilers, directives added by C89 must have their # - indented, and directives present in traditional C must - not. This is true even of directives in skipped - conditional blocks. */ - if (CPP_WTRADITIONAL (pfile)) - { - if (dir == &dtable[T_ELIF]) - cpp_warning (pfile, - "suggest not using #elif in traditional C"); - else if (indented && dir->origin == KANDR) - cpp_warning (pfile, - "traditional C ignores #%s with the # indented", - dir->name); - else if (!indented && dir->origin != KANDR) - cpp_warning (pfile, - "suggest hiding #%s from traditional C with an indented #", - dir->name); - } - - /* If we are skipping a failed conditional group, all - non-conditional directives are ignored. */ - if (! pfile->state.skipping || (dir->flags & COND)) - { - /* Issue -pedantic warnings for extensions. */ - if (CPP_PEDANTIC (pfile) && dir->origin == EXTENSION) - cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name); - - /* If we have a directive that is not an opening - conditional, invalidate any control macro. */ - if (! (dir->flags & IF_COND)) - pfile->mi_valid = false; - - (*dir->handler) (pfile); - } + /* In failed conditional groups, all non-conditional + directives are ignored. Before doing that, whether + skipping or not, we should lex angle-bracketed headers + correctly, and maybe output some diagnostics. */ + pfile->state.angled_headers = dir->flags & INCL; + if (! CPP_OPTION (pfile, preprocessed)) + directive_diagnostics (pfile, dir, indented); + if (pfile->state.skipping && !(dir->flags & COND)) + dir = 0; } } - else if (dname.type != CPP_EOF && ! pfile->state.skipping) + else if (dname.type == CPP_EOF) + ; /* CPP_EOF is the "null directive". */ + else { /* An unknown directive. Don't complain about it in assembly source: we don't know where the comments are, and # may introduce assembler pseudo-ops. Don't complain about invalid directives in skipped conditional groups (6.10 p4). */ if (CPP_OPTION (pfile, lang) == CLK_ASM) - { - /* Output the # and this token for the assembler. */ - _cpp_backup_tokens (pfile, 1); - skip = 0; - } - else + skip = 0; + else if (!pfile->state.skipping) cpp_error (pfile, "invalid preprocessing directive #%s", cpp_token_as_text (pfile, &dname)); } - if (pfile->state.in_directive) - end_directive (pfile, skip); + if (dir) + { + pfile->directive = dir; + (*pfile->directive->handler) (pfile); + } + else if (skip == 0) + _cpp_backup_tokens (pfile, 1); + + end_directive (pfile, skip); return skip; } @@ -394,11 +400,10 @@ run_directive (pfile, dir_no, buf, count) cpp_push_buffer (pfile, (const U_CHAR *) buf, count, /* from_stage3 */ true, 1); start_directive (pfile); - pfile->buffer->saved_flags = 0; /* We don't want to recognise directives. */ - pfile->state.prevent_expansion++; + /* We don't want a leading # to be interpreted as a directive. */ + pfile->buffer->saved_flags = 0; pfile->directive = &dtable[dir_no]; (void) (*pfile->directive->handler) (pfile); - pfile->state.prevent_expansion--; end_directive (pfile, 1); _cpp_pop_buffer (pfile); } @@ -708,6 +713,11 @@ do_line (pfile) /* C99 raised the minimum limit on #line numbers. */ cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767; + /* Putting this in _cpp_handle_directive risks two calls to + _cpp_backup_tokens in some circumstances, which can segfault. */ + if (pfile->state.line_extension) + _cpp_backup_tokens (pfile, 1); + /* #line commands expand macros. */ cpp_get_token (pfile, &token); if (token.type != CPP_NUMBER diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 7719995..ad74187 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -41,7 +41,6 @@ typedef struct cpp_token cpp_token; typedef struct cpp_string cpp_string; typedef struct cpp_hashnode cpp_hashnode; typedef struct cpp_macro cpp_macro; -typedef struct cpp_lexer_pos cpp_lexer_pos; typedef struct cpp_callbacks cpp_callbacks; struct answer; @@ -186,13 +185,6 @@ struct cpp_token } val; }; -/* The position of a token in the current file. */ -struct cpp_lexer_pos -{ - unsigned int line; - unsigned short col; -}; - /* A standalone character. We may want to make it unsigned for the same reason we use unsigned char - to avoid signedness issues. */ typedef int cppchar_t; diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c index 5c64767..80c0154 100644 --- a/gcc/cppmacro.c +++ b/gcc/cppmacro.c @@ -1321,8 +1321,12 @@ _cpp_create_definition (pfile, node) /* Don't count the CPP_EOF. */ macro->count--; - /* Clear the whitespace flag from the leading token. */ - macro->expansion[0].flags &= ~PREV_WHITE; + /* Clear the whitespace flag from the leading token, but put a space + in front of a leading # which might be used to fake a directive. */ + if (macro->expansion[0].type == CPP_HASH) + macro->expansion[0].flags |= PREV_WHITE; + else + macro->expansion[0].flags &= ~PREV_WHITE; /* Implement the macro-defined-to-itself optimisation. */ macro->disabled = (macro->count == 1 && !macro->fun_like diff --git a/gcc/cppmain.c b/gcc/cppmain.c index 18bd7fd..5451ccc 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -233,13 +233,6 @@ scan_translation_unit (pfile) if ((token->flags & (PREV_WHITE | AVOID_LPASTE | BOL)) == AVOID_LPASTE && cpp_avoid_paste (pfile, &tokens[1 - index], token)) token->flags |= PREV_WHITE; - /* Special case '# <directive name>': insert a space between - the # and the token. This will prevent it from being - treated as a directive when this code is re-preprocessed. - XXX Should do this only at the beginning of a line, but how? */ - else if (token->type == CPP_NAME && token->val.node->directive_index - && tokens[1 - index].type == CPP_HASH) - token->flags |= PREV_WHITE; cpp_output_token (token, print.outf); if (token->type == CPP_STRING || token->type == CPP_WSTRING diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0aea5b7..40333a3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-09-16 Neil Booth <neil@daikokuya.demon.co.uk> + + * gcc.dg/cpp/line5.c: New testcase. + 2001-09-15 Neil Booth <neil@daikokuya.demon.co.uk> * gcc.dg/cpp/macro9.c: New test. diff --git a/gcc/testsuite/gcc.dg/cpp/line5.c b/gcc/testsuite/gcc.dg/cpp/line5.c new file mode 100644 index 0000000..d0c04b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/line5.c @@ -0,0 +1,15 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. */ + +/* { dg-do preprocess } */ +/* { dg-options "-fpreprocessed" } */ + +/* Source: Neil Booth, 16 Sep 2001. + + This file, with an indented line marker, is not possible without + user editing of preprocessed output, or the user using + -fpreprocessed on raw source. Nevertheless, we should not + segfault. This is a test that we don't back up two tokens in + cpplib.c - one to back up over the number, and one when we + recognise that it's not a valid directive in preprocessed input. */ + + # 1 "foo.c" |