summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Booth <neil@daikokuya.co.uk>2002-07-23 22:57:49 +0000
committerNeil Booth <neil@gcc.gnu.org>2002-07-23 22:57:49 +0000
commita69cbaac60d73feb37e6c17abd6f84991dc791a0 (patch)
treed7305615fe0d53e288982b583d2c9c637deb2699
parentb841421a28b7e7c616e58cae4b5e36599f288b7f (diff)
downloadgcc-a69cbaac60d73feb37e6c17abd6f84991dc791a0.tar.gz
cppexp.c (parse_defined): Mark macro used.
* 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. From-SVN: r55692
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/cppexp.c2
-rw-r--r--gcc/cpphash.h12
-rw-r--r--gcc/cppinit.c15
-rw-r--r--gcc/cpplib.c20
-rw-r--r--gcc/cpplib.h3
-rw-r--r--gcc/cppmacro.c29
-rw-r--r--gcc/cpptrad.c2
-rw-r--r--gcc/doc/cppopts.texi10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/Wunused.c32
-rw-r--r--gcc/testsuite/gcc.dg/cpp/Wunused.h1
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/Wunused.c31
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/Wunused.h1
14 files changed, 177 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 15020fff59c..95afea08c82 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2002-07-24 Neil Booth <neil@daikokuya.co.uk>
+
+ * 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.
+
2002-07-23 Neil Booth <neil@daikokuya.co.uk>
* dwarf2out.c (SECTION_ASM_OP,
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index b66fea925e7..569043651d6 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -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;
diff --git a/gcc/cpphash.h b/gcc/cpphash.h
index 133c9b93015..5e69c853b98 100644
--- a/gcc/cpphash.h
+++ b/gcc/cpphash.h
@@ -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 ((cpp_reader *, cpp_macro *,
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 *));
diff --git a/gcc/cppinit.c b/gcc/cppinit.c
index a6be4aa6736..6a4dd0a53f8 100644
--- a/gcc/cppinit.c
+++ b/gcc/cppinit.c
@@ -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, handler)
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) \
@@ -1692,6 +1700,13 @@ cpp_handle_option (pfile, argc, argv)
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:
CPP_OPTION (pfile, warn_undef) = 1;
break;
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index c87572aba12..935a0e0b882 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -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);
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index c407321ff43..8902f536902 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -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;
diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c
index 4d807a226ad..c8e2410af61 100644
--- a/gcc/cppmacro.c
+++ b/gcc/cppmacro.c
@@ -74,6 +74,29 @@ static void check_trad_stringification PARAMS ((cpp_reader *,
const cpp_macro *,
const cpp_string *));
+/* Emits a warning if NODE is a macro defined in the main file that
+ has not been used. */
+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 +751,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 +1513,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 +1549,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,
diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c
index e8b5a1e638d..51b0bfc9cb5 100644
--- a/gcc/cpptrad.c
+++ b/gcc/cpptrad.c
@@ -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;
}
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 6fb3b53f157..24c6edd238d 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -110,6 +110,16 @@ Warn whenever an identifier which is not a macro is encountered in an
@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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index df3fa02f844..b3742503184 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2002-07-24 Neil Booth <neil@daikokuya.co.uk>
+
+ * gcc.dg/cpp/trad/Wunused.c, gcc.dg/cpp/trad/Wunused.h,
+ gcc.dg/cpp/Wunused.c, gcc.dg/cpp/Wunused.h: New tests.
+
2002-07-23 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.c-torture/execute/va-arg-15.x, va-arg-16.x, va-arg-17.x:
diff --git a/gcc/testsuite/gcc.dg/cpp/Wunused.c b/gcc/testsuite/gcc.dg/cpp/Wunused.c
new file mode 100644
index 00000000000..f134f55a159
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/Wunused.c
@@ -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
diff --git a/gcc/testsuite/gcc.dg/cpp/Wunused.h b/gcc/testsuite/gcc.dg/cpp/Wunused.h
new file mode 100644
index 00000000000..8b54412bdd4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/Wunused.h
@@ -0,0 +1 @@
+#define unused_but_ok
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/Wunused.c b/gcc/testsuite/gcc.dg/cpp/trad/Wunused.c
new file mode 100644
index 00000000000..fd81a27ecc7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/trad/Wunused.c
@@ -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
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/Wunused.h b/gcc/testsuite/gcc.dg/cpp/trad/Wunused.h
new file mode 100644
index 00000000000..8b54412bdd4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/trad/Wunused.h
@@ -0,0 +1 @@
+#define unused_but_ok