From 0f89df67fc5dbad0e6eb068f6facc4cbb0342c0d Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Sat, 22 Apr 2000 23:02:08 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 ++++ gcc/cpphash.c | 184 ++++++++++++++++++++++++++++++++++++++++---------- gcc/cpplex.c | 27 ++++++-- gcc/cpplib.c | 7 +- 4 files changed, 186 insertions(+), 47 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec86bbd02e0..28db7bafdb5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2000-04-22 Zack Weinberg + + * 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 * loop.c (strength_reduce): Fix biv removal code. diff --git a/gcc/cpphash.c b/gcc/cpphash.c index c39ca9f5fa6..26d03fec055 100644 --- a/gcc/cpphash.c +++ b/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 diff --git a/gcc/cpplex.c b/gcc/cpplex.c index effb6ca0510..3e6a89feac5 100644 --- a/gcc/cpplex.c +++ b/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); diff --git a/gcc/cpplib.c b/gcc/cpplib.c index f8815842f58..7f2554bfc06 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.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); -- 2.30.2