-Wunused-macros

Neil Booth neil@daikokuya.co.uk
Tue Jul 23 13:21:00 GMT 2002


As recently discussed, here's a patch to warn about macros
defined in the main file that are not used.  Docs and full
tests included.

I've not added it to -Wunused, since -Wall implies -Wunused,
and I think this option may be too pricey to go there.  If you
disagree, please shout.

Neil.

	* cppexp.c (parse_defined): Mark macro used.
	* cpphash.h (struct cpp_macro): New member "used".
	(_cpp_mark_macro_used, _cpp_warn_if_unused_macro): New.
	(struct cpp_reader): New member.
	* cppinit.c (cpp_finish_options): Set first_unused_line.
	(cpp_finish): Warn of unused macros if requested.
	(OPT_TABLE): New switches.
	(cpp_handle_option): Handle them.
	* cpplib.c (do_undef): Warn if macro unused.
	(do_ifdef, do_ifndef): Mark macro used.
	* cpplib.h (struct cpp_options): New member.
	* cppmacro.c (_cpp_warn_if_unused_macro): New.
	(enter_macro_context): Mark macro used.
	(_cpp_create_definition): Mark macro unused; warn if unused
	when redefined.
	* cpptrad.c (scan_out_logcial_line, push_replacement_text):
	Mark macros used.
	* doc/cppopts.texi: Update.
testsuite:
	* gcc.dg/cpp/trad/Wunused.c, gcc.dg/cpp/trad/Wunused.h,
	gcc.dg/cpp/Wunused.c, gcc.dg/cpp/Wunused.h: New tests.

============================================================
Index: gcc/cppexp.c
--- gcc/cppexp.c	20 Jul 2002 13:31:56 -0000	1.129
+++ gcc/cppexp.c	23 Jul 2002 19:53:22 -0000
@@ -501,6 +501,8 @@ parse_defined (pfile)
 	cpp_error (pfile, DL_WARNING,
 		   "this use of \"defined\" may not be portable");
 
+      _cpp_mark_macro_used (node);
+
       /* A possible controlling macro of the form #if !defined ().
 	 _cpp_parse_expr checks there was no other junk on the line.  */
       pfile->mi_ind_cmacro = node;
============================================================
Index: gcc/cpphash.h
--- gcc/cpphash.h	27 Jun 2002 06:01:58 -0000	1.167
+++ gcc/cpphash.h	23 Jul 2002 19:53:23 -0000
@@ -98,8 +98,15 @@ struct cpp_macro
 
   /* If macro defined in system header.  */
   unsigned int syshdr   : 1;
+
+  /* Non-zero if it has been expanded or had its existence tested.  */
+  unsigned int used     : 1;
 };
 
+#define _cpp_mark_macro_used(NODE) do {					\
+  if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN))	\
+    (NODE)->value.macro->used = 1; } while (0)
+
 /* A generic memory buffer, and operations on it.  */
 typedef struct _cpp_buff _cpp_buff;
 struct _cpp_buff
@@ -370,6 +377,9 @@ struct cpp_reader
      for include files.  (Altered as we get more of them.)  */
   unsigned int max_include_len;
 
+  /* Macros on or after this line are warned about if unused.  */
+  unsigned int first_unused_line;
+
   /* Date and time text.  Calculated together if either is requested.  */
   const uchar *date;
   const uchar *time;
@@ -477,6 +487,8 @@ extern bool _cpp_arguments_ok		PARAMS ((
 						 unsigned int));
 extern const uchar *_cpp_builtin_macro_text PARAMS ((cpp_reader *,
 						     cpp_hashnode *));
+int _cpp_warn_if_unused_macro		PARAMS ((cpp_reader *, cpp_hashnode *,
+						 void *));
 /* In cpphash.c */
 extern void _cpp_init_hashtable		PARAMS ((cpp_reader *, hash_table *));
 extern void _cpp_destroy_hashtable	PARAMS ((cpp_reader *));
