diff options
author | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-04-02 19:42:53 +0000 |
---|---|---|
committer | jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-04-02 19:42:53 +0000 |
commit | 34c3de48578a737fce63c51b7a6f63db5c7d43ab (patch) | |
tree | f70286f28df6c1a7f1cb8695448540d74ba1f396 | |
parent | 483108791801d42d879b6aa23b1954e1f692d372 (diff) | |
download | gcc-34c3de48578a737fce63c51b7a6f63db5c7d43ab.tar.gz |
gcc:
* doc/cppopts.texi (-dU): Document.
* c-common.h (flag_dump_macros): Update comment.
* c-opts.c (handle_OPT_d): Handle -dU.
* c-ppoutput.c (macro_queue, define_queue, undef_queue,
dump_queued_macros, cb_used_define, cb_used_undef): New.
(init_pp_output): Handle -dU.
(cb_line_change): Call dump_queued_macros.
* toplev.c (decode_d_option): Accept -dU as preprocessor option.
gcc/testsuite:
* gcc.dg/cpp/cmdlne-dU-1.c, gcc.dg/cpp/cmdlne-dU-2.c,
gcc.dg/cpp/cmdlne-dU-3.c, gcc.dg/cpp/cmdlne-dU-4.c,
gcc.dg/cpp/cmdlne-dU-5.c, gcc.dg/cpp/cmdlne-dU-6.c,
gcc.dg/cpp/cmdlne-dU-7.c, gcc.dg/cpp/cmdlne-dU-8.c,
gcc.dg/cpp/cmdlne-dU-9.c, gcc.dg/cpp/cmdlne-dU-10.c,
gcc.dg/cpp/cmdlne-dU-11.c, gcc.dg/cpp/cmdlne-dU-12.c,
gcc.dg/cpp/cmdlne-dU-13.c, gcc.dg/cpp/cmdlne-dU-14.c,
gcc.dg/cpp/cmdlne-dU-15.c, gcc.dg/cpp/cmdlne-dU-16.c,
gcc.dg/cpp/cmdlne-dU-17.c, gcc.dg/cpp/cmdlne-dU-18.c,
gcc.dg/cpp/cmdlne-dU-19.c, gcc.dg/cpp/cmdlne-dU-20.c,
gcc.dg/cpp/cmdlne-dU-21.c, gcc.dg/cpp/cmdlne-dU-22.c: New tests.
libcpp:
* include/cpplib.h (struct cpp_callbacks): Add used_define,
used_undef and before_define.
(NODE_USED): Define.
* directives.c (do_define, do_undef, undefine_macros, do_ifdef,
do_ifndef, cpp_pop_definition): Handle new flag and use new
callbacks.
* expr.c (parse_defined): Handle new flag and use new callbacks.
* macro.c (enter_macro_context, _cpp_free_definition): Handle new
flag and use new callbacks.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@133847 138bc75d-0d04-0410-961f-82ee72b054a4
34 files changed, 360 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 279b66312f2..e32f8846aea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2008-04-02 Joseph Myers <joseph@codesourcery.com> + + * doc/cppopts.texi (-dU): Document. + * c-common.h (flag_dump_macros): Update comment. + * c-opts.c (handle_OPT_d): Handle -dU. + * c-ppoutput.c (macro_queue, define_queue, undef_queue, + dump_queued_macros, cb_used_define, cb_used_undef): New. + (init_pp_output): Handle -dU. + (cb_line_change): Call dump_queued_macros. + * toplev.c (decode_d_option): Accept -dU as preprocessor option. + 2008-04-02 Anatoly Sokolov <aesok@post.ru> * config/avr/predicates.md (io_address_operand): New predicate. diff --git a/gcc/c-common.h b/gcc/c-common.h index a072710c9ab..10933e9dd82 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -358,8 +358,8 @@ extern char flag_no_line_commands; extern char flag_no_output; -/* Nonzero means dump macros in some fashion; contains the 'D', 'M' or - 'N' of the command line switch. */ +/* Nonzero means dump macros in some fashion; contains the 'D', 'M', + 'N' or 'U' of the command line switch. */ extern char flag_dump_macros; diff --git a/gcc/c-opts.c b/gcc/c-opts.c index 69c4d544885..1413b7f8036 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -1668,6 +1668,7 @@ handle_OPT_d (const char *arg) case 'M': /* Dump macros only. */ case 'N': /* Dump names. */ case 'D': /* Dump definitions. */ + case 'U': /* Dump used macros. */ flag_dump_macros = c; break; diff --git a/gcc/c-ppoutput.c b/gcc/c-ppoutput.c index 6a251fe995c..5fb41b20975 100644 --- a/gcc/c-ppoutput.c +++ b/gcc/c-ppoutput.c @@ -39,6 +39,17 @@ static struct bool first_time; /* pp_file_change hasn't been called yet. */ } print; +/* Defined and undefined macros being queued for output with -dU at + the next newline. */ +typedef struct macro_queue +{ + struct macro_queue *next; /* Next macro in the list. */ + char *macro; /* The name of the macro if not + defined, the full definition if + defined. */ +} macro_queue; +static macro_queue *define_queue, *undef_queue; + /* General output routines. */ static void scan_translation_unit (cpp_reader *); static void print_lines_directives_only (int, const void *, size_t); @@ -46,6 +57,7 @@ static void scan_translation_unit_directives_only (cpp_reader *); static void scan_translation_unit_trad (cpp_reader *); static void account_for_newlines (const unsigned char *, size_t); static int dump_macro (cpp_reader *, cpp_hashnode *, void *); +static void dump_queued_macros (cpp_reader *); static void print_line (source_location, const char *); static void maybe_print_line (source_location); @@ -55,6 +67,8 @@ static void maybe_print_line (source_location); static void cb_line_change (cpp_reader *, const cpp_token *, int); static void cb_define (cpp_reader *, source_location, cpp_hashnode *); static void cb_undef (cpp_reader *, source_location, cpp_hashnode *); +static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *); +static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *); static void cb_include (cpp_reader *, source_location, const unsigned char *, const char *, int, const cpp_token **); static void cb_ident (cpp_reader *, source_location, const cpp_string *); @@ -125,6 +139,13 @@ init_pp_output (FILE *out_stream) cb->undef = cb_undef; } + if (flag_dump_macros == 'U') + { + cb->before_define = dump_queued_macros; + cb->used_define = cb_used_define; + cb->used_undef = cb_used_undef; + } + /* Initialize the print structure. Setting print.src_line to -1 here is a trick to guarantee that the first token of the file will cause a linemarker to be output by maybe_print_line. */ @@ -320,6 +341,9 @@ cb_line_change (cpp_reader *pfile, const cpp_token *token, { source_location src_loc = token->src_loc; + if (define_queue || undef_queue) + dump_queued_macros (pfile); + if (token->type == CPP_EOF || parsing_args) return; @@ -380,6 +404,68 @@ cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line, } static void +cb_used_define (cpp_reader *pfile, source_location line ATTRIBUTE_UNUSED, + cpp_hashnode *node) +{ + macro_queue *q; + q = XNEW (macro_queue); + q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node)); + q->next = define_queue; + define_queue = q; +} + +static void +cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, + source_location line ATTRIBUTE_UNUSED, + cpp_hashnode *node) +{ + macro_queue *q; + q = XNEW (macro_queue); + q->macro = xstrdup ((const char *) NODE_NAME (node)); + q->next = undef_queue; + undef_queue = q; +} + +static void +dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + macro_queue *q; + + /* End the previous line of text. */ + if (print.printed) + { + putc ('\n', print.outf); + print.src_line++; + print.printed = 0; + } + + for (q = define_queue; q;) + { + macro_queue *oq; + fputs ("#define ", print.outf); + fputs (q->macro, print.outf); + putc ('\n', print.outf); + print.src_line++; + oq = q; + q = q->next; + free (oq->macro); + free (oq); + } + define_queue = NULL; + for (q = undef_queue; q;) + { + macro_queue *oq; + fprintf (print.outf, "#undef %s\n", q->macro); + print.src_line++; + oq = q; + q = q->next; + free (oq->macro); + free (oq); + } + undef_queue = NULL; +} + +static void cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line, const unsigned char *dir, const char *header, int angle_brackets, const cpp_token **comments) diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi index dbc8f0e6e67..4b02a87cb8e 100644 --- a/gcc/doc/cppopts.texi +++ b/gcc/doc/cppopts.texi @@ -682,6 +682,14 @@ Like @samp{D}, but emit only the macro names, not their expansions. @opindex dI Output @samp{#include} directives in addition to the result of preprocessing. + +@item U +@opindex dU +Like @samp{D} except that only macros that are expanded, or whose +definedness is tested in preprocessor directives, are output; the +output is delayed until the use or test of the macro; and +@samp{#undef} directives are also output for macros tested but +undefined at the time. @end table @item -P diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 432e9e019a0..1e2d40d9afe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2008-04-02 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/cpp/cmdlne-dU-1.c, gcc.dg/cpp/cmdlne-dU-2.c, + gcc.dg/cpp/cmdlne-dU-3.c, gcc.dg/cpp/cmdlne-dU-4.c, + gcc.dg/cpp/cmdlne-dU-5.c, gcc.dg/cpp/cmdlne-dU-6.c, + gcc.dg/cpp/cmdlne-dU-7.c, gcc.dg/cpp/cmdlne-dU-8.c, + gcc.dg/cpp/cmdlne-dU-9.c, gcc.dg/cpp/cmdlne-dU-10.c, + gcc.dg/cpp/cmdlne-dU-11.c, gcc.dg/cpp/cmdlne-dU-12.c, + gcc.dg/cpp/cmdlne-dU-13.c, gcc.dg/cpp/cmdlne-dU-14.c, + gcc.dg/cpp/cmdlne-dU-15.c, gcc.dg/cpp/cmdlne-dU-16.c, + gcc.dg/cpp/cmdlne-dU-17.c, gcc.dg/cpp/cmdlne-dU-18.c, + gcc.dg/cpp/cmdlne-dU-19.c, gcc.dg/cpp/cmdlne-dU-20.c, + gcc.dg/cpp/cmdlne-dU-21.c, gcc.dg/cpp/cmdlne-dU-22.c: New tests. + 2008-04-02 Richard Guenther <rguenther@suse.de> PR tree-optimization/14495 diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c new file mode 100644 index 00000000000..ce3f5b72128 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c @@ -0,0 +1,5 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-1.i "^\n*#undef A\n*$" } } */ +#ifdef A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c new file mode 100644 index 00000000000..dd1474ad0eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-10.i "^\n*C\n+#define B C\n+#define A B\n*$" } } */ +/* This file deliberately has no final newline. */ +#define A B +#define B C +A
\ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c new file mode 100644 index 00000000000..c9cc5934631 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-11.i "^\n*\n*$" } } */ +#define A B +#if 0 +A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c new file mode 100644 index 00000000000..bf765fbf0eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c @@ -0,0 +1,6 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-12.i "^\n*#define A 1\n*$" } } */ +#define A 1 +#if A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c new file mode 100644 index 00000000000..3ab08d5d59c --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-13.i "^\n*#undef A\n*$" } } */ +#ifdef A +#endif +#ifdef A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c new file mode 100644 index 00000000000..5d36f1acb09 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c @@ -0,0 +1,6 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-14.i "^\n*B\n+#define A B\n+B\n*$" } } */ +#define A B +A +A diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c new file mode 100644 index 00000000000..a6a96182678 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c @@ -0,0 +1,5 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-15.i "^\n*\n*$" } } */ +#if A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c new file mode 100644 index 00000000000..8e5078b5c27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c @@ -0,0 +1,5 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-16.i "^\n*#define __STDC__ 1\n*$" } } */ +#ifdef __STDC__ +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c new file mode 100644 index 00000000000..c543439e71e --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c @@ -0,0 +1,4 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-17.i "^\n*1\n+#define __STDC__ 1\n*$" } } */ +__STDC__ diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c new file mode 100644 index 00000000000..0b2c54307ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c @@ -0,0 +1,5 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-18.i "^\n*x 1 y\n+#define A 1\n*$" } } */ +#define A 1 +x A y diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c new file mode 100644 index 00000000000..50edfc2b959 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c @@ -0,0 +1,8 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-19.i "^\n*B\n+#define A B\n+#undef A\n*$" } } */ +#define A B +A +#undef A +#ifdef A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c new file mode 100644 index 00000000000..e4754630405 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c @@ -0,0 +1,6 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-2.i "^\n*#define A *\n*$" } } */ +#define A +#ifdef A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c new file mode 100644 index 00000000000..4845b51e77b --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c @@ -0,0 +1,5 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-20.i "^\n*A B\n*$" } } */ +#define A(x) x +A B diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c new file mode 100644 index 00000000000..c17a0435ed7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c @@ -0,0 +1,9 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-21.i "^\n*hello There\n+#define ASTRING There\n+#define MACROARGS\\(A\\) A\n+#undef BSTRING\n*$" } } */ +#define ASTRING There +#define MACROARGS(A) A +MACROARGS(hello) ASTRING +#ifdef BSTRING +bye +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c new file mode 100644 index 00000000000..383a29f85e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c @@ -0,0 +1,14 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-22.i "^\n*#undef AAA\n+AAA is undefined\n+#undef BBB\n+BBB is undefined\n+#undef CCC\n+CCC is undefined\n*$" } } */ +#ifndef AAA +AAA is undefined +#endif + +#ifndef BBB +BBB is undefined +#endif + +#ifndef CCC +CCC is undefined +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c new file mode 100644 index 00000000000..26c6ec1de26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c @@ -0,0 +1,6 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-3.i "^\n*#define A B\n*$" } } */ +#define A B +#ifndef A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c new file mode 100644 index 00000000000..9c57ffe7c74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c @@ -0,0 +1,5 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-4.i "^\n*#undef A\n*$" } } */ +#if defined(A) +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c new file mode 100644 index 00000000000..01880b77b5f --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c @@ -0,0 +1,7 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-5.i "^\n*#undef A\n*$" } } */ +#ifdef A +#ifdef B +#endif +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c new file mode 100644 index 00000000000..edf6b444518 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c @@ -0,0 +1,8 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-6.i "^\n*#undef A\n+#define A *\n*$" } } */ +#ifdef A +#endif +#define A +#ifdef A +#endif diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c new file mode 100644 index 00000000000..43a66341d0c --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c @@ -0,0 +1,8 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-7.i "^\n*B\n+#define A B\n+C\n+#define A C\n*$" } } */ +#define A B +A +#undef A +#define A C +A diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c new file mode 100644 index 00000000000..d5984a31494 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c @@ -0,0 +1,6 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-8.i "^\n*B D\n+#define A\\(x\\) B x\n+#define C D\n*$" } } */ +#define A(x) B x +#define C D +A(C) diff --git a/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c new file mode 100644 index 00000000000..ac8b92114ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c @@ -0,0 +1,6 @@ +/* { dg-do preprocess } */ +/* { dg-options "-P -dU" } */ +/* { dg-final { scan-file cmdlne-dU-9.i "^\n*C\n+#define B C\n+#define A B\n*$" } } */ +#define A B +#define B C +A diff --git a/gcc/toplev.c b/gcc/toplev.c index 36b24d7eabf..b4b628d210c 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1067,6 +1067,7 @@ decode_d_option (const char *arg) case 'I': case 'M': case 'N': + case 'U': break; case 'H': setup_core_dumping(); diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index e8719d931e1..f5c623db910 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,15 @@ +2008-04-02 Joseph Myers <joseph@codesourcery.com> + + * include/cpplib.h (struct cpp_callbacks): Add used_define, + used_undef and before_define. + (NODE_USED): Define. + * directives.c (do_define, do_undef, undefine_macros, do_ifdef, + do_ifndef, cpp_pop_definition): Handle new flag and use new + callbacks. + * expr.c (parse_defined): Handle new flag and use new callbacks. + * macro.c (enter_macro_context, _cpp_free_definition): Handle new + flag and use new callbacks. + 2008-04-01 Jakub Jelinek <jakub@redhat.com> PR pch/13675 diff --git a/libcpp/directives.c b/libcpp/directives.c index 249a2324ee7..0ca1117c19a 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -559,9 +559,14 @@ do_define (cpp_reader *pfile) pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments_in_macro_exp); + if (pfile->cb.before_define) + pfile->cb.before_define (pfile); + if (_cpp_create_definition (pfile, node)) if (pfile->cb.define) pfile->cb.define (pfile, pfile->directive_line, node); + + node->flags &= ~NODE_USED; } } @@ -573,6 +578,9 @@ do_undef (cpp_reader *pfile) if (node) { + if (pfile->cb.before_define) + pfile->cb.before_define (pfile); + if (pfile->cb.undef) pfile->cb.undef (pfile, pfile->directive_line, node); @@ -603,7 +611,7 @@ undefine_macros (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *h, /* Body of _cpp_free_definition inlined here for speed. Macros and assertions no longer have anything to free. */ h->type = NT_VOID; - h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED); + h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED|NODE_USED); return 1; } @@ -1638,12 +1646,26 @@ do_ifdef (cpp_reader *pfile) if (! pfile->state.skipping) { - const cpp_hashnode *node = lex_macro_node (pfile, false); + cpp_hashnode *node = lex_macro_node (pfile, false); if (node) { skip = node->type != NT_MACRO; _cpp_mark_macro_used (node); + if (!(node->flags & NODE_USED)) + { + node->flags |= NODE_USED; + if (node->type == NT_MACRO) + { + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + } + else + { + if (pfile->cb.used_undef) + pfile->cb.used_undef (pfile, pfile->directive_line, node); + } + } check_eol (pfile); } } @@ -1656,7 +1678,7 @@ static void do_ifndef (cpp_reader *pfile) { int skip = 1; - const cpp_hashnode *node = 0; + cpp_hashnode *node = 0; if (! pfile->state.skipping) { @@ -1666,6 +1688,20 @@ do_ifndef (cpp_reader *pfile) { skip = node->type == NT_MACRO; _cpp_mark_macro_used (node); + if (!(node->flags & NODE_USED)) + { + node->flags |= NODE_USED; + if (node->type == NT_MACRO) + { + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + } + else + { + if (pfile->cb.used_undef) + pfile->cb.used_undef (pfile, pfile->directive_line, node); + } + } check_eol (pfile); } } @@ -2145,6 +2181,9 @@ cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn) if (node == NULL) return; + if (pfile->cb.before_define) + pfile->cb.before_define (pfile); + if (node->type == NT_MACRO) { if (pfile->cb.undef) diff --git a/libcpp/expr.c b/libcpp/expr.c index 9df75332c05..9e89dd9574a 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -637,6 +637,20 @@ parse_defined (cpp_reader *pfile) "this use of \"defined\" may not be portable"); _cpp_mark_macro_used (node); + if (!(node->flags & NODE_USED)) + { + node->flags |= NODE_USED; + if (node->type == NT_MACRO) + { + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + } + else + { + if (pfile->cb.used_undef) + pfile->cb.used_undef (pfile, pfile->directive_line, node); + } + } /* A possible controlling macro of the form #if !defined (). _cpp_parse_expr checks there was no other junk on the line. */ diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index e205be7cd6c..84de0e09975 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -480,6 +480,14 @@ struct cpp_callbacks This callback receives the translated message. */ void (*error) (cpp_reader *, int, const char *, va_list *) ATTRIBUTE_FPTR_PRINTF(3,0); + + /* Callbacks for when a macro is expanded, or tested (whether + defined or not at the time) in #ifdef, #ifndef or "defined". */ + void (*used_define) (cpp_reader *, unsigned int, cpp_hashnode *); + void (*used_undef) (cpp_reader *, unsigned int, cpp_hashnode *); + /* Called before #define and #undef or other macro definition + changes are processed. */ + void (*before_define) (cpp_reader *); }; /* Chain of directories to look for include files in. */ @@ -537,6 +545,7 @@ extern const char *progname; #define NODE_WARN (1 << 4) /* Warn if redefined or undefined. */ #define NODE_DISABLED (1 << 5) /* A disabled macro. */ #define NODE_MACRO_ARG (1 << 6) /* Used during #define processing. */ +#define NODE_USED (1 << 7) /* Dumped with -dU. */ /* Different flavors of hash node. */ enum node_type diff --git a/libcpp/macro.c b/libcpp/macro.c index fd624b10110..587b94814cc 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -815,6 +815,13 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, pfile->state.angled_headers = false; + if ((node->flags & NODE_BUILTIN) && !(node->flags & NODE_USED)) + { + node->flags |= NODE_USED; + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + } + /* Handle standard macros. */ if (! (node->flags & NODE_BUILTIN)) { @@ -854,6 +861,13 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, /* Disable the macro within its expansion. */ node->flags |= NODE_DISABLED; + if (!(node->flags & NODE_USED)) + { + node->flags |= NODE_USED; + if (pfile->cb.used_define) + pfile->cb.used_define (pfile, pfile->directive_line, node); + } + macro->used = 1; if (macro->paramc == 0) @@ -1393,7 +1407,7 @@ _cpp_free_definition (cpp_hashnode *h) /* Macros and assertions no longer have anything to free. */ h->type = NT_VOID; /* Clear builtin flag in case of redefinition. */ - h->flags &= ~(NODE_BUILTIN | NODE_DISABLED); + h->flags &= ~(NODE_BUILTIN | NODE_DISABLED | NODE_USED); } /* Save parameter NODE to the parameter list of macro MACRO. Returns |