This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
cpplib: Fix spacing issues, optimize cpp_get_token.
- To: gcc-patches at gcc dot gnu dot org
- Subject: cpplib: Fix spacing issues, optimize cpp_get_token.
- From: Neil Booth <neilb at earthling dot net>
- Date: Fri, 1 Dec 2000 18:38:22 +0000
- Cc: Todd Plessel <plessel dot todd at epamail dot epa dot gov>
This patch, plus testcase, fixes once and for all token spacing and
positioning issues for the stand-alone preprocessor.
Currently, nasty stuff like
#define str(x) #x
#define f(x) x
f
bar
f (g) str
(
1
2
) f
(bam) baz
produces
f
bar
g "1 2"
bam
baz
With this patch it produces the more pretty and correct
f
bar
g "1 2" bam baz
It is also a good test that we get the "newlines in a macro argument
are whitespace" correct.
Combined in the patch is an optimization to cpp_get_token; moving the
"whilst skipping" loop into _cpp_lex_token where it properly belongs.
cpp_get_token is by far the most executed routine in cpplib; so this
should give a 1 or 2 percent performance win.
Bootstrapping x86 Linux, will commit if and when it succeeds.
Neil.
* cppinit.c (initialize): Forgotten prototype.
* cpplex.c (_cpp_lex_token): Loop until not skipping.
Always clear PREV_WHITE upon meeting a new line.
* cpplib.c (end_directive): Set pfile->skipping after
skip_rest_of_line.
* cpplib.h (cpp_reader): Remove macro_pos.
* cppmacro.c (cpp_get_line): Don't do anything special inside
macros.
(parse_arg): Add PREV_WHITE if a token appears after new lines.
(funlike_invocation_p): Save and restore the output position
over a successful check for a '('.
(enter_macro_context): Delete uses of macro_pos.
(cpp_get_token): Don't use pfile->skipping.
* gcc.dg/cpp/20000720-1.S: Remove duplicate testcase.
* gcc.dg/cpp/poison.c: Update.
* gcc.dg/cpp/spacing1.c: New testcase for all spacing issues.
Index: gcc/cppinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppinit.c,v
retrieving revision 1.122
diff -u -p -r1.122 cppinit.c
--- cppinit.c 2000/11/28 21:34:29 1.122
+++ cppinit.c 2000/12/01 18:22:48
@@ -94,6 +94,7 @@ struct cpp_pending
static void print_help PARAMS ((void));
static void path_include PARAMS ((cpp_reader *,
char *, int));
+static void initialize PARAMS ((void));
static void initialize_builtins PARAMS ((cpp_reader *));
static void append_include_chain PARAMS ((cpp_reader *,
char *, int, int));
Index: gcc/cpplex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplex.c,v
retrieving revision 1.121
diff -u -p -r1.121 cpplex.c
--- cpplex.c 2000/11/26 17:31:10 1.121
+++ cpplex.c 2000/12/01 18:22:52
@@ -850,8 +850,10 @@ _cpp_lex_token (pfile, result)
cppchar_t c;
cpp_buffer *buffer;
const unsigned char *comment_start;
- unsigned char bol = pfile->state.next_bol;
+ unsigned char bol;
+ skip:
+ bol = pfile->state.next_bol;
done_directive:
buffer = pfile->buffer;
pfile->state.next_bol = 0;
@@ -894,13 +896,10 @@ _cpp_lex_token (pfile, result)
handle_newline (buffer, c);
bol = 1;
pfile->lexer_pos.output_line = buffer->lineno;
-
- /* Newlines in arguments are white space (6.10.3.10).
- Otherwise, clear any white space flag. */
- if (pfile->state.parsing_args)
- result->flags |= PREV_WHITE;
- else
- result->flags &= ~PREV_WHITE;
+ /* 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;
goto next_char;
}
@@ -1275,6 +1274,9 @@ _cpp_lex_token (pfile, result)
result->val.c = c;
break;
}
+
+ if (pfile->skipping)
+ goto skip;
/* If not in a directive, this token invalidates controlling macros. */
if (!pfile->state.in_directive)
Index: gcc/cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.223
diff -u -p -r1.223 cpplib.c
--- cpplib.c 2000/11/27 08:00:03 1.223
+++ cpplib.c 2000/12/01 18:22:56
@@ -247,13 +247,13 @@ end_directive (pfile, skip_line)
{
cpp_buffer *buffer = pfile->buffer;
- /* Restore pfile->skipping before skip_rest_of_line. This avoids
- warning about poisoned identifiers in skipped #error lines. */
- pfile->skipping = buffer->was_skipping;
-
/* We don't skip for an assembler #. */
if (skip_line)
skip_rest_of_line (pfile);
+
+ /* Restore pfile->skipping after skip_rest_of_line. Otherwise the
+ lexer might not return! */
+ pfile->skipping = buffer->was_skipping;
/* Restore state. */
pfile->la_write = pfile->la_saved;
Index: gcc/cpplib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.h,v
retrieving revision 1.143
diff -u -p -r1.143 cpplib.h
--- cpplib.h 2000/11/28 21:34:30 1.143
+++ cpplib.h 2000/12/01 18:23:04
@@ -498,10 +498,8 @@ struct cpp_reader
/* Lexer state. */
struct lexer_state state;
- /* The position of the last lexed token, last lexed directive, and
- last macro invocation. */
+ /* The position of the last lexed token and last lexed directive. */
cpp_lexer_pos lexer_pos;
- cpp_lexer_pos macro_pos;
cpp_lexer_pos directive_pos;
/* Memory pools. */
Index: gcc/cppmacro.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppmacro.c,v
retrieving revision 1.32
diff -u -p -r1.32 cppmacro.c
--- cppmacro.c 2000/11/28 21:34:29 1.32
+++ cppmacro.c 2000/12/01 18:23:04
@@ -236,10 +236,6 @@ const cpp_lexer_pos *
cpp_get_line (pfile)
cpp_reader *pfile;
{
- /* Within a macro expansion, return the position of the outermost
- invocation. */
- if (pfile->context->prev)
- return &pfile->macro_pos;
return &pfile->lexer_pos;
}
@@ -489,6 +485,7 @@ parse_arg (pfile, arg, var_args)
{
enum cpp_ttype result;
unsigned int paren = 0;
+ unsigned int line;
arg->first = (cpp_token *) POOL_FRONT (&pfile->argument_pool);
for (;; arg->count++)
@@ -501,9 +498,13 @@ parse_arg (pfile, arg, var_args)
token = &arg->first[arg->count];
}
+ /* Newlines in arguments are white space (6.10.3.10). */
+ line = pfile->lexer_pos.output_line;
cpp_get_token (pfile, token);
- result = token->type;
+ if (line != pfile->lexer_pos.output_line)
+ token->flags |= PREV_WHITE;
+ result = token->type;
if (result == CPP_OPEN_PAREN)
paren++;
else if (result == CPP_CLOSE_PAREN && paren-- == 0)
@@ -608,7 +609,9 @@ funlike_invocation_p (pfile, node, list)
cpp_context *orig_context;
cpp_token maybe_paren;
macro_arg *args = 0;
+ cpp_lexer_pos macro_pos;
+ macro_pos = pfile->lexer_pos;
pfile->state.parsing_args = 1;
pfile->state.prevent_expansion++;
orig_context = pfile->context;
@@ -631,6 +634,9 @@ funlike_invocation_p (pfile, node, list)
if (args)
{
+ /* The macro's expansion appears where the name would have. */
+ pfile->lexer_pos = macro_pos;
+
if (node->value.macro->paramc > 0)
{
/* Don't save tokens during pre-expansion. */
@@ -660,10 +666,7 @@ enter_macro_context (pfile, node)
/* Save the position of the outermost macro invocation. */
if (!pfile->context->prev)
- {
- pfile->macro_pos = pfile->lexer_pos;
- lock_pools (pfile);
- }
+ lock_pools (pfile);
if (macro->fun_like && !funlike_invocation_p (pfile, node, &list))
{
@@ -924,7 +927,7 @@ cpp_get_token (pfile, token)
token->flags |= flags;
flags = 0;
/* PASTE_LEFT tokens can only appear in macro expansions. */
- if (token->flags & PASTE_LEFT && !pfile->skipping)
+ if (token->flags & PASTE_LEFT)
paste_all_tokens (pfile, token);
}
else
@@ -939,10 +942,6 @@ cpp_get_token (pfile, token)
token->flags = 0;
return;
}
-
- /* Loop until we're not skipping. */
- if (pfile->skipping)
- continue;
if (token->type != CPP_NAME)
break;
Index: gcc/testsuite/gcc.dg/cpp/20000720-1.S
===================================================================
RCS file: 20000720-1.S
diff -N 20000720-1.S
--- /sourceware/cvs-tmp/cvsgTeyvk Fri Dec 1 10:23:33 2000
+++ /dev/null Tue May 5 13:32:27 1998
@@ -1,14 +0,0 @@
-/* { dg-do preprocess } */
-
-#define nop() foobar
- nop
- call b
-
-/*
- { dg-final { if ![file exists 20000720-1.i] { return } } }
- { dg-final { if \{ [grep 20000720-1.i "nop.*call"] != "" \} \{ } }
- { dg-final { fail "20000720-1.S: new-line preservation" } }
- { dg-final { \} else \{ } }
- { dg-final { pass "20000720-1.S: new-line preservation" } }
- { dg-final { \} } }
-*/
Index: gcc/testsuite/gcc.dg/cpp/poison.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/cpp/poison.c,v
retrieving revision 1.1
diff -u -p -r1.1 poison.c
--- poison.c 2000/06/27 22:26:11 1.1
+++ poison.c 2000/12/01 18:23:24
@@ -15,10 +15,10 @@ foo5 /* { dg-error "foo5" "use of foo5
#define foo6 345 /* { dg-error "foo6" "def of foo6" } */
#define foo6 456 /* { dg-error "foo6" "redef of foo6" } */
#ifdef foo6 /* { dg-error "foo6" "#ifdef foo6" } */
-#error hey! foo6 poisoned!
+#error hey! foo6 poisoned! /* { dg-error "foo6" "poisoned identifiers" } */
#endif
#if defined(foo6) /* { dg-error "foo6" "#if defined foo6" } */
-#error no, foo6 still poisoned!
+#error foo6 still poisoned! /* { dg-error "foo6" "poisoned identifiers" } */
#else
foo6 /* { dg-error "foo6" "use of foo6" } */
#endif
Index: gcc/testsuite/gcc.dg/cpp/spacing1.c
===================================================================
RCS file: spacing1.c
diff -N spacing1.c
--- /dev/null Tue May 5 13:32:27 1998
+++ spacing1.c Fri Dec 1 10:23:24 2000
@@ -0,0 +1,38 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc. */
+
+/* { dg-do preprocess } */
+
+/* This tests correct spacing of macro expansion output, as well as
+ the line it falls on. This is quite subtle; it involves newlines
+ within macro arguments becoming spaces, but not if it turns out to
+ not be a macro invocation. Also, */
+
+#define str(x) #x
+#define f(x) x
+
+/* The correct output is shown here. Note the spaces, and the way
+ everything after the invocation of f appears on the same line.
+
+f
+bar
+g "1 2" bam baz
+
+*/
+
+f
+bar
+f (g) str
+(
+1
+2
+) f
+(bam) baz
+
+/*
+ { dg-final { if ![file exists spacing1.i] { return } } }
+ { dg-final { if \{ [grep spacing1.i "f.*bar"] == "" \} \{ } }
+ { dg-final { if \{ [grep spacing1.i "^bar"] != "" \} \{ } }
+ { dg-final { if \{ [grep spacing1.i "g \"1 2\" bam baz"] != "" \} \{ } }
+ { dg-final { return \} \} \} } }
+ { dg-final { fail "spacing1.c: spacing and new-line preservation" } }
+*/