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
This commit is contained in:
parent
4ff812cd3f
commit
0f89df67fc
4 changed files with 186 additions and 47 deletions
|
@ -1,3 +1,18 @@
|
|||
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>
|
||||
|
||||
* loop.c (strength_reduce): Fix biv removal code.
|
||||
|
|
184
gcc/cpphash.c
184
gcc/cpphash.c
|
@ -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,
|
||||
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 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.
|
||||
`raw' points to the argument text as written (`raw_length' is its length).
|
||||
|
@ -279,6 +285,32 @@ macro_cleanup (pbuf, pfile)
|
|||
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. */
|
||||
static void
|
||||
warn_trad_stringify (pfile, p, len, argc, argv)
|
||||
|
@ -287,7 +319,6 @@ warn_trad_stringify (pfile, p, len, argc, argv)
|
|||
size_t len;
|
||||
unsigned int argc;
|
||||
const struct arg *argv;
|
||||
|
||||
{
|
||||
U_CHAR *limit;
|
||||
unsigned int i;
|
||||
|
@ -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
|
||||
structure. LIST contains the replacement list, beginning at
|
||||
REPLACEMENT. ARGLIST specifies the formal parameters to look for
|
||||
|
@ -332,7 +416,7 @@ collect_expansion (pfile, list, arglist, replacement)
|
|||
DEFINITION *defn;
|
||||
struct reflist *pat = 0, *endpat = 0;
|
||||
enum cpp_ttype token;
|
||||
long start, last;
|
||||
unsigned int start, last;
|
||||
unsigned int i;
|
||||
int j, argc;
|
||||
size_t len;
|
||||
|
@ -374,19 +458,21 @@ collect_expansion (pfile, list, arglist, replacement)
|
|||
/* # is not special in object-like macros. It is special in
|
||||
function-like macros with no args. (6.10.3.2 para 1.)
|
||||
However, it is not special after PASTE. (Implied by
|
||||
6.10.3.3 para 4.) */
|
||||
if (arglist == NULL || last_token == PASTE)
|
||||
goto norm;
|
||||
6.10.3.3 para 4.) Nor is it special if -traditional. */
|
||||
if (arglist == NULL || last_token == PASTE
|
||||
|| CPP_TRADITIONAL (pfile))
|
||||
break;
|
||||
last_token = STRIZE;
|
||||
break;
|
||||
continue;
|
||||
|
||||
case CPP_PASTE:
|
||||
if (last_token == PASTE)
|
||||
/* ## ## - the second ## is ordinary. */
|
||||
goto norm;
|
||||
else if (last_token == START)
|
||||
/* ## is not special if it appears right after another ##;
|
||||
nor is it special if -traditional. */
|
||||
if (last_token == PASTE || CPP_TRADITIONAL (pfile))
|
||||
break;
|
||||
|
||||
if (last_token == START)
|
||||
cpp_error (pfile, "`##' at start of macro definition");
|
||||
|
||||
else if (last_token == ARG)
|
||||
/* If the last token was an argument, mark it raw_after. */
|
||||
endpat->raw_after = 1;
|
||||
|
@ -395,12 +481,33 @@ collect_expansion (pfile, list, arglist, replacement)
|
|||
CPP_PUTC (pfile, '#');
|
||||
|
||||
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_CHAR:
|
||||
if (argc && CPP_WTRADITIONAL (pfile))
|
||||
warn_trad_stringify (pfile, tok, len, argc, argv);
|
||||
if (argc)
|
||||
{
|
||||
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;
|
||||
|
||||
case CPP_NAME:
|
||||
|
@ -419,31 +526,20 @@ collect_expansion (pfile, list, arglist, replacement)
|
|||
CPP_PUTC (pfile, ' ');
|
||||
CPP_PUTS (pfile, tok, len);
|
||||
last_token = NORM;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
addref:
|
||||
{
|
||||
struct reflist *tpat;
|
||||
if (last_token != PASTE && (list->tokens[i].flags & HSPACE_BEFORE))
|
||||
CPP_PUTC (pfile, ' ');
|
||||
|
||||
/* Make a pat node for this arg and add it to the pat list */
|
||||
tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
|
||||
tpat->next = NULL;
|
||||
tpat->raw_before = (last_token == PASTE);
|
||||
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;
|
||||
int raw_before = (last_token == PASTE
|
||||
|| (CPP_TRADITIONAL (pfile)
|
||||
&& !(list->tokens[i].flags & HSPACE_BEFORE)));
|
||||
|
||||
add_pat (&pat, &endpat,
|
||||
CPP_WRITTEN (pfile) - last /* nchars */, j /* argno */,
|
||||
raw_before, 0 /* raw_after */,
|
||||
(last_token == STRIZE), argv[j].rest_arg);
|
||||
|
||||
last = CPP_WRITTEN (pfile);
|
||||
}
|
||||
last_token = ARG;
|
||||
|
@ -1028,8 +1124,11 @@ _cpp_macroexpand (pfile, hp)
|
|||
}
|
||||
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 */
|
||||
if (i == nargs - 1 && defn->rest_args)
|
||||
else if (i == nargs - 1 && defn->rest_args)
|
||||
rest_zero = 1;
|
||||
else if (i == 0)
|
||||
cpp_error (pfile, "macro `%s' used without args", hp->name);
|
||||
|
@ -1317,8 +1416,19 @@ _cpp_macroexpand (pfile, hp)
|
|||
/* Pop the space we've used in the token_buffer for argument expansion. */
|
||||
CPP_SET_WRITTEN (pfile, old_written);
|
||||
|
||||
/* Per C89, a macro cannot be expanded recursively. */
|
||||
hp->type = T_DISABLED;
|
||||
/* In C89, a macro cannot be expanded recursively. Traditional C
|
||||
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
|
||||
|
|
27
gcc/cpplex.c
27
gcc/cpplex.c
|
@ -513,6 +513,11 @@ _cpp_scan_line (pfile, list)
|
|||
space_before = 1;
|
||||
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)
|
||||
expand_token_space (list);
|
||||
|
@ -644,13 +649,17 @@ skip_comment (pfile, m)
|
|||
}
|
||||
else if (CPP_OPTION (pfile, cplusplus_comments))
|
||||
{
|
||||
if (CPP_OPTION (pfile, c89)
|
||||
&& CPP_PEDANTIC (pfile)
|
||||
&& ! CPP_BUFFER (pfile)->warned_cplusplus_comments)
|
||||
if (! CPP_BUFFER (pfile)->warned_cplusplus_comments)
|
||||
{
|
||||
cpp_pedwarn (pfile,
|
||||
"C++ style comments are not allowed in ISO C89");
|
||||
cpp_pedwarn (pfile,
|
||||
if (CPP_WTRADITIONAL (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)");
|
||||
CPP_BUFFER (pfile)->warned_cplusplus_comments = 1;
|
||||
}
|
||||
|
@ -1053,7 +1062,11 @@ _cpp_lex_token (pfile)
|
|||
if (!CPP_OPTION (pfile, discard_comments))
|
||||
return CPP_COMMENT;
|
||||
else if (CPP_TRADITIONAL (pfile))
|
||||
goto get_next;
|
||||
{
|
||||
if (pfile->parsing_define_directive)
|
||||
return CPP_COMMENT;
|
||||
goto get_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
CPP_PUTC (pfile, c);
|
||||
|
|
|
@ -352,7 +352,7 @@ do_define (pfile)
|
|||
|
||||
|
||||
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 '(',
|
||||
then this is a function-like macro. Otherwise it is an object-
|
||||
|
@ -425,7 +425,8 @@ do_define (pfile)
|
|||
}
|
||||
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;
|
||||
*slot = hp;
|
||||
}
|
||||
|
@ -768,7 +769,7 @@ do_undef (pfile)
|
|||
if (CPP_OPTION (pfile, debug_output))
|
||||
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);
|
||||
|
||||
htab_clear_slot (pfile->hashtab, (void **)slot);
|
||||
|
|
Loading…
Add table
Reference in a new issue