============================================================
Index: gcc/cppinit.c
--- gcc/cppinit.c	21 Jul 2002 21:59:02 -0000	1.245
+++ gcc/cppinit.c	23 Jul 2002 19:53:23 -0000
@@ -1009,6 +1009,8 @@ cpp_finish_options (pfile)
       _cpp_maybe_push_include_file (pfile);
     }
 
+  pfile->first_unused_line = pfile->line;
+
   free_chain (CPP_OPTION (pfile, pending)->imacros_head);
   free_chain (CPP_OPTION (pfile, pending)->directive_head);
 }
@@ -1081,6 +1083,10 @@ void
 cpp_finish (pfile)
      cpp_reader *pfile;
 {
+  /* Warn about unused macros before popping the final buffer.  */
+  if (CPP_OPTION (pfile, warn_unused_macros))
+    cpp_forall_identifiers (pfile, _cpp_warn_if_unused_macro, NULL);
+
   /* cpplex.c leaves the final buffer on the stack.  This it so that
      it returns an unending stream of CPP_EOFs to the client.  If we
      popped the buffer, we'd dereference a NULL buffer pointer and
@@ -1165,10 +1171,12 @@ new_pending_directive (pend, text, handl
   DEF_OPT("Wno-traditional",          0,      OPT_Wno_traditional)            \
   DEF_OPT("Wno-trigraphs",            0,      OPT_Wno_trigraphs)              \
   DEF_OPT("Wno-undef",                0,      OPT_Wno_undef)                  \
+  DEF_OPT("Wno-unused-macros",        0,      OPT_Wno_unused_macros)          \
   DEF_OPT("Wsystem-headers",          0,      OPT_Wsystem_headers)            \
   DEF_OPT("Wtraditional",             0,      OPT_Wtraditional)               \
   DEF_OPT("Wtrigraphs",               0,      OPT_Wtrigraphs)                 \
   DEF_OPT("Wundef",                   0,      OPT_Wundef)                     \
+  DEF_OPT("Wunused-macros",           0,      OPT_Wunused_macros)             \
   DEF_OPT("d",                        no_arg, OPT_d)                          \
   DEF_OPT("fno-operator-names",       0,      OPT_fno_operator_names)         \
   DEF_OPT("fno-preprocessed",         0,      OPT_fno_preprocessed)           \
@@ -1690,6 +1698,13 @@ cpp_handle_option (pfile, argc, argv)
 	case OPT_Wno_comment:
 	case OPT_Wno_comments:
 	  CPP_OPTION (pfile, warn_comments) = 0;
+	  break;
+
+	case OPT_Wunused_macros:
+	  CPP_OPTION (pfile, warn_unused_macros) = 1;
+	  break;
+	case OPT_Wno_unused_macros:
+	  CPP_OPTION (pfile, warn_unused_macros) = 0;
 	  break;
 
 	case OPT_Wundef:
============================================================
Index: gcc/cpplib.c
--- gcc/cpplib.c	17 Jul 2002 21:31:27 -0000	1.319
+++ gcc/cpplib.c	23 Jul 2002 19:53:24 -0000
@@ -545,6 +545,9 @@ do_undef (pfile)
       if (node->flags & NODE_WARN)
 	cpp_error (pfile, DL_WARNING, "undefining \"%s\"", NODE_NAME (node));
 
+      if (CPP_OPTION (pfile, warn_unused_macros))
+	_cpp_warn_if_unused_macro (pfile, node, NULL);
+
       _cpp_free_definition (node);
     }
   check_eol (pfile);
@@ -1331,10 +1334,11 @@ do_ifdef (pfile)
       const cpp_hashnode *node = lex_macro_node (pfile);
 
       if (node)
-	skip = node->type != NT_MACRO;
-
-      if (node)
-	check_eol (pfile);
+	{
+	  skip = node->type != NT_MACRO;
+	  _cpp_mark_macro_used (node);
+	  check_eol (pfile);
+	}
     }
 
   push_conditional (pfile, skip, T_IFDEF, 0);
@@ -1351,11 +1355,13 @@ do_ifndef (pfile)
   if (! pfile->state.skipping)
     {
       node = lex_macro_node (pfile);
-      if (node)
-	skip = node->type == NT_MACRO;
 
       if (node)
-	check_eol (pfile);
+	{
+	  skip = node->type == NT_MACRO;
+	  _cpp_mark_macro_used (node);
+	  check_eol (pfile);
+	}
     }
 
   push_conditional (pfile, skip, T_IFNDEF, node);
============================================================
Index: gcc/cpplib.h
--- gcc/cpplib.h	20 Jul 2002 13:31:56 -0000	1.226
+++ gcc/cpplib.h	23 Jul 2002 19:53:24 -0000
@@ -361,6 +361,9 @@ struct cpp_options
   /* Nonzero means warn if undefined identifiers are evaluated in an #if.  */
   unsigned char warn_undef;
 
+  /* Nonzero means warn of unused macros from the main file.  */
+  unsigned char warn_unused_macros;
+
   /* Nonzero for the 1999 C Standard, including corrigenda and amendments.  */
   unsigned char c99;
 
============================================================
Index: gcc/cppmacro.c
--- gcc/cppmacro.c	17 Jul 2002 17:27:13 -0000	1.117
+++ gcc/cppmacro.c	23 Jul 2002 19:53:25 -0000
@@ -74,6 +74,27 @@ static void check_trad_stringification P
 						const cpp_macro *,
 						const cpp_string *));
 
