Commit 0f89df67 by Zack Weinberg Committed by Zack Weinberg

cpphash.c (trad_stringify, add_pat): New functions.

	* cpphash.c (trad_stringify, add_pat): New functions.
	(collect_expansion): Restore support for -traditional syntax.
	Use trad_stringify and add_pat.
	(_cpp_macroexpand): Restore support for -traditional semantics.
	* cpplex.c (_cpp_scan_line): Don't change space_before if we
	get a COMMENT token.
	(_cpp_lex_token): Provide COMMENT tokens to caller if
	traditional and parsing_define_directive.
	(skip_comment): Warn about // comments if -Wtraditional.
	* cpplib.c (do_define): Fix typo.  Create EMPTY nodes with
	proper node type.
	(do_undef): Don't warn about undefining EMPTY nodes.

From-SVN: r33350
parent 4ff812cd
2000-04-22 Zack Weinberg <zack@wolery.cumb.org>
* cpphash.c (trad_stringify, add_pat): New functions.
(collect_expansion): Restore support for -traditional syntax.
Use trad_stringify and add_pat.
(_cpp_macroexpand): Restore support for -traditional semantics.
* cpplex.c (_cpp_scan_line): Don't change space_before if we
get a COMMENT token.
(_cpp_lex_token): Provide COMMENT tokens to caller if
traditional and parsing_define_directive.
(skip_comment): Warn about // comments if -Wtraditional.
* cpplib.c (do_define): Fix typo. Create EMPTY nodes with
proper node type.
(do_undef): Don't warn about undefining EMPTY nodes.
Sat Apr 22 22:35:38 MET DST 2000 Jan Hubicka <jh@suse.cz> Sat Apr 22 22:35:38 MET DST 2000 Jan Hubicka <jh@suse.cz>
* loop.c (strength_reduce): Fix biv removal code. * loop.c (strength_reduce): Fix biv removal code.
......
...@@ -79,7 +79,13 @@ static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *, ...@@ -79,7 +79,13 @@ static unsigned int collect_params PARAMS ((cpp_reader *, cpp_toklist *,
static void warn_trad_stringify PARAMS ((cpp_reader *, U_CHAR *, size_t, static void warn_trad_stringify PARAMS ((cpp_reader *, U_CHAR *, size_t,
unsigned int, const struct arg *)); unsigned int, const struct arg *));
static unsigned int trad_stringify PARAMS ((cpp_reader *, U_CHAR *, size_t,
unsigned int, const struct arg *,
struct reflist **,
struct reflist **, unsigned int));
static int duplicate_arg_p PARAMS ((U_CHAR *, U_CHAR *)); static int duplicate_arg_p PARAMS ((U_CHAR *, U_CHAR *));
static void add_pat PARAMS ((struct reflist **, struct reflist **,
unsigned int, unsigned int, int, int, int, int));
/* This structure represents one parsed argument in a macro call. /* This structure represents one parsed argument in a macro call.
`raw' points to the argument text as written (`raw_length' is its length). `raw' points to the argument text as written (`raw_length' is its length).
...@@ -279,6 +285,32 @@ macro_cleanup (pbuf, pfile) ...@@ -279,6 +285,32 @@ macro_cleanup (pbuf, pfile)
return 0; return 0;
} }
/* Create pat nodes. */
static void
add_pat (pat, endpat, nchars, argno, raw_before, raw_after, strize, rest)
struct reflist **pat, **endpat;
unsigned int nchars;
unsigned int argno;
int raw_before, raw_after, strize, rest;
{
struct reflist *tpat;
tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
tpat->next = NULL;
tpat->raw_before = raw_before;
tpat->raw_after = raw_after;
tpat->stringify = strize;
tpat->rest_args = rest;
tpat->argno = argno;
tpat->nchars = nchars;
if (*endpat == NULL)
*pat = tpat;
else
(*endpat)->next = tpat;
*endpat = tpat;
}
/* Issue warnings for macro argument names seen inside strings. */ /* Issue warnings for macro argument names seen inside strings. */
static void static void
warn_trad_stringify (pfile, p, len, argc, argv) warn_trad_stringify (pfile, p, len, argc, argv)
...@@ -287,7 +319,6 @@ warn_trad_stringify (pfile, p, len, argc, argv) ...@@ -287,7 +319,6 @@ warn_trad_stringify (pfile, p, len, argc, argv)
size_t len; size_t len;
unsigned int argc; unsigned int argc;
const struct arg *argv; const struct arg *argv;
{ {
U_CHAR *limit; U_CHAR *limit;
unsigned int i; unsigned int i;
...@@ -315,6 +346,59 @@ warn_trad_stringify (pfile, p, len, argc, argv) ...@@ -315,6 +346,59 @@ warn_trad_stringify (pfile, p, len, argc, argv)
} }
} }
/* Generate pat nodes for macro arguments seen inside strings. */
static unsigned int
trad_stringify (pfile, base, len, argc, argv, pat, endpat, last)
cpp_reader *pfile;
U_CHAR *base;
size_t len;
unsigned int argc;
const struct arg *argv;
struct reflist **pat, **endpat;
unsigned int last;
{
U_CHAR *p, *limit;
unsigned int i;
p = base;
limit = base + len;
for (;;)
{
proceed:
while (p < limit && !is_idstart (*p)) p++;
if (p >= limit)
break;
for (i = 0; i < argc; i++)
if (!strncmp (p, argv[i].name, argv[i].len)
&& ! is_idchar (p[argv[i].len]))
{
if (CPP_WTRADITIONAL (pfile))
cpp_warning (pfile, "macro argument \"%s\" is stringified",
argv[i].name);
/* Write out the string up to this point, and add a pat
node for the argument. Note that the argument is NOT
stringified. */
CPP_PUTS (pfile, base, p - base);
add_pat (pat, endpat, CPP_WRITTEN (pfile) - last, i /* argno */,
!is_hspace (p[-1]) /* raw_before */,
!is_hspace (p[argv[i].len]) /* raw_after */,
0 /* strize */,
argv[i].rest_arg);
last = CPP_WRITTEN (pfile);
base = p + argv[i].len;
goto proceed;
}
p++;
while (p < limit && is_idchar (*p)) p++;
if (p >= limit)
break;
}
CPP_PUTS (pfile, base, p - base);
return last;
}
/* Read a replacement list for a macro, and build the DEFINITION /* Read a replacement list for a macro, and build the DEFINITION
structure. LIST contains the replacement list, beginning at structure. LIST contains the replacement list, beginning at
REPLACEMENT. ARGLIST specifies the formal parameters to look for REPLACEMENT. ARGLIST specifies the formal parameters to look for
...@@ -332,7 +416,7 @@ collect_expansion (pfile, list, arglist, replacement) ...@@ -332,7 +416,7 @@ collect_expansion (pfile, list, arglist, replacement)
DEFINITION *defn; DEFINITION *defn;
struct reflist *pat = 0, *endpat = 0; struct reflist *pat = 0, *endpat = 0;
enum cpp_ttype token; enum cpp_ttype token;
long start, last; unsigned int start, last;
unsigned int i; unsigned int i;
int j, argc; int j, argc;
size_t len; size_t len;
...@@ -374,19 +458,21 @@ collect_expansion (pfile, list, arglist, replacement) ...@@ -374,19 +458,21 @@ collect_expansion (pfile, list, arglist, replacement)
/* # is not special in object-like macros. It is special in /* # is not special in object-like macros. It is special in
function-like macros with no args. (6.10.3.2 para 1.) function-like macros with no args. (6.10.3.2 para 1.)
However, it is not special after PASTE. (Implied by However, it is not special after PASTE. (Implied by
6.10.3.3 para 4.) */ 6.10.3.3 para 4.) Nor is it special if -traditional. */
if (arglist == NULL || last_token == PASTE) if (arglist == NULL || last_token == PASTE
goto norm; || CPP_TRADITIONAL (pfile))
break;
last_token = STRIZE; last_token = STRIZE;
break; continue;
case CPP_PASTE: case CPP_PASTE:
if (last_token == PASTE) /* ## is not special if it appears right after another ##;
/* ## ## - the second ## is ordinary. */ nor is it special if -traditional. */
goto norm; if (last_token == PASTE || CPP_TRADITIONAL (pfile))
else if (last_token == START) break;
if (last_token == START)
cpp_error (pfile, "`##' at start of macro definition"); cpp_error (pfile, "`##' at start of macro definition");
else if (last_token == ARG) else if (last_token == ARG)
/* If the last token was an argument, mark it raw_after. */ /* If the last token was an argument, mark it raw_after. */
endpat->raw_after = 1; endpat->raw_after = 1;
...@@ -395,12 +481,33 @@ collect_expansion (pfile, list, arglist, replacement) ...@@ -395,12 +481,33 @@ collect_expansion (pfile, list, arglist, replacement)
CPP_PUTC (pfile, '#'); CPP_PUTC (pfile, '#');
last_token = PASTE; last_token = PASTE;
break; continue;
default:;
}
if (last_token != PASTE && last_token != START
&& (list->tokens[i].flags & HSPACE_BEFORE))
CPP_PUTC (pfile, ' ');
if (last_token == ARG && CPP_TRADITIONAL (pfile)
&& !(list->tokens[i].flags & HSPACE_BEFORE))
endpat->raw_after = 1;
switch (token)
{
case CPP_STRING: case CPP_STRING:
case CPP_CHAR: case CPP_CHAR:
if (argc && CPP_WTRADITIONAL (pfile)) if (argc)
warn_trad_stringify (pfile, tok, len, argc, argv); {
if (CPP_TRADITIONAL (pfile))
{
last = trad_stringify (pfile, tok, len, argc, argv,
&pat, &endpat, last);
break;
}
if (CPP_WTRADITIONAL (pfile))
warn_trad_stringify (pfile, tok, len, argc, argv);
}
goto norm; goto norm;
case CPP_NAME: case CPP_NAME:
...@@ -419,31 +526,20 @@ collect_expansion (pfile, list, arglist, replacement) ...@@ -419,31 +526,20 @@ collect_expansion (pfile, list, arglist, replacement)
CPP_PUTC (pfile, ' '); CPP_PUTC (pfile, ' ');
CPP_PUTS (pfile, tok, len); CPP_PUTS (pfile, tok, len);
last_token = NORM; last_token = NORM;
break;
} }
continue; continue;
addref: addref:
{ {
struct reflist *tpat; int raw_before = (last_token == PASTE
if (last_token != PASTE && (list->tokens[i].flags & HSPACE_BEFORE)) || (CPP_TRADITIONAL (pfile)
CPP_PUTC (pfile, ' '); && !(list->tokens[i].flags & HSPACE_BEFORE)));
/* Make a pat node for this arg and add it to the pat list */ add_pat (&pat, &endpat,
tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); CPP_WRITTEN (pfile) - last /* nchars */, j /* argno */,
tpat->next = NULL; raw_before, 0 /* raw_after */,
tpat->raw_before = (last_token == PASTE); (last_token == STRIZE), argv[j].rest_arg);
tpat->raw_after = 0;
tpat->stringify = (last_token == STRIZE);
tpat->rest_args = argv[j].rest_arg;
tpat->argno = j;
tpat->nchars = CPP_WRITTEN (pfile) - last;
if (endpat == NULL)
pat = tpat;
else
endpat->next = tpat;
endpat = tpat;
last = CPP_WRITTEN (pfile); last = CPP_WRITTEN (pfile);
} }
last_token = ARG; last_token = ARG;
...@@ -1028,8 +1124,11 @@ _cpp_macroexpand (pfile, hp) ...@@ -1028,8 +1124,11 @@ _cpp_macroexpand (pfile, hp)
} }
else if (i < nargs) else if (i < nargs)
{ {
/* traditional C allows foo() if foo wants one argument. */
if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
;
/* the rest args token is allowed to absorb 0 tokens */ /* the rest args token is allowed to absorb 0 tokens */
if (i == nargs - 1 && defn->rest_args) else if (i == nargs - 1 && defn->rest_args)
rest_zero = 1; rest_zero = 1;
else if (i == 0) else if (i == 0)
cpp_error (pfile, "macro `%s' used without args", hp->name); cpp_error (pfile, "macro `%s' used without args", hp->name);
...@@ -1317,8 +1416,19 @@ _cpp_macroexpand (pfile, hp) ...@@ -1317,8 +1416,19 @@ _cpp_macroexpand (pfile, hp)
/* Pop the space we've used in the token_buffer for argument expansion. */ /* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written); CPP_SET_WRITTEN (pfile, old_written);
/* Per C89, a macro cannot be expanded recursively. */ /* In C89, a macro cannot be expanded recursively. Traditional C
hp->type = T_DISABLED; permits it, but any use in an object-like macro must lead to
infinite recursion, so always follow C89 in object-like macros.
The only example known where this doesn't cause infinite recursion
in function-like macros is:
#define foo(x,y) bar(x(y, 0))
foo(foo, baz)
which expands to bar(foo(baz, 0)) in C89 and
bar(bar(baz(0, 0)) in K+R. This looks pathological to me.
If someone has a real-world example I would love to see it. */
if (nargs <= 0 || !CPP_TRADITIONAL (pfile))
hp->type = T_DISABLED;
} }
/* Return 1 iff a token ending in C1 followed directly by a token C2 /* Return 1 iff a token ending in C1 followed directly by a token C2
......
...@@ -513,6 +513,11 @@ _cpp_scan_line (pfile, list) ...@@ -513,6 +513,11 @@ _cpp_scan_line (pfile, list)
space_before = 1; space_before = 1;
continue; continue;
} }
else if (type == CPP_COMMENT)
/* Only happens when processing -traditional macro definitions.
Do not give this a token entry, but do not change space_before
either. */
continue;
if (list->tokens_used >= list->tokens_cap) if (list->tokens_used >= list->tokens_cap)
expand_token_space (list); expand_token_space (list);
...@@ -644,13 +649,17 @@ skip_comment (pfile, m) ...@@ -644,13 +649,17 @@ skip_comment (pfile, m)
} }
else if (CPP_OPTION (pfile, cplusplus_comments)) else if (CPP_OPTION (pfile, cplusplus_comments))
{ {
if (CPP_OPTION (pfile, c89) if (! CPP_BUFFER (pfile)->warned_cplusplus_comments)
&& CPP_PEDANTIC (pfile)
&& ! CPP_BUFFER (pfile)->warned_cplusplus_comments)
{ {
cpp_pedwarn (pfile, if (CPP_WTRADITIONAL (pfile))
"C++ style comments are not allowed in ISO C89"); cpp_pedwarn (pfile,
cpp_pedwarn (pfile, "C++ style comments are not allowed in traditional C");
else if (CPP_OPTION (pfile, c89) && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile,
"C++ style comments are not allowed in ISO C89");
if (CPP_WTRADITIONAL (pfile)
|| (CPP_OPTION (pfile, c89) && CPP_PEDANTIC (pfile)))
cpp_pedwarn (pfile,
"(this will be reported only once per input file)"); "(this will be reported only once per input file)");
CPP_BUFFER (pfile)->warned_cplusplus_comments = 1; CPP_BUFFER (pfile)->warned_cplusplus_comments = 1;
} }
...@@ -1053,7 +1062,11 @@ _cpp_lex_token (pfile) ...@@ -1053,7 +1062,11 @@ _cpp_lex_token (pfile)
if (!CPP_OPTION (pfile, discard_comments)) if (!CPP_OPTION (pfile, discard_comments))
return CPP_COMMENT; return CPP_COMMENT;
else if (CPP_TRADITIONAL (pfile)) else if (CPP_TRADITIONAL (pfile))
goto get_next; {
if (pfile->parsing_define_directive)
return CPP_COMMENT;
goto get_next;
}
else else
{ {
CPP_PUTC (pfile, c); CPP_PUTC (pfile, c);
......
...@@ -352,7 +352,7 @@ do_define (pfile) ...@@ -352,7 +352,7 @@ do_define (pfile)
if (list->tokens_used == 2 && list->tokens[1].type == CPP_VSPACE) if (list->tokens_used == 2 && list->tokens[1].type == CPP_VSPACE)
empty = 0; /* Empty definition of object-like macro. */ empty = 1; /* Empty definition of object-like macro. */
/* If the next character, with no intervening whitespace, is '(', /* If the next character, with no intervening whitespace, is '(',
then this is a function-like macro. Otherwise it is an object- then this is a function-like macro. Otherwise it is an object-
...@@ -425,7 +425,8 @@ do_define (pfile) ...@@ -425,7 +425,8 @@ do_define (pfile)
} }
else else
{ {
HASHNODE *hp = _cpp_make_hashnode (sym, len, T_MACRO, hash); HASHNODE *hp = _cpp_make_hashnode (sym, len, empty ? T_EMPTY : T_MACRO,
hash);
hp->value.defn = def; hp->value.defn = def;
*slot = hp; *slot = hp;
} }
...@@ -768,7 +769,7 @@ do_undef (pfile) ...@@ -768,7 +769,7 @@ do_undef (pfile)
if (CPP_OPTION (pfile, debug_output)) if (CPP_OPTION (pfile, debug_output))
pass_thru_directive (hp->name, len, pfile, T_UNDEF); pass_thru_directive (hp->name, len, pfile, T_UNDEF);
if (hp->type != T_MACRO) if (hp->type != T_MACRO && hp->type != T_EMPTY)
cpp_warning (pfile, "undefining `%s'", hp->name); cpp_warning (pfile, "undefining `%s'", hp->name);
htab_clear_slot (pfile->hashtab, (void **)slot); htab_clear_slot (pfile->hashtab, (void **)slot);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment