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
This commit is contained in:
Neil Booth 2001-09-16 11:23:56 +00:00 committed by Neil Booth
parent 27553bf325
commit 18a9d8ff7f
7 changed files with 144 additions and 114 deletions

View File

@ -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.

View File

@ -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 have a directive that is not an opening conditional,
invalidate any control macro. */
if (! (dir->flags & IF_COND))
pfile->mi_valid = false;
/* 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))
/* 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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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"