+int
+_cpp_warn_if_unused_macro (pfile, node, v)
+     cpp_reader *pfile;
+     cpp_hashnode *node;
+     void *v ATTRIBUTE_UNUSED;
+{
+  if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
+    {
+      cpp_macro *macro = node->value.macro;
+
+      if (!macro->used
+	  /* Skip front-end built-ins and command line macros.  */
+	  && macro->line >= pfile->first_unused_line
+	  && MAIN_FILE_P (lookup_line (&pfile->line_maps, macro->line)))
+	cpp_error_with_line (pfile, DL_WARNING, macro->line, 0,
+			     "macro \"%s\" is not used", NODE_NAME (node));
+    }
+
+  return 1;
+}
+
 /* Allocates and returns a CPP_STRING token, containing TEXT of length
    LEN, after null-terminating it.  TEXT must be in permanent storage.  */
 static const cpp_token *
@@ -728,6 +749,8 @@ enter_macro_context (pfile, node)
       /* Disable the macro within its expansion.  */
       node->flags |= NODE_DISABLED;
 
+      macro->used = 1;
+
       if (macro->paramc == 0)
 	push_token_context (pfile, node, macro->exp.tokens, macro->count);
 
@@ -1488,6 +1511,7 @@ _cpp_create_definition (pfile, node)
   macro->params = 0;
   macro->paramc = 0;
   macro->variadic = 0;
+  macro->used = 0;
   macro->count = 0;
   macro->fun_like = 0;
   /* To suppress some diagnostics.  */
