gcc:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Apr 2008 19:42:53 +0000 (19:42 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Apr 2008 19:42:53 +0000 (19:42 +0000)
* 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:
gcc/ChangeLog
gcc/c-common.h
gcc/c-opts.c
gcc/c-ppoutput.c
gcc/doc/cppopts.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c [new file with mode: 0644]
gcc/toplev.c
libcpp/ChangeLog
libcpp/directives.c
libcpp/expr.c
libcpp/include/cpplib.h
libcpp/macro.c

index 279b663..e32f884 100644 (file)
@@ -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. 
index a072710..10933e9 100644 (file)
@@ -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;
 
index 69c4d54..1413b7f 100644 (file)
@@ -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;
 
index 6a251fe..5fb41b2 100644 (file)
@@ -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)
index dbc8f0e..4b02a87 100644 (file)
@@ -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
index 432e9e0..1e2d40d 100644 (file)
@@ -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 (file)
index 0000000..ce3f5b7
--- /dev/null
@@ -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 (file)
index 0000000..dd1474a
--- /dev/null
@@ -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 (file)
index 0000000..c9cc593
--- /dev/null
@@ -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 (file)
index 0000000..bf765fb
--- /dev/null
@@ -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 (file)
index 0000000..3ab08d5
--- /dev/null
@@ -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 (file)
index 0000000..5d36f1a
--- /dev/null
@@ -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 (file)
index 0000000..a6a9618
--- /dev/null
@@ -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 (file)
index 0000000..8e5078b
--- /dev/null
@@ -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 (file)
index 0000000..c543439
--- /dev/null
@@ -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 (file)
index 0000000..0b2c543
--- /dev/null
@@ -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 (file)
index 0000000..50edfc2
--- /dev/null
@@ -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 (file)
index 0000000..e475463
--- /dev/null
@@ -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 (file)
index 0000000..4845b51
--- /dev/null
@@ -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 (file)
index 0000000..c17a043
--- /dev/null
@@ -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 (file)
index 0000000..383a29f
--- /dev/null
@@ -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 (file)
index 0000000..26c6ec1
--- /dev/null
@@ -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 (file)
index 0000000..9c57ffe
--- /dev/null
@@ -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 (file)
index 0000000..01880b7
--- /dev/null
@@ -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 (file)
index 0000000..edf6b44
--- /dev/null
@@ -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 (file)
index 0000000..43a6634
--- /dev/null
@@ -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 (file)
index 0000000..d5984a3
--- /dev/null
@@ -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 (file)
index 0000000..ac8b921
--- /dev/null
@@ -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
index 36b24d7..b4b628d 100644 (file)
@@ -1067,6 +1067,7 @@ decode_d_option (const char *arg)
       case 'I':
       case 'M':
       case 'N':
+      case 'U':
        break;
       case 'H':
        setup_core_dumping();
index e8719d9..f5c623d 100644 (file)
@@ -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
index 249a232..0ca1117 100644 (file)
@@ -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)
index 9df7533..9e89dd9 100644 (file)
@@ -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.  */
index e205be7..84de0e0 100644 (file)
@@ -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
index fd624b1..587b948 100644 (file)
@@ -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