This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: preprocessor option to dump "used" macros


Since the response to the initial posting was favourable to the
inclusion of this feature, this is the patch I'll commit subject to
passing bootstrap with no regressions on i686-pc-linux-gnu.

I've added the toplev.c change to avoid a warning on every use of -dU,
and converted the testcases into DejaGnu format.  Note that these
DejaGnu format tests test the particular output of the preprocessor
more closely than the standalone testsuite (which tried to allow for
all valid output possibilities), so some changes to the preprocessor
may require some of these tests to be updated to allow for different
but still correct output generated.

gcc:
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.

gcc/testsuite:
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.

libcpp:
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.

Index: gcc/doc/cppopts.texi
===================================================================
--- gcc/doc/cppopts.texi	(revision 133836)
+++ gcc/doc/cppopts.texi	(working copy)
@@ -682,6 +682,14 @@
 @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: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 133836)
+++ gcc/toplev.c	(working copy)
@@ -1067,6 +1067,7 @@
       case 'I':
       case 'M':
       case 'N':
+      case 'U':
 	break;
       case 'H':
 	setup_core_dumping();
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-5.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-10.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-18.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-6.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-11.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-19.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-20.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-7.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-12.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-21.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-8.c	(revision 0)
@@ -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)
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-13.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-22.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-1.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-9.c	(revision 0)
@@ -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: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-14.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-2.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-15.c	(revision 0)
@@ -0,0 +1,5 @@
+/* { dg-do preprocess } */
+/* { dg-options "-P -dU" } */
+/* { dg-final { scan-file cmdlne-dU-15.i "^\n*\n*$" } } */
+#if A
+#endif
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-3.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-16.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-4.c	(revision 0)
@@ -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
Index: gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/cmdlne-dU-17.c	(revision 0)
@@ -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__
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 133836)
+++ gcc/c-opts.c	(working copy)
@@ -1668,6 +1668,7 @@
       case 'M':			/* Dump macros only.  */
       case 'N':			/* Dump names.  */
       case 'D':			/* Dump definitions.  */
+      case 'U':			/* Dump used macros.  */
 	flag_dump_macros = c;
 	break;
 
Index: gcc/c-ppoutput.c
===================================================================
--- gcc/c-ppoutput.c	(revision 133836)
+++ gcc/c-ppoutput.c	(working copy)
@@ -39,6 +39,17 @@
   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_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 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 @@
       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 @@
 {
   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 @@
 }
 
 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: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 133836)
+++ gcc/c-common.h	(working copy)
@@ -358,8 +358,8 @@
 
 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: libcpp/macro.c
===================================================================
--- libcpp/macro.c	(revision 133836)
+++ libcpp/macro.c	(working copy)
@@ -815,6 +815,13 @@
 
   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 @@
       /* 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 @@
   /* 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
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c	(revision 133836)
+++ libcpp/directives.c	(working copy)
@@ -559,9 +559,14 @@
       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 @@
 
   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 @@
   /* 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 @@
 
   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 @@
 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 @@
 	{
 	  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 @@
   if (node == NULL)
     return;
 
+  if (pfile->cb.before_define)
+    pfile->cb.before_define (pfile);
+
   if (node->type == NT_MACRO)
     {
       if (pfile->cb.undef)
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 133836)
+++ libcpp/include/cpplib.h	(working copy)
@@ -480,6 +480,14 @@
      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 @@
 #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: libcpp/expr.c
===================================================================
--- libcpp/expr.c	(revision 133836)
+++ libcpp/expr.c	(working copy)
@@ -637,6 +637,20 @@
 		   "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.  */

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]