aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/cpplib.c206
-rw-r--r--gcc/cpplib.h8
-rw-r--r--gcc/cppmacro.c8
-rw-r--r--gcc/cppmain.c7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/line5.c15
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"