@@ -1523,6 +1547,9 @@ _cpp_create_definition (pfile, node)
 
   if (node->type != NT_VOID)
     {
+      if (CPP_OPTION (pfile, warn_unused_macros))
+	_cpp_warn_if_unused_macro (pfile, node, NULL);
+
       if (warn_of_redefinition (pfile, node, macro))
 	{
 	  cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0,
============================================================
Index: gcc/cpptrad.c
--- gcc/cpptrad.c	17 Jul 2002 17:27:13 -0000	1.26
+++ gcc/cpptrad.c	23 Jul 2002 19:53:25 -0000
@@ -655,6 +655,7 @@ scan_out_logical_line (pfile, macro)
 		{
 		  cpp_macro *m = fmacro.node->value.macro;
 
+		  m->used = 1;
 		  lex_state = ls_none;
 		  save_argument (&fmacro, out - pfile->out.base);
 
@@ -789,6 +790,7 @@ push_replacement_text (pfile, node)
   else
     {
       cpp_macro *macro = node->value.macro;
+      macro->used = 1;
       text = macro->exp.text;
       len = macro->count;
     }
============================================================
Index: gcc/doc/cppopts.texi
--- gcc/doc/cppopts.texi	2 Jul 2002 22:20:33 -0000	1.8
+++ gcc/doc/cppopts.texi	23 Jul 2002 19:53:25 -0000
@@ -110,6 +110,16 @@ Warn whenever an identifier which is not
 @samp{#if} directive, outside of @samp{defined}.  Such identifiers are
 replaced with zero.
 
+@item -Wunused-macros
+@opindex Wunused-macros
+Warn about macros defined in the main file that are unused.  A macro
+is @dfn{used} if it is expanded or tested for existence at least once.
+The preprocessor will also warn if the macro has not been used at the
+time it is redefined or undefined.
+
+Built-in macros, macros defined on the command line, and macros
+defined in include files are not warned about.
+
 @item -Wendif-labels
 @opindex Wendif-labels
 Warn whenever an @samp{#else} or an @samp{#endif} are followed by text.
============================================================
Index: gcc/testsuite/gcc.dg/cpp/Wunused.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/cpp/Wunused.c	23 Jul 2002 19:53:25 -0000
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+/* { dg-options -Wunused-macros } */
+
+/* Test everything related to -Wunused-macros.
+
+   Source: Neil Booth, 23 Jul 2002.  */
+
+#include "Wunused.h"
+
+#define used1			/* { dg-bogus "used" } */
+#define used2			/* { dg-bogus "used" } */
+#define used3			/* { dg-bogus "used" } */
+#define used4 used4		/* { dg-bogus "used" } */
+
+#define unused5			/* { dg-warning "used" } */
+#define unused6			/* { dg-warning "used" } */
+#define unused7()		/* { dg-warning "used" } */
+
+#if defined used1
+#endif
+#ifdef used2
+#endif
+#ifndef used3
+#endif
+used4
+
+unused7
+#undef unused5
+#define unused6
+unused6
============================================================
Index: gcc/testsuite/gcc.dg/cpp/Wunused.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/cpp/Wunused.h	23 Jul 2002 19:53:25 -0000
@@ -0,0 +1 @@
+#define unused_but_ok
============================================================
Index: gcc/testsuite/gcc.dg/cpp/trad/Wunused.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/cpp/trad/Wunused.c	23 Jul 2002 19:53:25 -0000
@@ -0,0 +1,31 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+/* { dg-options "-Wunused-macros -traditional-cpp" } */
+
+/* Test everything related to -Wunused-macros.
+
+   Source: Neil Booth, 23 Jul 2002.  */
+
+#include "Wunused.h"
+
+#define used1			/* { dg-bogus "used" } */
+#define used2			/* { dg-bogus "used" } */
+#define used3			/* { dg-bogus "used" } */
+#define used4 something		/* { dg-bogus "used" } */
+
+#define unused5			/* { dg-warning "used" } */
+#define unused6			/* { dg-warning "used" } */
+#define unused7()		/* { dg-warning "used" } */
+
+#if defined used1
+#endif
+#ifdef used2
+#endif
+#ifndef used3
+#endif
+used4
+
+#undef unused5
+#define unused6
+unused6
============================================================
Index: gcc/testsuite/gcc.dg/cpp/trad/Wunused.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/cpp/trad/Wunused.h	23 Jul 2002 19:53:25 -0000
@@ -0,0 +1 @@
+#define unused_but_ok



More information about the Gcc-patches mailing list