cppmacro.c (CAN_PASTE_AFTER): New macro.

* cppmacro.c (CAN_PASTE_AFTER): New macro.
	(count_params): Don't set GNU_REST_ARGS on anything.
	(save_expansion): Set PASTE_LEFT only on tokens for which
	CAN_PASTE_AFTER is true, or which are named operators.

	* cpplex.c (parse_args): Distinguish between a rest argument
	given one empty argument, and a rest argument given zero arguments.
	(maybe_paste_with_next): Look for VOID_REST tag, and trigger
	deletion of previous token based on that.
	(get_raw_token): Flatten some control structure.

	* cpplib.h (CPP_LAST_EQ): Correct.
	(VOID_REST): New token flag.
	(GNU_REST_ARGS): Delete.

	* gcc.dg/cpp/20000625-2.c, gcc.dg/cpp/macsyntx.c: Update error
	regexps.
	* gcc.dg/cpp/paste6.c: New test.

From-SVN: r35146
This commit is contained in:
Zack Weinberg 2000-07-20 17:57:38 +00:00
parent 1e18a243c2
commit 6fee6033e7
8 changed files with 92 additions and 40 deletions

View file

@ -1,3 +1,28 @@
2000-07-20 Zack Weinberg <zack@wolery.cumb.org>
* cppmacro.c (CAN_PASTE_AFTER): New macro.
(count_params): Don't set GNU_REST_ARGS on anything.
(save_expansion): Set PASTE_LEFT only on tokens for which
CAN_PASTE_AFTER is true, or which are named operators.
* cpplex.c (parse_args): Distinguish between a rest argument
given one empty argument, and a rest argument given zero arguments.
(maybe_paste_with_next): Look for VOID_REST tag, and trigger
deletion of previous token based on that.
(get_raw_token): Flatten some control structure.
* cpplib.h (CPP_LAST_EQ): Correct.
(VOID_REST): New token flag.
(GNU_REST_ARGS): Delete.
* tradcpp.c (main): Don't munge -D options.
(make_definition): Bring -D handling in line with cpplib.
(do_define): Strip all leading whitespace from macro definitions.
2000-07-20 David Billinghurst <David.Billinghurst@riotinto.com.au>
* Makefile.in (tradcpp): Depend on intl.o and version.o.
2000-07-20 Bruce Korb <bkorb@gnu.org>
* fixincl/check.tpl: strip the platform specific types before testing

View file

@ -2399,13 +2399,19 @@ parse_args (pfile, hp, args)
debug("string");
This is exactly the same as if the rest argument had received no
tokens - debug("string",); This extension is deprecated. */
if (argc + 1 == macro->paramc && (macro->flags & GNU_REST_ARGS))
if (argc + 1 == macro->paramc && (macro->flags & VAR_ARGS))
{
/* Duplicate the placemarker. Then we can set its flags and
position and safely be using more than one. */
save_token (args, duplicate_token (pfile, &placemarker_token));
cpp_token *pm = duplicate_token (pfile, &placemarker_token);
pm->flags = VOID_REST;
save_token (args, pm);
args->ends[argc] = total + 1;
if (CPP_OPTION (pfile, c99) && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used");
return 0;
}
else
@ -2710,17 +2716,11 @@ maybe_paste_with_next (pfile, token)
pasted = duplicate_token (pfile, second);
else if (second->type == CPP_PLACEMARKER)
{
cpp_context *mac_context = CURRENT_CONTEXT (pfile) - 1;
/* GCC has special extended semantics for a ## b where b is
a varargs parameter: a disappears if b consists of no
tokens. This extension is deprecated. */
if ((mac_context->u.list->flags & GNU_REST_ARGS)
&& (mac_context->u.list->tokens[mac_context->posn-1].val.aux + 1
== (unsigned) mac_context->u.list->paramc))
{
cpp_warning (pfile, "deprecated GNU ## extension used");
pasted = duplicate_token (pfile, second);
}
a varargs parameter: a disappears if b was given no actual
arguments (not merely if b is an empty argument). */
if (second->flags & VOID_REST)
pasted = duplicate_token (pfile, second);
else
pasted = duplicate_token (pfile, token);
}
@ -3161,6 +3161,7 @@ get_raw_token (pfile)
{
result = context->pushed_token;
context->pushed_token = 0;
return result; /* Cannot be a CPP_MACRO_ARG */
}
else if (context->posn == context->count)
{
@ -3168,21 +3169,19 @@ get_raw_token (pfile)
return &eof_token;
continue;
}
else
else if (IS_ARG_CONTEXT (context))
{
if (IS_ARG_CONTEXT (context))
result = context->u.arg[context->posn++];
if (result == 0)
{
context->flags ^= CONTEXT_RAW;
result = context->u.arg[context->posn++];
if (result == 0)
{
context->flags ^= CONTEXT_RAW;
result = context->u.arg[context->posn++];
}
return result; /* Cannot be a CPP_MACRO_ARG */
}
result = &context->u.list->tokens[context->posn++];
return result; /* Cannot be a CPP_MACRO_ARG */
}
result = &context->u.list->tokens[context->posn++];
if (result->type != CPP_MACRO_ARG)
return result;
@ -3225,7 +3224,6 @@ lex_next (pfile, clear)
if (pfile->temp_used)
release_temp_tokens (pfile);
}
lex_line (pfile, list);
pfile->contexts[0].count = list->tokens_used;

View file

@ -46,7 +46,7 @@ typedef struct cpp_hashnode cpp_hashnode;
the same order as their counterparts without the '=', like ">>". */
/* Positions in the table. */
#define CPP_LAST_EQ CPP_LSHIFT
#define CPP_LAST_EQ CPP_MAX
#define CPP_FIRST_DIGRAPH CPP_HASH
#define TTYPE_TABLE \
@ -154,7 +154,8 @@ struct cpp_string
#define STRINGIFY_ARG (1 << 3) /* If macro argument to be stringified. */
#define PASTE_LEFT (1 << 4) /* If on LHS of a ## operator. */
#define PASTED (1 << 5) /* The result of a ## operator. */
#define NAMED_OP (1 << 6) /* C++ named operators, also defined */
#define NAMED_OP (1 << 6) /* C++ named operators, also "defined". */
#define VOID_REST (1 << 7) /* When a rest arg gets zero actual args. */
/* A preprocessing token. This has been carefully packed and should
occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
@ -178,8 +179,7 @@ struct cpp_token
/* cpp_toklist flags. */
#define LIST_OFFSET (1 << 0)
#define VAR_ARGS (1 << 1)
#define GNU_REST_ARGS (1 << 2) /* Set in addition to VAR_ARGS. */
#define BEG_OF_FILE (1 << 3)
#define BEG_OF_FILE (1 << 2)
struct directive; /* These are deliberately incomplete. */
struct answer;

View file

@ -53,6 +53,14 @@ static unsigned int find_param PARAMS ((const cpp_token *,
const cpp_token *));
static cpp_toklist * alloc_macro PARAMS ((cpp_reader *, struct macro_info *));
/* These are all the tokens that can have something pasted after them.
Comma is included in the list only to support the GNU varargs extension
(where you write a ## b and a disappears if b is an empty rest argument). */
#define CAN_PASTE_AFTER(type) \
((type) <= CPP_LAST_EQ || (type) == CPP_COLON || (type) == CPP_HASH \
|| (type) == CPP_DEREF || (type) == CPP_DOT || (type) == CPP_NAME \
|| (type) == CPP_INT || (type) == CPP_FLOAT || (type) == CPP_NUMBER \
|| (type) == CPP_MACRO_ARG || (type) == CPP_PLACEMARKER || (type) == CPP_COMMA)
/* Scans for a given token, returning the parameter number if found,
or 0 if not found. Scans from FIRST to TOKEN - 1 or the first
@ -192,7 +200,6 @@ count_params (pfile, info)
}
else
{
info->flags |= GNU_REST_ARGS;
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile,
"ISO C does not permit named varargs parameters");
@ -294,9 +301,6 @@ parse_define (pfile, info)
/* Constraint 6.10.3.5 */
if (!(info->flags & VAR_ARGS) && is__va_args__ (pfile, token))
return 1;
/* It might be worth doing a check here that we aren't a
macro argument, since we don't store the text of macro
arguments. This would reduce "len" and save space. */
}
info->ntokens++;
if (TOKEN_SPELL (token) == SPELL_STRING)
@ -463,7 +467,15 @@ save_expansion (pfile, info)
continue;
case CPP_PASTE:
dest[-1].flags |= PASTE_LEFT;
/* Set the paste flag on the token to our left, unless there
is no possible token to which it might be pasted. That
is critical for correct operation under some circumstances;
see gcc.dg/cpp/paste6.c. */
if (CAN_PASTE_AFTER (dest[-1].type) || (dest[-1].flags & NAMED_OP))
dest[-1].flags |= PASTE_LEFT;
else if (CPP_OPTION (pfile, warn_paste))
cpp_warning_with_line (pfile, dest[-1].line, dest[-1].col,
"nothing can be pasted after this token");
continue;
case CPP_HASH:

View file

@ -1,3 +1,9 @@
2000-07-20 Zack Weinberg <zack@wolery.cumb.org>
* gcc.dg/cpp/20000625-2.c, gcc.dg/cpp/macsyntx.c: Update error
regexps.
* gcc.dg/cpp/paste6.c: New test.
2000-07-19 Zack Weinberg <zack@wolery.cumb.org>
* gcc.dg/cpp/tr-direct.c: New test.

View file

@ -2,7 +2,7 @@
/* { dg-do run } */
#define symbol_version(name, version) name##@##version
/* { dg-warning "nothing can be pasted" "" { target *-*-* } 4 } */
#define str(x) xstr(x)
#define xstr(x) #x

View file

@ -51,16 +51,15 @@ one(ichi\
two(ichi) /* { dg-error "not enough" } */
var0() /* OK. */
var0(ichi) /* OK. */
var1() /* { dg-error "not enough" } */
var1(ichi) /* { dg-error "not enough" } */
var1() /* { dg-warning "rest arguments to be used" } */
var1(ichi) /* { dg-warning "rest arguments to be used" } */
var1(ichi, ni) /* OK. */
/* This tests two deprecated oddities of GNU rest args - omitting a
comma is OK, and backtracking a token on pasting an empty rest
args. */
/* This tests two oddities of GNU rest args - omitting a comma is OK,
and backtracking a token on pasting an empty rest args. */
#define rest(x, y...) x ## y /* { dg-warning "ISO C" } */
rest(ichi,) /* { dg-warning "deprecated" } */
rest(ichi) /* { dg-warning "deprecated" } */
rest(ichi,) /* OK. */
rest(ichi) /* { dg-warning "rest arguments to be used" } */
#if 23 != rest(2, 3) /* OK, no warning. */
#error 23 != 23 !!
#endif

View file

@ -0,0 +1,12 @@
/* Regression test for paste appearing at the beginning of a set of
actual arguments. Original bug exposed by Linux kernel. Problem
reported by Jakub Jelinek <jakub@redhat.com>. */
/* { dg-do compile } */
extern int foo(int x);
#define bar(x) foo(x)
#define baz(x) bar(##x) /* { dg-warning "nothing can be pasted" } */
int quux(int y) { return baz(y); }