(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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35146
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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
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);
}
{
result = context->pushed_token;
context->pushed_token = 0;
+ return result; /* Cannot be a CPP_MACRO_ARG */
}
else if (context->posn == context->count)
{
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;
if (pfile->temp_used)
release_temp_tokens (pfile);
}
-
lex_line (pfile, list);
pfile->contexts[0].count = list->tokens_used;
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 \
#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. */
/* 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;
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
}
else
{
- info->flags |= GNU_REST_ARGS;
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile,
"ISO C does not permit named varargs parameters");
/* 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)
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:
+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.
/* { 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
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
--- /dev/null
+/* 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); }