aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zack@wolery.cumb.org>2000-04-22 23:02:08 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-04-22 23:02:08 +0000
commit0f89df67fc5dbad0e6eb068f6facc4cbb0342c0d (patch)
treece631ea761f6a054491332ece44f6ba0154f01b3
parent4ff812cd3f08389d68aa257bbfa9baaf9dbda2cc (diff)
downloadgcc-0f89df67fc5dbad0e6eb068f6facc4cbb0342c0d.zip
gcc-0f89df67fc5dbad0e6eb068f6facc4cbb0342c0d.tar.gz
gcc-0f89df67fc5dbad0e6eb068f6facc4cbb0342c0d.tar.bz2
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
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/cpphash.c184
-rw-r--r--gcc/cpplex.c27
-rw-r--r--gcc/cpplib.c7
4 files changed, 186 insertions, 47 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ec86bbd..28db7ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cpphash.c b/gcc/cpphash.c
index c39ca9f..26d03fe 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 effb6ca..3e6a89f 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 f881584..7f2554b 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);