public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
@ 2011-07-27 21:35 Dodji Seketeli
  2011-07-29  9:35 ` Jason Merrill
  0 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-07-27 21:35 UTC (permalink / raw)
  To: Jason Merrill, Paolo Carlini; +Cc: GCC Patches

Hello,

The patch below implements a new flag to warn when a typedef defined
in a function is unused.  The warning is -Wunused-local-typedef, is
active for the C and C++ FEs and is intended for trunk.

With this patch the compiler caught a few spots of unused local
typedefs in libstdc++ that I have fixed thus.

Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.

-- 
		Dodji

From b4612a6dd8a642795fe81398b372746f19c86614 Mon Sep 17 00:00:00 2001
From: Dodji Seketeli <dodji@redhat.com>
Date: Mon, 25 Jul 2011 19:02:07 +0200
Subject: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning

gcc/

	* Makefile.in: add pointer-set.h dependency to function.h
	* function.h (function::{local_typedefs,used_local_typedefs}): New
	struct members.
	* tree.c (walk_type_fields): Don't forget to walk the underlying
	type of a typedef.
	* c-decl.c (pushdecl, grokdeclarator): Use the new
	record_locally_defined_typedef.
	(finish_function): Use the new maybe_warn_unused_local_typedefs.
	(maybe_record_local_typedef_use_r)
	(c_maybe_record_local_typedef_use): New static functions.
	(maybe_record_local_typedef_use): New public function definition.
	* c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
	maybe_record_local_typedef_use.

gcc/c-family

	* c-common.h (record_locally_defined_typedef)
	(maybe_record_local_typedef_use)
	(maybe_record_local_typedef_use_real)
	(maybe_warn_unused_local_typedefs): Declare new functions.
	* c-common.c (c_sizeof_or_alignof_type): Use the new
	maybe_record_local_typedef_use.
	(record_locally_defined_typedef)
	(maybe_record_local_typedef_use_real)
	(maybe_warn_unused_local_typedefs): Define new functions.
	* c.opt: Declare new -Wunused-local-typedefs flag.

gcc/cp

	* name-lookup.c (pushdecl_maybe_friend_1): Use the new
	record_locally_defined_typedef.
	* cp-tree.h (maybe_record_local_typedef_use): Declare new function.
	* decl.c (grokdeclarator): Use the new
	maybe_record_local_typedef_use.
	(finish_function): Use the new maybe_warn_unused_local_typedefs.
	* decl2.c (cp_maybe_record_local_typedef_use_r)
	(cp_maybe_record_local_typedef_use): New static functions.
	(maybe_record_local_typedef_use): New public function.
	(mark_used): Use the new maybe_record_local_typedef_use.
	* init.c (build_new): Likewise.
	* parser.c (cp_parser_qualifying_entity, cp_parser_template_id):
	Likewise.
	* rtti.c (build_dynamic_cast_1): Use the new
	maybe_record_local_typedef_use.
	* typeck.c (cxx_sizeof_or_alignof_type, build_static_cast_1)
	(build_reinterpret_cast_1)
	(build_const_cast_1): Use the new maybe_record_local_typedef_use.
	* typeck2.c (build_functional_cast): Likewise.

gcc/doc/

	* invoke.texi: Update documentation for -Wunused-local-typedefs.

gcc/testsuite/

	* g++.dg/warn/Wunused-local-typedefs.C: New test file.
	* c-c++-common/Wunused-local-typedefs.c: Likewise.

libstdc++-v3/

	* include/ext/bitmap_allocator.h
	(__detail::__mini_vector::__lower_bound): Remove unused typedef.
	* src/istream.cc (std::operator>>(basic_istream<char>& __in,
	basic_string<char>& __str)): Likewise.
	(std::getline): Likewise.
	* src/valarray.cc (__valarray_product): Likewise.
---
 gcc/Makefile.in                                    |    2 +-
 gcc/c-decl.c                                       |   54 +++++++++++-
 gcc/c-family/c-common.c                            |   95 ++++++++++++++++++++
 gcc/c-family/c-common.h                            |    4 +
 gcc/c-family/c.opt                                 |    4 +
 gcc/c-typeck.c                                     |    5 +
 gcc/cp/cp-tree.h                                   |    1 +
 gcc/cp/decl.c                                      |    6 ++
 gcc/cp/decl2.c                                     |   46 ++++++++++
 gcc/cp/init.c                                      |    2 +
 gcc/cp/name-lookup.c                               |    7 ++
 gcc/cp/parser.c                                    |    7 ++
 gcc/cp/rtti.c                                      |    2 +
 gcc/cp/typeck.c                                    |    7 ++
 gcc/cp/typeck2.c                                   |    2 +
 gcc/doc/invoke.texi                                |    9 ++-
 gcc/function.h                                     |    8 ++
 .../c-c++-common/Wunused-local-typedefs.c          |   38 ++++++++
 gcc/tree.c                                         |    5 +
 libstdc++-v3/include/ext/bitmap_allocator.h        |    2 -
 libstdc++-v3/src/istream.cc                        |    3 -
 libstdc++-v3/src/valarray.cc                       |    1 -
 22 files changed, 300 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 593c951..f92f650 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -937,7 +937,7 @@ ALIAS_H = alias.h coretypes.h
 EMIT_RTL_H = emit-rtl.h
 FLAGS_H = flags.h coretypes.h flag-types.h $(OPTIONS_H)
 OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
-FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H) vecprim.h $(TM_H) hard-reg-set.h
+FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H) vecprim.h $(TM_H) hard-reg-set.h pointer-set.h
 EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
 OPTABS_H = optabs.h insn-codes.h
 REGS_H = regs.h $(MACHMODE_H) hard-reg-set.h
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 33d2615..0ffa831 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2769,7 +2769,15 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    set_underlying_type (x);
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+	 for the purpose of implementing the -Wunused-local-typedefs
+	 warning.  */
+      record_locally_defined_typedef (x);
+    }
 
   bind (name, x, scope, /*invisible=*/false, nested, locus);
 
@@ -6076,6 +6084,8 @@ grokdeclarator (const struct c_declarator *declarator,
      name of a variable.  Thus, if it's known before this, die horribly.  */
     gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
 
+    maybe_record_local_typedef_use (TREE_TYPE (decl));
+
     if (warn_cxx_compat
 	&& TREE_CODE (decl) == VAR_DECL
 	&& TREE_PUBLIC (decl)
@@ -8265,6 +8275,10 @@ finish_function (void)
 		      "parameter %qD set but not used", decl);
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -9888,4 +9902,42 @@ c_register_addr_space (const char *word, addr_space_t as)
   ridpointers [rid] = id;
 }
 
+/* Subroutine of c_maybe_record_local_typedef_use, called from
+   walk_tree_without_duplicates.   */
+
+static tree
+maybe_record_local_typedef_use_r (tree *tp,
+				  int *walk_subtrees ATTRIBUTE_UNUSED,
+				  void *data ATTRIBUTE_UNUSED)
+{
+  maybe_record_local_typedef_use_real (*tp);
+  return NULL_TREE;
+}
+
+/* A subroutine of maybe_record_local_typedef_use.  */
+
+static void
+c_maybe_record_local_typedef_use (tree t)
+{
+    if (!warn_unused_local_typedefs)
+      return;
+
+    maybe_record_local_typedef_use_real (t);
+
+    /* Record the typedefs used by subtypes of TYPE.  */
+    walk_tree_without_duplicates (&t,
+				  maybe_record_local_typedef_use_r,
+				  NULL_TREE);
+}
+
+/* If T is a typedef variant type or a TYPE_DECL declared locally,
+   record it in CFUN->USED_LOCAL_TYPEDEFS.  This function also records
+   the typedefs that are direct or indirect subtypes of T.  */
+
+void
+maybe_record_local_typedef_use (tree t)
+{
+  c_maybe_record_local_typedef_use (t);
+}
+
 #include "gt-c-decl.h"
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 96275ba..7036da6 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4340,6 +4340,8 @@ c_sizeof_or_alignof_type (location_t loc,
   value = fold_convert_loc (loc, size_type_node, value);
   gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
 
+  maybe_record_local_typedef_use (type);
+
   return value;
 }
 
@@ -9604,6 +9606,99 @@ record_types_used_by_current_var_decl (tree decl)
     }
 }
 
+/* If DECL is a typedef that is declared in the current function,
+   record it in CFUN->LOCAL_TYPEDEFS, for the purpose of
+   -Wunused-local-typedefs.  */
+
+void
+record_locally_defined_typedef (tree decl)
+{
+  if (!warn_unused_local_typedefs
+      /* if this is not a locally defined typedef then we are not
+	 interested.  */
+      || !is_typedef_decl (decl)
+      || !DECL_CONTEXT (decl)
+      || DECL_CONTEXT (decl) != current_function_decl)
+    return;
+
+  VEC_safe_push (tree, gc, cfun->local_typedefs, decl);
+}
+
+/* If T is a typedef variant type or a TYPE_DECL declared locally,
+   record it in CFUN->USED_LOCAL_TYPEDEFS.  Note that this function
+   does not record the typedefs presents in the subtypes of T.  */
+
+void
+maybe_record_local_typedef_use_real (tree t)
+{
+  tree typedef_decl = NULL_TREE;
+
+  /* We want T to be either a type or a TYPE_DECL.   */
+  if (t == NULL_TREE
+      || (!TYPE_P (t) && TREE_CODE (t) != TYPE_DECL))
+    return;
+
+  if (TYPE_P (t))
+    {
+      if (typedef_variant_p (t))
+	typedef_decl = TYPE_NAME (t);
+    }
+  else
+    {
+      if (is_typedef_decl (t))
+	typedef_decl = t;
+    }
+
+  if (typedef_decl != NULL_TREE)
+    {
+      /* We are only interested in a typedef declared locally.  */
+      if (DECL_CONTEXT (typedef_decl) != current_function_decl)
+	return;
+
+      /* If this typedef is local, really record its use now.  */
+      if (cfun->used_local_typedefs == NULL)
+	cfun->used_local_typedefs = pointer_set_create ();
+      pointer_set_insert (cfun->used_local_typedefs, typedef_decl);
+    }
+}
+
+/* Warn if there are some unused locally defined typedefs in the
+   current function. */
+
+void
+maybe_warn_unused_local_typedefs (void)
+{
+  int i;
+  tree decl;
+  static int unused_local_typedefs_warn_count;
+
+  if (cfun->used_local_typedefs != NULL)
+    gcc_assert (cfun->local_typedefs != NULL);
+
+  if (warn_unused_local_typedefs
+      && errorcount == unused_local_typedefs_warn_count)
+    {
+      FOR_EACH_VEC_ELT (tree, cfun->local_typedefs, i, decl)
+	if (cfun->used_local_typedefs == NULL
+	    || !pointer_set_contains (cfun->used_local_typedefs, decl))
+	  warning_at (DECL_SOURCE_LOCATION (decl),
+		      OPT_Wunused_local_typedefs,
+		      "typedef %qD locally defined but not used", decl);
+      unused_local_typedefs_warn_count = errorcount;
+    }
+
+  if (cfun->used_local_typedefs)
+    {
+      pointer_set_destroy (cfun->used_local_typedefs);
+      cfun->used_local_typedefs = NULL;
+    }
+  if (cfun->local_typedefs)
+    {
+      VEC_free (tree, gc, cfun->local_typedefs);
+      cfun->local_typedefs = NULL;
+    }
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 4ac7c4a..12a1550 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -705,6 +705,7 @@ extern tree (*make_fname_decl) (location_t, tree, int);
 
 /* In c-decl.c and cp/tree.c.  FIXME.  */
 extern void c_register_addr_space (const char *str, addr_space_t as);
+extern void maybe_record_local_typedef_use (tree);
 
 /* In c-common.c.  */
 extern bool in_late_binary_op;
@@ -986,6 +987,9 @@ extern void warn_for_sign_compare (location_t,
 extern void do_warn_double_promotion (tree, tree, tree, const char *, 
 				      location_t);
 extern void set_underlying_type (tree);
+extern void record_locally_defined_typedef (tree);
+extern void maybe_record_local_typedef_use_real (tree);
+extern void maybe_warn_unused_local_typedefs (void);
 extern VEC(tree,gc) *make_tree_vector (void);
 extern void release_tree_vector (VEC(tree,gc) *);
 extern VEC(tree,gc) *make_tree_vector_single (tree);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 617ea2d..e6ac5dc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -653,6 +653,10 @@ Wunsuffixed-float-constants
 C ObjC Var(warn_unsuffixed_float_constants) Warning
 Warn about unsuffixed float constants
 
+Wunused-local-typedefs
+C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning
+Warn about
+
 Wunused-macros
 C ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index aeb6625..4cd4301 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -2633,6 +2633,9 @@ c_expr_sizeof_type (location_t loc, struct c_type_name *t)
   ret.value = c_sizeof (loc, type);
   ret.original_code = ERROR_MARK;
   ret.original_type = NULL;
+
+  maybe_record_local_typedef_use (type);
+
   if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
       && c_vla_type_p (type))
     {
@@ -4737,6 +4740,8 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
   type = groktypename (type_name, &type_expr, &type_expr_const);
   warn_strict_prototypes = saved_wsp;
 
+  maybe_record_local_typedef_use (type);
+
   ret = build_c_cast (loc, type, expr);
   if (type_expr)
     {
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fb17178..38be149 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5001,6 +5001,7 @@ extern void note_vague_linkage_fn		(tree);
 extern tree build_artificial_parm		(tree, tree);
 extern bool possibly_inlined_p			(tree);
 extern int parm_index                           (tree);
+void maybe_record_local_typedef_use             (tree);
 
 /* in error.c */
 extern void init_error				(void);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2000bd4..199e51b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10318,6 +10318,8 @@ grokdeclarator (const cp_declarator *declarator,
     if (!processing_template_decl)
       cp_apply_type_quals_to_decl (type_quals, decl);
 
+    maybe_record_local_typedef_use (TREE_TYPE (decl));
+
     return decl;
   }
 }
@@ -13378,6 +13380,10 @@ finish_function (int flags)
       unused_but_set_errorcount = errorcount;
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Genericize before inlining.  */
   if (!processing_template_decl)
     {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f05b0f8..10882dd 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4175,6 +4175,9 @@ mark_used (tree decl)
 
   /* Set TREE_USED for the benefit of -Wunused.  */
   TREE_USED (decl) = 1;
+
+  maybe_record_local_typedef_use (TREE_TYPE (decl));
+
   if (DECL_CLONED_FUNCTION_P (decl))
     TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
 
@@ -4335,4 +4338,47 @@ mark_used (tree decl)
     }
 }
 
+/* Subroutine of cp_maybe_record_local_typedef_use, called from
+   cp_walk_tree_without_duplicate.   */
+
+static tree
+cp_maybe_record_local_typedef_use_r (tree *tp,
+				     int *walk_subtrees ATTRIBUTE_UNUSED,
+				     void *data ATTRIBUTE_UNUSED)
+{
+  maybe_record_local_typedef_use_real (*tp);
+  return NULL_TREE;
+}
+
+/* A subroutine of maybe_record_local_typedef_use.  */
+
+static void
+cp_maybe_record_local_typedef_use (tree t)
+{
+  if (!warn_unused_local_typedefs)
+    return;
+
+  /*  If the current function is being instantiated, bail out.  */
+  if (current_instantiation () != NULL
+      && (current_instantiation ()->decl == current_function_decl))
+    return;
+
+  maybe_record_local_typedef_use_real (t);
+
+  /* Record the typedefs used by subtypes of TYPE.  */
+  cp_walk_tree_without_duplicates (&t,
+				   cp_maybe_record_local_typedef_use_r,
+				   NULL_TREE);
+}
+
+/* If T is a typedef variant type or a TYPE_DECL declared locally,
+   record it in CFUN->USED_LOCAL_TYPEDEFS.  This function also records
+   the typedefs that are direct or indirect subtypes of T.  */
+
+void
+maybe_record_local_typedef_use (tree t)
+{
+  cp_maybe_record_local_typedef_use (t);
+}
+
 #include "gt-cp-decl2.h"
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 52b9484..4880903 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2612,6 +2612,8 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
   if (type == error_mark_node)
     return error_mark_node;
 
+  maybe_record_local_typedef_use (type);
+
   if (nelts == NULL_TREE && VEC_length (tree, *init) == 1)
     {
       tree auto_node = type_uses_auto (type);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1afd9ed..512480c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	      && TYPE_NAME (type)
 	      && TYPE_IDENTIFIER (type))
 	    set_identifier_type_value (DECL_NAME (x), x);
+
+	  /* If this is a locally defined typedef in a function that
+	     is not a template instantation, record it to implement
+	     -Wunused-local-typedefs.  */
+	  if (current_instantiation () == NULL
+	      || (current_instantiation ()->decl != current_function_decl))
+	  record_locally_defined_typedef (x);
 	}
 
       /* Multiple external decls of the same identifier ought to match.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b7410d5..7097f0d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4707,6 +4707,7 @@ cp_parser_qualifying_entity (cp_parser *parser,
       scope = cp_parser_namespace_name (parser);
     }
 
+  maybe_record_local_typedef_use (scope);
   return scope;
 }
 
@@ -11705,6 +11706,12 @@ cp_parser_template_id (cp_parser *parser,
       template_id = lookup_template_function (templ, arguments);
     }
 
+  /* Mark the possible use of a typedefs in the arguments, for the
+     purpose of -Wunused-local-typedefs.  */
+  if (arguments != NULL_TREE)
+    for (i = 0; i < TREE_VEC_LENGTH (arguments); ++i)
+      maybe_record_local_typedef_use (TREE_VEC_ELT (arguments, i));
+
   /* If parsing tentatively, replace the sequence of tokens that makes
      up the template-id with a CPP_TEMPLATE_ID token.  That way,
      should we re-parse the token stream, we will not have to repeat
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 434b772..b1483e9 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -523,6 +523,8 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
   /* Save casted types in the function's used types hash table.  */
   used_types_insert (type);
 
+  maybe_record_local_typedef_use (type);
+
   /* T shall be a pointer or reference to a complete class type, or
      `pointer to cv void''.  */
   switch (tc)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ab08eae..5990f09 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1534,6 +1534,7 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
     {
       value = build_min (op, size_type_node, type);
       TREE_READONLY (value) = 1;
+      maybe_record_local_typedef_use (type);
       return value;
     }
 
@@ -5714,6 +5715,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
   /* Save casted types in the function's used types hash table.  */
   used_types_insert (type);
 
+  maybe_record_local_typedef_use (type);
+
   /* [expr.static.cast]
 
      An lvalue of type "cv1 B", where B is a class type, can be cast
@@ -6017,6 +6020,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
   /* Save casted types in the function's used types hash table.  */
   used_types_insert (type);
 
+  maybe_record_local_typedef_use (type);
+
   /* [expr.reinterpret.cast]
      An lvalue expression of type T1 can be cast to the type
      "reference to T2" if an expression of type "pointer to T1" can be
@@ -6237,6 +6242,8 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
   /* Save casted types in the function's used types hash table.  */
   used_types_insert (dst_type);
 
+  maybe_record_local_typedef_use (dst_type);
+
   src_type = TREE_TYPE (expr);
   /* Expressions do not really have reference types.  */
   if (TREE_CODE (src_type) == REFERENCE_TYPE)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 727a88b..5ac24e4 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1607,6 +1607,8 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
       type = error_mark_node;
     }
 
+  maybe_record_local_typedef_use (type);
+
   if (processing_template_decl)
     {
       tree t;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index db9a5da..1289dd4 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -267,8 +267,9 @@ Objective-C and Objective-C++ Dialects}.
 -Wsystem-headers  -Wtrampolines  -Wtrigraphs  -Wtype-limits  -Wundef @gol
 -Wuninitialized  -Wunknown-pragmas  -Wno-pragmas @gol
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
--Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value @gol
--Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol
+-Wunused-label  -Wunused-local-typedefs -Wunused-parameter @gol
+-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
+-Wunused-but-set-parameter -Wunused-but-set-variable @gol
 -Wvariadic-macros -Wvla -Wvolatile-register-var  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
@@ -3499,6 +3500,10 @@ This warning is enabled by @option{-Wall}.
 To suppress this warning use the @samp{unused} attribute
 (@pxref{Variable Attributes}).
 
+@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
+@opindex Wunused-local-typedefs
+Warn when a typedef locally defined in a function is not used.
+
 @item -Wunused-parameter
 @opindex Wunused-parameter
 @opindex Wno-unused-parameter
diff --git a/gcc/function.h b/gcc/function.h
index ff193bc..ee13506 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "vecprim.h"
 #include "tm.h"		/* For CUMULATIVE_ARGS.  */
 #include "hard-reg-set.h"
+#include "pointer-set.h"
 
 /* Stack of pending (incomplete) sequences saved by `start_sequence'.
    Each element describes one pending sequence.
@@ -532,6 +533,13 @@ struct GTY(()) function {
   /* Vector of function local variables, functions, types and constants.  */
   VEC(tree,gc) *local_decls;
 
+  /* Vector of locally defined typedefs, for
+     -Wunused-local-typedefs.  */
+  VEC(tree,gc) *local_typedefs;
+
+  /*  Set of typedefs that are used in this function.  */
+  struct pointer_set_t * GTY((skip)) used_local_typedefs;
+
   /* For md files.  */
 
   /* tm.h can use this to store whatever it likes.  */
diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
new file mode 100644
index 0000000..32fb723
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
@@ -0,0 +1,38 @@
+/*  Origin PR c++/33255
+    { dg-options "-Wunused-local-typedefs" }
+    { dg-do compile }
+*/
+
+void
+test_warn ()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+void
+test0 ()
+{
+    typedef int foo;
+    foo var __attribute__((unused));
+}
+
+void
+test1 ()
+{
+    typedef int foo;
+    const foo *var = 0;
+}
+
+void
+test2 ()
+{
+  typedef int foo;
+  void func(foo);  
+}
+
+void
+test7 (void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 30ff80f..a1dda11 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10323,6 +10323,11 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
 {
   tree result = NULL_TREE;
 
+  /* If this type is a typedef variant, walk the fields of its
+     underlying type.  */
+  if (typedef_variant_p (type))
+    WALK_SUBTREE (DECL_ORIGINAL_TYPE (TYPE_NAME (type)));
+
   switch (TREE_CODE (type))
     {
     case POINTER_TYPE:
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index dd0634b..41b0b1f 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -238,8 +238,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
       __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
 		    const _Tp& __val, _Compare __comp)
       {
-	typedef typename __mv_iter_traits<_ForwardIterator>::value_type
-	  _ValueType;
 	typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
 	  _DistanceType;
 
diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc
index f161016..6bcf2db 100644
--- a/libstdc++-v3/src/istream.cc
+++ b/libstdc++-v3/src/istream.cc
@@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef basic_istream<char>       	__istream_type;
       typedef __istream_type::int_type		__int_type;
-      typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
       typedef __istream_type::__ctype_type	__ctype_type;
@@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<char>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
@@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<wchar_t>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc
index 4d21ab1..5de146b 100644
--- a/libstdc++-v3/src/valarray.cc
+++ b/libstdc++-v3/src/valarray.cc
@@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline size_t
   __valarray_product(const valarray<size_t>& __a)
   {
-    typedef const size_t* __restrict__ _Tp;
     const size_t __n = __a.size();
     // XXX: This ugly cast is necessary because
     //      valarray::operator[]() const return a VALUE!
-- 
1.7.6

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-27 21:35 [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning Dodji Seketeli
@ 2011-07-29  9:35 ` Jason Merrill
  2011-07-29 10:25   ` Paolo Carlini
                     ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: Jason Merrill @ 2011-07-29  9:35 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 07/27/2011 01:54 PM, Dodji Seketeli wrote:
> +  /*  Set of typedefs that are used in this function.  */
> +  struct pointer_set_t * GTY((skip)) used_local_typedefs;

Is there a reason not to just use TREE_USED for this?

> +  /* Vector of locally defined typedefs, for
> +     -Wunused-local-typedefs.  */
> +  VEC(tree,gc) *local_typedefs;

If the accessors are in c-common, this field should be in 
c_language_function.

> +      /* We are only interested in a typedef declared locally.  */
> +      if (DECL_CONTEXT (typedef_decl) != current_function_decl)
> +	return;

What if it's used in a nested function/local class/lambda?

> @@ -4175,6 +4175,9 @@ mark_used (tree decl)
>
>    /* Set TREE_USED for the benefit of -Wunused.  */
>    TREE_USED (decl) = 1;
> +
> +  maybe_record_local_typedef_use (TREE_TYPE (decl));

Why is this needed?  If the decl has the typedef for a type, we should 
have already marked it as used in grokdeclarator.

Actually, couldn't we just mark a typedef as used when when lookup finds 
it?  That would avoid having to mark in so many places and avoid the 
need for walk_tree.

I think -Wunused and -Wall should imply -Wunused-local-typedefs unless 
the user specifies -Wno-unused-local-typedefs.

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29  9:35 ` Jason Merrill
@ 2011-07-29 10:25   ` Paolo Carlini
  2011-07-29 11:34   ` Dodji Seketeli
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 28+ messages in thread
From: Paolo Carlini @ 2011-07-29 10:25 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Dodji Seketeli, GCC Patches

Hi,
> I think -Wunused and -Wall should imply -Wunused-local-typedefs unless 
> the user specifies -Wno-unused-local-typedefs.
IMHO, this is a very good idea looking forward, but then I think we 
should make sure the warning plays well with system headers either as-is 
or together with some other pending work of Dodji. In particular, as I 
probably mentioned already in the trail, we really want to double check 
that debug-mode does not trigger warnings, I'm a bit of worried because 
many people use and like it.

Paolo.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29  9:35 ` Jason Merrill
  2011-07-29 10:25   ` Paolo Carlini
@ 2011-07-29 11:34   ` Dodji Seketeli
  2011-07-29 12:37     ` Paolo Carlini
  2011-07-29 17:12     ` Jason Merrill
  2011-07-29 15:58   ` [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning Dodji Seketeli
  2011-08-06 12:49   ` Dodji Seketeli
  3 siblings, 2 replies; 28+ messages in thread
From: Dodji Seketeli @ 2011-07-29 11:34 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 07/27/2011 01:54 PM, Dodji Seketeli wrote:
>> +  /*  Set of typedefs that are used in this function.  */
>> +  struct pointer_set_t * GTY((skip)) used_local_typedefs;
>
> Is there a reason not to just use TREE_USED for this?

I wasn't sure if that flag wasn't (or couldn't be) used for some "core"
functionality with another meaning for this type of tree, and so would
cause some conflict.

>
>> +  /* Vector of locally defined typedefs, for
>> +     -Wunused-local-typedefs.  */
>> +  VEC(tree,gc) *local_typedefs;
>
> If the accessors are in c-common, this field should be in
> c_language_function.
>

Thanks, I didn't realize this existed.

> Actually, couldn't we just mark a typedef as used when when lookup
> finds it?  That would avoid having to mark in so many places and avoid
> the need for walk_tree.

This would indeed simplify things.  I'll try it.

> I think -Wunused and -Wall should imply -Wunused-local-typedefs unless
> the user specifies -Wno-unused-local-typedefs.

I actually first tried this (actually adding it to -Wall -extra and
-Wunused) and found out the following issue.

A typedef can be defined in a macro in a system header, be expanded in a
function and not be used by the function.  In this case we shouldn't
warn, but PR preprocessor/7263 makes us warn nonetheless.  There are
many spots of that kind in the libstdc++ test suite.

Paolo Carlini <paolo.carlini@oracle.com> writes:

> Hi,
>> I think -Wunused and -Wall should imply -Wunused-local-typedefs
>> unless the user specifies -Wno-unused-local-typedefs.
> IMHO, this is a very good idea looking forward, but then I think we
> should make sure the warning plays well with system headers either
> as-is or together with some other pending work of Dodji. In
> particular, as I probably mentioned already in the trail, we really
> want to double check that debug-mode does not trigger warnings, I'm a
> bit of worried because many people use and like it.

Exactly.  This would be a side effect of PR preprocessor/7263?

So do you guys think we should add it nonetheless and just add
-Wno-unused-local-typedefs to the tests that exhibit the above issue
before fixing PR preprocessor/7263?

Thanks.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 11:34   ` Dodji Seketeli
@ 2011-07-29 12:37     ` Paolo Carlini
  2011-07-29 17:12     ` Jason Merrill
  1 sibling, 0 replies; 28+ messages in thread
From: Paolo Carlini @ 2011-07-29 12:37 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, GCC Patches

Hi,
>> I think -Wunused and -Wall should imply -Wunused-local-typedefs unless
>> the user specifies -Wno-unused-local-typedefs.
> I actually first tried this (actually adding it to -Wall -extra and
> -Wunused) and found out the following issue.
>
> A typedef can be defined in a macro in a system header, be expanded in a
> function and not be used by the function.  In this case we shouldn't
> warn, but PR preprocessor/7263 makes us warn nonetheless.  There are
> many spots of that kind in the libstdc++ test suite.
>
> Paolo Carlini<paolo.carlini@oracle.com>  writes:
>
>> Hi,
>>> I think -Wunused and -Wall should imply -Wunused-local-typedefs
>>> unless the user specifies -Wno-unused-local-typedefs.
>> IMHO, this is a very good idea looking forward, but then I think we
>> should make sure the warning plays well with system headers either
>> as-is or together with some other pending work of Dodji. In
>> particular, as I probably mentioned already in the trail, we really
>> want to double check that debug-mode does not trigger warnings, I'm a
>> bit of worried because many people use and like it.
> Exactly.  This would be a side effect of PR preprocessor/7263?
>
> So do you guys think we should add it nonetheless and just add
> -Wno-unused-local-typedefs to the tests that exhibit the above issue
> before fixing PR preprocessor/7263?
Personally, I don't have a strong opinion, but I think it's very 
important to have a solid plan for 4.7.0: we don't want to regress in 
terms of warnings spilled from system headers, we slowly made good 
progress over the years and now the situation is pretty good and much 
less confusing than it used to be to the users. For sure, anyway, I'm 
available to clean up a bit some of the warnings emitted by the library, 
if that can help the process.

Paolo.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29  9:35 ` Jason Merrill
  2011-07-29 10:25   ` Paolo Carlini
  2011-07-29 11:34   ` Dodji Seketeli
@ 2011-07-29 15:58   ` Dodji Seketeli
  2011-07-29 17:10     ` Jason Merrill
  2011-08-06 12:49   ` Dodji Seketeli
  3 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-07-29 15:58 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 07/27/2011 01:54 PM, Dodji Seketeli wrote:
>> +  /*  Set of typedefs that are used in this function.  */
>> +  struct pointer_set_t * GTY((skip)) used_local_typedefs;
>
> Is there a reason not to just use TREE_USED for this?
>
>> +  /* Vector of locally defined typedefs, for
>> +     -Wunused-local-typedefs.  */
>> +  VEC(tree,gc) *local_typedefs;
>
> If the accessors are in c-common, this field should be in
> c_language_function.

Looking into this a bit, it seems to me that I can access
cfun->language->base (of type c_language_function) from inside either
the C or C++ FE only, as the type of cfun->language -- which is of type
struct language_function -- is only defined either in c-lang.h or
cp-tree.h.  I cannot access it from c-common.c.

This is consistent with the comment of the language field of the
function struct:

  /* Language-specific code can use this to store whatever it likes.  */
  struct language_function * language;

What am I missing?

-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 15:58   ` [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning Dodji Seketeli
@ 2011-07-29 17:10     ` Jason Merrill
  2011-07-29 17:56       ` Dodji Seketeli
  0 siblings, 1 reply; 28+ messages in thread
From: Jason Merrill @ 2011-07-29 17:10 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 07/29/2011 08:36 AM, Dodji Seketeli wrote:
> Looking into this a bit, it seems to me that I can access
> cfun->language->base (of type c_language_function) from inside either
> the C or C++ FE only, as the type of cfun->language -- which is of type
> struct language_function -- is only defined either in c-lang.h or
> cp-tree.h.  I cannot access it from c-common.c.

I think you can use (struct c_language_function *)cfun->language.

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 11:34   ` Dodji Seketeli
  2011-07-29 12:37     ` Paolo Carlini
@ 2011-07-29 17:12     ` Jason Merrill
  2011-07-29 17:40       ` Dodji Seketeli
  2011-09-08 21:13       ` Dodji Seketeli
  1 sibling, 2 replies; 28+ messages in thread
From: Jason Merrill @ 2011-07-29 17:12 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 07/29/2011 03:35 AM, Dodji Seketeli wrote:
> So do you guys think we should add it nonetheless and just add
> -Wno-unused-local-typedefs to the tests that exhibit the above issue
> before fixing PR preprocessor/7263?

Does your set of linemap patches fix the issue?  In that case, we can 
add it when those go in.  Speaking of which, sorry I haven't found the 
time to review them yet.

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 17:12     ` Jason Merrill
@ 2011-07-29 17:40       ` Dodji Seketeli
  2011-09-08 21:13       ` Dodji Seketeli
  1 sibling, 0 replies; 28+ messages in thread
From: Dodji Seketeli @ 2011-07-29 17:40 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 07/29/2011 03:35 AM, Dodji Seketeli wrote:
>> So do you guys think we should add it nonetheless and just add
>> -Wno-unused-local-typedefs to the tests that exhibit the above issue
>> before fixing PR preprocessor/7263?
>
> Does your set of linemap patches fix the issue?

Yes it does.  Particularly this patch
http://gcc.gnu.org/ml/gcc-patches/2011-07/msg01318.html 

>  In that case, we can add it when those go in.

OK.

>  Speaking of which, sorry I haven't found the time to review them yet.

No problem.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 17:10     ` Jason Merrill
@ 2011-07-29 17:56       ` Dodji Seketeli
  2011-07-29 22:41         ` Jason Merrill
  0 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-07-29 17:56 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 07/29/2011 08:36 AM, Dodji Seketeli wrote:
>> Looking into this a bit, it seems to me that I can access
>> cfun->language->base (of type c_language_function) from inside either
>> the C or C++ FE only, as the type of cfun->language -- which is of type
>> struct language_function -- is only defined either in c-lang.h or
>> cp-tree.h.  I cannot access it from c-common.c.
>
> I think you can use (struct c_language_function *)cfun->language.

I see.

Looking a bit further, it looks like the C FE uses cfun->language only
to store the context of the outer function when faced with a nested
function.  This is done by c_push_function_context, called by
c_parser_declaration_or_fndef.  Otherwise, cfun->language is not
allocated.  Is it appropriate that -Wunused-local-typedefs allocates it
as well?

-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 17:56       ` Dodji Seketeli
@ 2011-07-29 22:41         ` Jason Merrill
  2011-07-30 16:44           ` Joseph S. Myers
  0 siblings, 1 reply; 28+ messages in thread
From: Jason Merrill @ 2011-07-29 22:41 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches, Joseph S. Myers

On 07/29/2011 10:27 AM, Dodji Seketeli wrote:
> Jason Merrill<jason@redhat.com>  writes:
>
>> On 07/29/2011 08:36 AM, Dodji Seketeli wrote:
>>> Looking into this a bit, it seems to me that I can access
>>> cfun->language->base (of type c_language_function) from inside either
>>> the C or C++ FE only, as the type of cfun->language -- which is of type
>>> struct language_function -- is only defined either in c-lang.h or
>>> cp-tree.h.  I cannot access it from c-common.c.
>>
>> I think you can use (struct c_language_function *)cfun->language.
>
> I see.
>
> Looking a bit further, it looks like the C FE uses cfun->language only
> to store the context of the outer function when faced with a nested
> function.  This is done by c_push_function_context, called by
> c_parser_declaration_or_fndef.  Otherwise, cfun->language is not
> allocated.  Is it appropriate that -Wunused-local-typedefs allocates it
> as well?

I think so.  Joseph?

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 22:41         ` Jason Merrill
@ 2011-07-30 16:44           ` Joseph S. Myers
  0 siblings, 0 replies; 28+ messages in thread
From: Joseph S. Myers @ 2011-07-30 16:44 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Dodji Seketeli, Paolo Carlini, GCC Patches

On Fri, 29 Jul 2011, Jason Merrill wrote:

> > Looking a bit further, it looks like the C FE uses cfun->language only
> > to store the context of the outer function when faced with a nested
> > function.  This is done by c_push_function_context, called by
> > c_parser_declaration_or_fndef.  Otherwise, cfun->language is not
> > allocated.  Is it appropriate that -Wunused-local-typedefs allocates it
> > as well?
> 
> I think so.  Joseph?

Seems reasonable.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29  9:35 ` Jason Merrill
                     ` (2 preceding siblings ...)
  2011-07-29 15:58   ` [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning Dodji Seketeli
@ 2011-08-06 12:49   ` Dodji Seketeli
  2011-08-07  7:46     ` Jason Merrill
  3 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-08-06 12:49 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

So I finally got back to this and updated the patch according to the
comments below.

Jason Merrill <jason@redhat.com> writes:

> On 07/27/2011 01:54 PM, Dodji Seketeli wrote:
>> +  /*  Set of typedefs that are used in this function.  */
>> +  struct pointer_set_t * GTY((skip)) used_local_typedefs;
>
> Is there a reason not to just use TREE_USED for this?

Done now.

>> +  /* Vector of locally defined typedefs, for
>> +     -Wunused-local-typedefs.  */
>> +  VEC(tree,gc) *local_typedefs;
>
> If the accessors are in c-common, this field should be in
> c_language_function.

Done, see my comment below.

>
>> +      /* We are only interested in a typedef declared locally.  */
>> +      if (DECL_CONTEXT (typedef_decl) != current_function_decl)
>> +	return;
>
> What if it's used in a nested function/local class/lambda?


Oops.  Good catch.  I have added a local_decl_p predicated and used that
instead.  I have also added a test case for this.

>> @@ -4175,6 +4175,9 @@ mark_used (tree decl)
>>
>>    /* Set TREE_USED for the benefit of -Wunused.  */
>>    TREE_USED (decl) = 1;
>> +
>> +  maybe_record_local_typedef_use (TREE_TYPE (decl));
>
> Why is this needed?  If the decl has the typedef for a type, we should
> have already marked it as used in grokdeclarator.
>
> Actually, couldn't we just mark a typedef as used when when lookup
> finds it?  That would avoid having to mark in so many places and avoid
> the need for walk_tree.

I have done this and it's indeed much better.  Thanks.

> I think -Wunused and -Wall should imply -Wunused-local-typedefs unless
> the user specifies -Wno-unused-local-typedefs.

[...]

> Does your set of linemap patches fix the issue?  In that case, we can
> add it when those go in.

OK.

"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Fri, 29 Jul 2011, Jason Merrill wrote:
>
>> > Looking a bit further, it looks like the C FE uses cfun->language only
>> > to store the context of the outer function when faced with a nested
>> > function.  This is done by c_push_function_context, called by
>> > c_parser_declaration_or_fndef.  Otherwise, cfun->language is not
>> > allocated.  Is it appropriate that -Wunused-local-typedefs allocates it
>> > as well?
>> 
>> I think so.  Joseph?
>
> Seems reasonable.

So I have done this in the C FE.  -Wunused-local-typedefs allocates
cfun->language when the cfun for the current function is created, and
let it be garbage-collected at the end of the current function.

Tested on x86_64-unknown-linux-gnu against trunk.

gcc/

	* c-decl.c (lookup_name): Use the new
	maybe_record_local_typedef_use.
	(pushdecl): Use the new
	record_locally_defined_typedef.
	(store_parm_decls): Allocate cfun->language.
	(finish_function): Use the new maybe_warn_unused_local_typedefs,
	and mark cfun>language to be collected.
	(c_push_function_context): Allocate cfun->language here only if
	needed.
	(c_pop_function_context): Likewise, mark cfun->language
	for collection only when it should be done.
	* c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
	maybe_record_local_typedef_use.

gcc/c-family

	* c-common.h (struct c_language_function::local_typedefs): New
	field.
	(local_decl_p, record_locally_defined_typedef)
	(maybe_record_local_typedef_use)
	(maybe_warn_unused_local_typedefs): Declare new functions.
	* c-common.c (local_decl_p, record_locally_defined_typedef)
	(maybe_record_local_typedef_use)
	(maybe_warn_unused_local_typedefs): Define new functions.
	* c.opt: Declare new -Wunused-local-typedefs flag.

gcc/cp

	* name-lookup.c (pushdecl_maybe_friend_1): Use the new
	record_locally_defined_typedef.
	* cp-tree.h (cp_maybe_record_local_typedef_use): Declare new function.
	* decl.c (finish_function): Use the new maybe_warn_unused_local_typedefs.
	* decl2.c (cp_maybe_record_local_typedef_use): New public
	function.
	(grokfield): Use the new record_locally_defined_typedef.
	* parser.c (lookup_name): Use the new cp_maybe_record_local_typedef_use.
	maybe_record_local_typedef_use.

gcc/doc/

	* invoke.texi: Update documentation for -Wunused-local-typedefs.

gcc/testsuite/

	* g++.dg/warn/Wunused-local-typedefs.C: New test file.
	* c-c++-common/Wunused-local-typedefs.c: Likewise.

libstdc++-v3/

	* include/ext/bitmap_allocator.h
	(__detail::__mini_vector::__lower_bound): Remove unused typedef.
	* src/istream.cc (std::operator>>(basic_istream<char>& __in,
	basic_string<char>& __str)): Likewise.
	(std::getline): Likewise.
	* src/valarray.cc (__valarray_product): Likewise.
---
 gcc/c-decl.c                                       |   38 +++++-
 gcc/c-family/c-common.c                            |  114 +++++++++++++++
 gcc/c-family/c-common.h                            |    8 +
 gcc/c-family/c.opt                                 |    4 +
 gcc/cp/cp-tree.h                                   |    1 +
 gcc/cp/decl.c                                      |    4 +
 gcc/cp/decl2.c                                     |   15 ++
 gcc/cp/name-lookup.c                               |    7 +
 gcc/cp/parser.c                                    |    3 +
 gcc/doc/invoke.texi                                |    9 +-
 .../c-c++-common/Wunused-local-typedefs.c          |   38 +++++
 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C |  146 ++++++++++++++++++++
 libstdc++-v3/include/ext/bitmap_allocator.h        |    2 -
 libstdc++-v3/src/istream.cc                        |    3 -
 libstdc++-v3/src/valarray.cc                       |    1 -
 15 files changed, 379 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C

diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 33d2615..45ca27e 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2769,7 +2769,15 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    set_underlying_type (x);
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+	 for the purpose of implementing the -Wunused-local-typedefs
+	 warning.  */
+      record_locally_defined_typedef (x);
+    }
 
   bind (name, x, scope, /*invisible=*/false, nested, locus);
 
@@ -3435,7 +3443,10 @@ lookup_name (tree name)
 {
   struct c_binding *b = I_SYMBOL_BINDING (name);
   if (b && !b->invisible)
-    return b->decl;
+    {
+      maybe_record_local_typedef_use (b->decl);
+      return b->decl;
+    }
   return 0;
 }
 
@@ -8158,6 +8169,9 @@ store_parm_decls (void)
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl, false);
 
+  if (warn_unused_local_typedefs)
+    cfun->language = ggc_alloc_cleared_language_function ();
+
   /* Begin the statement tree for this function.  */
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
@@ -8265,6 +8279,10 @@ finish_function (void)
 		      "parameter %qD set but not used", decl);
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -8310,6 +8328,8 @@ finish_function (void)
   if (!decl_function_context (fndecl))
     undef_nested_function = false;
 
+  cfun->language = NULL;
+
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
      tree_rest_of_compilation.  */
@@ -8421,9 +8441,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 void
 c_push_function_context (void)
 {
-  struct language_function *p;
-  p = ggc_alloc_language_function ();
-  cfun->language = p;
+  struct language_function *p = cfun->language;
+  /* cfun->language might have been already allocated by the use of
+     -Wunused-local-typedefs.  In that case, just re-use it.  */
+  if (p == NULL)
+    cfun->language = p = ggc_alloc_cleared_language_function ();
 
   p->base.x_stmt_tree = c_stmt_tree;
   c_stmt_tree.x_cur_stmt_list
@@ -8449,7 +8471,11 @@ c_pop_function_context (void)
 
   pop_function_context ();
   p = cfun->language;
-  cfun->language = NULL;
+  /* When -Wunused-local-typedefs is in effect, cfun->languages is
+     used to store data throughout the life time of the current cfun,
+     So don't deallocate it.  */
+  if (!warn_unused_local_typedefs)
+    cfun->language = NULL;
 
   if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
       && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 96275ba..d6fdea3 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -4340,6 +4340,8 @@ c_sizeof_or_alignof_type (location_t loc,
   value = fold_convert_loc (loc, size_type_node, value);
   gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
 
+  maybe_record_local_typedef_use (type);
+
   return value;
 }
 
@@ -9604,6 +9606,118 @@ record_types_used_by_current_var_decl (tree decl)
     }
 }
 
+/* Return TRUE if DECL is declared in the current function.  */
+
+bool
+local_decl_p (tree decl)
+{
+  if (current_function_decl == NULL_TREE
+      || decl == NULL_TREE
+      || !DECL_P (decl))
+    return false;
+
+  while (DECL_CONTEXT (decl))
+    {
+      if (DECL_CONTEXT (decl) == current_function_decl)
+	return true;
+      decl = DECL_CONTEXT (decl);
+      if (decl != NULL_TREE && TYPE_P (decl))
+	decl = TYPE_NAME (decl);
+    }
+  return false;
+}
+
+/* If DECL is a typedef that is declared in the current function,
+   record it for the purpose of -Wunused-local-typedefs.  */
+
+void
+record_locally_defined_typedef (tree decl)
+{
+  struct c_language_function *l;
+
+  if (!warn_unused_local_typedefs
+      || cfun == NULL
+      /* if this is not a locally defined typedef then we are not
+	 interested.  */
+      || !is_typedef_decl (decl)
+      || !local_decl_p (decl))
+    return;
+
+  l = (struct c_language_function *) cfun->language;
+  VEC_safe_push (tree, gc, l->local_typedefs, decl);
+}
+
+/* If T is a typedef variant type or a TYPE_DECL declared locally,
+   mark it as used.  */
+
+void
+maybe_record_local_typedef_use (tree t)
+{
+  tree typedef_decl = NULL_TREE;
+
+  if (!warn_unused_local_typedefs)
+    return;
+
+  /* We want T to be either a type or a TYPE_DECL.   */
+  if (t == NULL_TREE
+      || (!TYPE_P (t) && TREE_CODE (t) != TYPE_DECL))
+    return;
+
+  if (TYPE_P (t))
+    {
+      if (typedef_variant_p (t))
+	typedef_decl = TYPE_NAME (t);
+    }
+  else
+    {
+      if (is_typedef_decl (t))
+	typedef_decl = t;
+    }
+
+  if (typedef_decl != NULL_TREE)
+    {
+      /* We are only interested in a typedef declared locally.  */
+      if (!local_decl_p (typedef_decl))
+	return;
+      TREE_USED (typedef_decl) = true;
+    }
+}
+
+/* Warn if there are some unused locally defined typedefs in the
+   current function. */
+
+void
+maybe_warn_unused_local_typedefs (void)
+{
+  int i;
+  tree decl;
+  static int unused_local_typedefs_warn_count;
+  struct c_language_function *l;
+
+  if (cfun == NULL)
+    return;
+
+  if ((l = (struct c_language_function *) cfun->language) == NULL)
+    return;
+
+  if (warn_unused_local_typedefs
+      && errorcount == unused_local_typedefs_warn_count)
+    {
+      FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
+	if (!TREE_USED (decl))
+	  warning_at (DECL_SOURCE_LOCATION (decl),
+		      OPT_Wunused_local_typedefs,
+		      "typedef %qD locally defined but not used", decl);
+      unused_local_typedefs_warn_count = errorcount;
+    }
+
+  if (l->local_typedefs)
+    {
+      VEC_free (tree, gc, l->local_typedefs);
+      l->local_typedefs = NULL;
+    }
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 3a49779..01d0ff0 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -505,6 +505,10 @@ struct GTY(()) c_language_function {
   /* While we are parsing the function, this contains information
      about the statement-tree that we are building.  */
   struct stmt_tree_s x_stmt_tree;
+
+  /* Vector of locally defined typedefs, for
+     -Wunused-local-typedefs.  */
+  VEC(tree,gc) *local_typedefs;
 };
 
 #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
@@ -986,6 +990,10 @@ extern void warn_for_sign_compare (location_t,
 extern void do_warn_double_promotion (tree, tree, tree, const char *, 
 				      location_t);
 extern void set_underlying_type (tree);
+extern void record_locally_defined_typedef (tree);
+extern void maybe_record_local_typedef_use (tree);
+extern void maybe_warn_unused_local_typedefs (void);
+extern bool local_decl_p (tree);
 extern VEC(tree,gc) *make_tree_vector (void);
 extern void release_tree_vector (VEC(tree,gc) *);
 extern VEC(tree,gc) *make_tree_vector_single (tree);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 617ea2d..e6ac5dc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -653,6 +653,10 @@ Wunsuffixed-float-constants
 C ObjC Var(warn_unsuffixed_float_constants) Warning
 Warn about unsuffixed float constants
 
+Wunused-local-typedefs
+C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning
+Warn about
+
 Wunused-macros
 C ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ff5509e..184eaef 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5001,6 +5001,7 @@ extern void note_vague_linkage_fn		(tree);
 extern tree build_artificial_parm		(tree, tree);
 extern bool possibly_inlined_p			(tree);
 extern int parm_index                           (tree);
+void cp_maybe_record_local_typedef_use          (tree);
 
 /* in error.c */
 extern void init_error				(void);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f0d1a1a..cc06682 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13385,6 +13385,10 @@ finish_function (int flags)
       unused_but_set_errorcount = errorcount;
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Genericize before inlining.  */
   if (!processing_template_decl)
     {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f05b0f8..fad621e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -868,6 +868,7 @@ grokfield (const cp_declarator *declarator,
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
 	set_underlying_type (value);
 
+      record_locally_defined_typedef (value);
       return value;
     }
 
@@ -4335,4 +4336,18 @@ mark_used (tree decl)
     }
 }
 
+/* If T is a typedef variant type or a TYPE_DECL declared locally,
+   flag it as such.  */
+
+void
+cp_maybe_record_local_typedef_use (tree t)
+{
+  /*  If the current function is being instantiated, bail out.  */
+  if (current_instantiation () != NULL
+      && (current_instantiation ()->decl == current_function_decl))
+    return;
+
+  maybe_record_local_typedef_use (t);
+}
+
 #include "gt-cp-decl2.h"
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1afd9ed..512480c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	      && TYPE_NAME (type)
 	      && TYPE_IDENTIFIER (type))
 	    set_identifier_type_value (DECL_NAME (x), x);
+
+	  /* If this is a locally defined typedef in a function that
+	     is not a template instantation, record it to implement
+	     -Wunused-local-typedefs.  */
+	  if (current_instantiation () == NULL
+	      || (current_instantiation ()->decl != current_function_decl))
+	  record_locally_defined_typedef (x);
 	}
 
       /* Multiple external decls of the same identifier ought to match.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9b3e56d..47bbd4d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19572,6 +19572,9 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (DECL_P (decl))
     check_accessibility_of_qualified_id (decl, object_type, parser->scope);
 
+  cp_maybe_record_local_typedef_use (decl);
+  cp_maybe_record_local_typedef_use (parser->scope);
+
   return decl;
 }
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6fd78d5..5430803 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -267,8 +267,9 @@ Objective-C and Objective-C++ Dialects}.
 -Wsystem-headers  -Wtrampolines  -Wtrigraphs  -Wtype-limits  -Wundef @gol
 -Wuninitialized  -Wunknown-pragmas  -Wno-pragmas @gol
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
--Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value @gol
--Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol
+-Wunused-label  -Wunused-local-typedefs -Wunused-parameter @gol
+-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
+-Wunused-but-set-parameter -Wunused-but-set-variable @gol
 -Wvariadic-macros -Wvla -Wvolatile-register-var  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
@@ -3499,6 +3500,10 @@ This warning is enabled by @option{-Wall}.
 To suppress this warning use the @samp{unused} attribute
 (@pxref{Variable Attributes}).
 
+@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
+@opindex Wunused-local-typedefs
+Warn when a typedef locally defined in a function is not used.
+
 @item -Wunused-parameter
 @opindex Wunused-parameter
 @opindex Wno-unused-parameter
diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
new file mode 100644
index 0000000..32fb723
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
@@ -0,0 +1,38 @@
+/*  Origin PR c++/33255
+    { dg-options "-Wunused-local-typedefs" }
+    { dg-do compile }
+*/
+
+void
+test_warn ()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+void
+test0 ()
+{
+    typedef int foo;
+    foo var __attribute__((unused));
+}
+
+void
+test1 ()
+{
+    typedef int foo;
+    const foo *var = 0;
+}
+
+void
+test2 ()
+{
+  typedef int foo;
+  void func(foo);  
+}
+
+void
+test7 (void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
new file mode 100644
index 0000000..87feb52
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
@@ -0,0 +1,146 @@
+// Origin PR c++/33255
+// { dg-options "-Wunused-local-typedefs" }
+// { dg-do compile }
+
+void
+test_warn()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+struct S
+{
+    typedef int T;
+    S() {}
+    S(int) {}
+};
+
+template<class T>
+struct ST
+{
+    typedef T type;
+    ST (int) {}
+    ST () {}
+};
+
+template<class T>
+void
+test0_tmpl(void)
+{
+    typedef struct ST<T> foo;
+    foo(2);
+}
+
+int
+test0(void)
+{
+    test0_tmpl<int>();
+}
+
+void
+test1(void)
+{
+    typedef int foo;
+    ST<foo> a;
+}
+
+
+int
+test2(void)
+{
+    typedef S foo;
+    foo::T i = 0;
+    return i;
+}
+
+template<class T>
+void
+test3_tmpl(void)
+{
+    typedef struct ST<int> foo;
+    ST<int> v;
+    const foo &var = v;
+}
+
+void
+test3(void)
+{
+    test3_tmpl<int>();
+}
+
+void
+test4(void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
+
+void
+test5(void)
+{
+  typedef int T0;
+  typedef char T1;
+  typedef int* T2;
+  typedef unsigned T3;
+  struct C0 { virtual void f(void) {}};
+  struct C1 : C0 {};
+  typedef C0 T4;
+
+  int v0 = (T0) 2;
+  char v1 = static_cast<T1> (0);
+  reinterpret_cast<T2> (&v0);
+  unsigned* const c = 0;
+  unsigned* v2 = const_cast<T3* const> (c);
+  C0 *p0 = 0;
+  C1 *p1 = 0;
+  p0 = dynamic_cast<T4*> (p1);  
+}
+
+void
+test6(void)
+{
+  struct C0 {};
+  typedef C0 foo;
+  C0 *v = new foo;
+}
+
+template<class T, class U>
+struct S7
+{
+  void
+  f()
+  {
+    typedef int foo;
+    sizeof(foo);
+  }
+};
+
+template<class T>
+void
+test7(void)
+{
+  typedef typename ST<T>::T bar; // { dg-warning "locally defined but not used" }
+  typedef typename ST<T>::T foo; // We shouldn't warn for this one, as
+				 // it's used below.
+  S7<int, foo> v;
+}
+
+
+template<class T, class U>
+void
+test8(void)
+{
+  int f(S7<T, U>);
+  void g(int);
+  typedef T foo;
+  g(f(S7<foo, U>()));
+}
+
+int
+test9(void)
+{
+  struct s { typedef int foo;}; // { dg-warning "locally defined but not used" }
+  struct t { typedef int bar;};
+  t::bar b = 0;
+  return b;
+}
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index dd0634b..41b0b1f 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -238,8 +238,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
       __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
 		    const _Tp& __val, _Compare __comp)
       {
-	typedef typename __mv_iter_traits<_ForwardIterator>::value_type
-	  _ValueType;
 	typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
 	  _DistanceType;
 
diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc
index f161016..6bcf2db 100644
--- a/libstdc++-v3/src/istream.cc
+++ b/libstdc++-v3/src/istream.cc
@@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef basic_istream<char>       	__istream_type;
       typedef __istream_type::int_type		__int_type;
-      typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
       typedef __istream_type::__ctype_type	__ctype_type;
@@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<char>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
@@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<wchar_t>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc
index 4d21ab1..5de146b 100644
--- a/libstdc++-v3/src/valarray.cc
+++ b/libstdc++-v3/src/valarray.cc
@@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline size_t
   __valarray_product(const valarray<size_t>& __a)
   {
-    typedef const size_t* __restrict__ _Tp;
     const size_t __n = __a.size();
     // XXX: This ugly cast is necessary because
     //      valarray::operator[]() const return a VALUE!
-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-08-06 12:49   ` Dodji Seketeli
@ 2011-08-07  7:46     ` Jason Merrill
  2011-08-08 21:49       ` Dodji Seketeli
  0 siblings, 1 reply; 28+ messages in thread
From: Jason Merrill @ 2011-08-07  7:46 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 08/06/2011 06:57 AM, Dodji Seketeli wrote:
> @@ -4340,6 +4340,8 @@ c_sizeof_or_alignof_type (location_t loc,
>    value = fold_convert_loc (loc, size_type_node, value);
>    gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
>
> +  maybe_record_local_typedef_use (type);

Why is this still needed?

> +/* Return TRUE if DECL is declared in the current function.  */
> +
> +bool
> +local_decl_p (tree decl)

I don't think we need to work so hard to compare contexts to 
current_function_decl; just checking that the decl is in some function 
should be enough, i.e. decl_function_context is non-null.

> +  static int unused_local_typedefs_warn_count;

This could use a comment.

> +/* If T is a typedef variant type or a TYPE_DECL declared locally,
> +   mark it as used.  */
> +
> +void
> +maybe_record_local_typedef_use (tree t)

Does this still need to handle types?  And the meaning of TREE_USED 
shouldn't change depending on a warning flag or whether a decl is local 
or not; let's just mark all TYPE_DECLs as used.

Seems like we don't need local_decl_p at all; at the definition point, 
if we're in a function, a new declaration must be local enough for our 
purposes.

> +void
> +cp_maybe_record_local_typedef_use (tree t)
> +{
> +  /*  If the current function is being instantiated, bail out.  */

As above, I think we shouldn't put so many conditions on setting TREE_USED.

> @@ -19572,6 +19572,9 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
>    if (DECL_P (decl))
>      check_accessibility_of_qualified_id (decl, object_type, parser->scope);
>
> +  cp_maybe_record_local_typedef_use (decl);
> +  cp_maybe_record_local_typedef_use (parser->scope);

Why do we need to handle parser->scope?  Wasn't it previously looked up?

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-08-07  7:46     ` Jason Merrill
@ 2011-08-08 21:49       ` Dodji Seketeli
  2011-09-01 16:52         ` [PING] " Dodji Seketeli
  2011-09-06 19:24         ` Jason Merrill
  0 siblings, 2 replies; 28+ messages in thread
From: Dodji Seketeli @ 2011-08-08 21:49 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Hello,

Jason Merrill <jason@redhat.com> writes:

> On 08/06/2011 06:57 AM, Dodji Seketeli wrote:
> > @@ -4340,6 +4340,8 @@ c_sizeof_or_alignof_type (location_t loc,
> >    value = fold_convert_loc (loc, size_type_node, value);
> >    gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
> >
> > +  maybe_record_local_typedef_use (type);
> 
> Why is this still needed?

It is not.  I just forgot to remove it.  Done now.

> 
> > +/* Return TRUE if DECL is declared in the current function.  */
> > +
> > +bool
> > +local_decl_p (tree decl)
> 
> I don't think we need to work so hard to compare contexts to
> current_function_decl; just checking that the decl is in some function
> should be enough, i.e. decl_function_context is non-null.

Thanks.  I didn't know about decl_function_context.  I grepped for
functions containing "local" in their names but I was doomed to
failure.  I am using that now.

> 
> > +  static int unused_local_typedefs_warn_count;
> 
> This could use a comment.

Added.

> 
> > +/* If T is a typedef variant type or a TYPE_DECL declared locally,
> > +   mark it as used.  */
> > +
> > +void
> > +maybe_record_local_typedef_use (tree t)
> 
> Does this still need to handle types?  And the meaning of TREE_USED
> shouldn't change depending on a warning flag or whether a decl is
> local or not; let's just mark all TYPE_DECLs as used.

OK, done.

> 
> Seems like we don't need local_decl_p at all; at the definition point,
> if we're in a function, a new declaration must be local enough for our
> purposes.
> 
> > +void
> > +cp_maybe_record_local_typedef_use (tree t)
> > +{
> > +  /*  If the current function is being instantiated, bail out.  */
> 
> As above, I think we shouldn't put so many conditions on setting
> TREE_USED.

I have removed cp_maybe_record_local_typedef_use altogether and just
use maybe_record_typedef_use now.

> 
> > @@ -19572,6 +19572,9 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
> >    if (DECL_P (decl))
> >      check_accessibility_of_qualified_id (decl, object_type, parser->scope);
> >
> > +  cp_maybe_record_local_typedef_use (decl);
> > +  cp_maybe_record_local_typedef_use (parser->scope);
> 
> Why do we need to handle parser->scope?  Wasn't it previously looked up?

Sigh, my bad..  Fixed.

Below is the updated patch that passed bootstrap and regression tests
on x86_64-unknown-linux-gnu against trunk.

Thanks.

From: Dodji Seketeli <dodji@redhat.com>
Date: Mon, 25 Jul 2011 19:02:07 +0200
Subject: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning

gcc/

	* c-decl.c (lookup_name): Use the new
	maybe_record_typedef_use.
	(pushdecl): Use the new
	record_locally_defined_typedef.
	(store_parm_decls): Allocate cfun->language.
	(finish_function): Use the new maybe_warn_unused_local_typedefs,
	and mark cfun->language to be collected.
	(c_push_function_context): Allocate cfun->language here only if
	needed.
	(c_pop_function_context): Likewise, mark cfun->language
	for collection only when it should be done.
	* c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
	maybe_record_local_typedef_use.

gcc/c-family

	* c-common.h (struct c_language_function::local_typedefs): New
	field.
	(record_locally_defined_typedef, maybe_record_typedef_use)
	(maybe_warn_unused_local_typedefs): Declare new functions.
	* c-common.c (record_locally_defined_typedef)
	(maybe_record_typedef_use)
	(maybe_warn_unused_local_typedefs): Define new functions.
	* c.opt: Declare new -Wunused-local-typedefs flag.

gcc/cp

	* name-lookup.c (pushdecl_maybe_friend_1): Use the new
	record_locally_defined_typedef.
	* decl.c (finish_function): Use the new
	maybe_warn_unused_local_typedefs.
	(grokfield): Use the new record_locally_defined_typedef.
	* parser.c (lookup_name): Use the new maybe_record_typedef_use.

gcc/doc/

	* invoke.texi: Update documentation for -Wunused-local-typedefs.

gcc/testsuite/

	* g++.dg/warn/Wunused-local-typedefs.C: New test file.
	* c-c++-common/Wunused-local-typedefs.c: Likewise.

libstdc++-v3/

	* include/ext/bitmap_allocator.h
	(__detail::__mini_vector::__lower_bound): Remove unused typedef.
	* src/istream.cc (std::operator>>(basic_istream<char>& __in,
	basic_string<char>& __str)): Likewise.
	(std::getline): Likewise.
	* src/valarray.cc (__valarray_product): Likewise.
---
 gcc/c-decl.c                                       |   38 +++++-
 gcc/c-family/c-common.c                            |   71 ++++++++++
 gcc/c-family/c-common.h                            |    7 +
 gcc/c-family/c.opt                                 |    4 +
 gcc/cp/decl.c                                      |    4 +
 gcc/cp/decl2.c                                     |    1 +
 gcc/cp/name-lookup.c                               |    7 +
 gcc/cp/parser.c                                    |    2 +
 gcc/doc/invoke.texi                                |    9 +-
 .../c-c++-common/Wunused-local-typedefs.c          |   38 +++++
 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C |  146 ++++++++++++++++++++
 libstdc++-v3/include/ext/bitmap_allocator.h        |    2 -
 libstdc++-v3/src/istream.cc                        |    3 -
 libstdc++-v3/src/valarray.cc                       |    1 -
 14 files changed, 319 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C

diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 33d2615..230f1a7 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2769,7 +2769,15 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    set_underlying_type (x);
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+	 for the purpose of implementing the -Wunused-local-typedefs
+	 warning.  */
+      record_locally_defined_typedef (x);
+    }
 
   bind (name, x, scope, /*invisible=*/false, nested, locus);
 
@@ -3435,7 +3443,10 @@ lookup_name (tree name)
 {
   struct c_binding *b = I_SYMBOL_BINDING (name);
   if (b && !b->invisible)
-    return b->decl;
+    {
+      maybe_record_typedef_use (b->decl);
+      return b->decl;
+    }
   return 0;
 }
 
@@ -8158,6 +8169,9 @@ store_parm_decls (void)
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl, false);
 
+  if (warn_unused_local_typedefs)
+    cfun->language = ggc_alloc_cleared_language_function ();
+
   /* Begin the statement tree for this function.  */
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
@@ -8265,6 +8279,10 @@ finish_function (void)
 		      "parameter %qD set but not used", decl);
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -8310,6 +8328,8 @@ finish_function (void)
   if (!decl_function_context (fndecl))
     undef_nested_function = false;
 
+  cfun->language = NULL;
+
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
      tree_rest_of_compilation.  */
@@ -8421,9 +8441,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 void
 c_push_function_context (void)
 {
-  struct language_function *p;
-  p = ggc_alloc_language_function ();
-  cfun->language = p;
+  struct language_function *p = cfun->language;
+  /* cfun->language might have been already allocated by the use of
+     -Wunused-local-typedefs.  In that case, just re-use it.  */
+  if (p == NULL)
+    cfun->language = p = ggc_alloc_cleared_language_function ();
 
   p->base.x_stmt_tree = c_stmt_tree;
   c_stmt_tree.x_cur_stmt_list
@@ -8449,7 +8471,11 @@ c_pop_function_context (void)
 
   pop_function_context ();
   p = cfun->language;
-  cfun->language = NULL;
+  /* When -Wunused-local-typedefs is in effect, cfun->languages is
+     used to store data throughout the life time of the current cfun,
+     So don't deallocate it.  */
+  if (!warn_unused_local_typedefs)
+    cfun->language = NULL;
 
   if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
       && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 96275ba..290240a 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -9604,6 +9604,77 @@ record_types_used_by_current_var_decl (tree decl)
     }
 }
 
+/* If DECL is a typedef that is declared in the current function,
+   record it for the purpose of -Wunused-local-typedefs.  */
+
+void
+record_locally_defined_typedef (tree decl)
+{
+  struct c_language_function *l;
+
+  if (!warn_unused_local_typedefs
+      || cfun == NULL
+      /* if this is not a locally defined typedef then we are not
+	 interested.  */
+      || !is_typedef_decl (decl)
+      || !decl_function_context (decl))
+    return;
+
+  l = (struct c_language_function *) cfun->language;
+  VEC_safe_push (tree, gc, l->local_typedefs, decl);
+}
+
+/* If T is a TYPE_DECL declared locally, mark it as used.  */
+
+void
+maybe_record_typedef_use (tree t)
+{
+  /* We want T to be either a type or a TYPE_DECL.   */
+  if (!is_typedef_decl (t))
+    return;
+
+  TREE_USED (t) = true;
+}
+
+/* Warn if there are some unused locally defined typedefs in the
+   current function. */
+
+void
+maybe_warn_unused_local_typedefs (void)
+{
+  int i;
+  tree decl;
+  /* The number of times we have emitted -Wunused-local-typedefs
+     warnings.  If this is different from errorcount, that means some
+     unrelated errors have been issued.  In which case, we'll avoid
+     emitting "unused-local-typedefs" warnings.  */
+  static int unused_local_typedefs_warn_count;
+  struct c_language_function *l;
+
+  if (cfun == NULL)
+    return;
+
+  if ((l = (struct c_language_function *) cfun->language) == NULL)
+    return;
+
+  if (warn_unused_local_typedefs
+      && errorcount == unused_local_typedefs_warn_count)
+    {
+      FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
+	if (!TREE_USED (decl))
+	  warning_at (DECL_SOURCE_LOCATION (decl),
+		      OPT_Wunused_local_typedefs,
+		      "typedef %qD locally defined but not used", decl);
+      unused_local_typedefs_warn_count = errorcount;
+    }
+
+  if (l->local_typedefs)
+    {
+      VEC_free (tree, gc, l->local_typedefs);
+      l->local_typedefs = NULL;
+    }
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 3a49779..6b324d4 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -505,6 +505,10 @@ struct GTY(()) c_language_function {
   /* While we are parsing the function, this contains information
      about the statement-tree that we are building.  */
   struct stmt_tree_s x_stmt_tree;
+
+  /* Vector of locally defined typedefs, for
+     -Wunused-local-typedefs.  */
+  VEC(tree,gc) *local_typedefs;
 };
 
 #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
@@ -986,6 +990,9 @@ extern void warn_for_sign_compare (location_t,
 extern void do_warn_double_promotion (tree, tree, tree, const char *, 
 				      location_t);
 extern void set_underlying_type (tree);
+extern void record_locally_defined_typedef (tree);
+extern void maybe_record_typedef_use (tree);
+extern void maybe_warn_unused_local_typedefs (void);
 extern VEC(tree,gc) *make_tree_vector (void);
 extern void release_tree_vector (VEC(tree,gc) *);
 extern VEC(tree,gc) *make_tree_vector_single (tree);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 617ea2d..e6ac5dc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -653,6 +653,10 @@ Wunsuffixed-float-constants
 C ObjC Var(warn_unsuffixed_float_constants) Warning
 Warn about unsuffixed float constants
 
+Wunused-local-typedefs
+C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning
+Warn about
+
 Wunused-macros
 C ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f0d1a1a..cc06682 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13385,6 +13385,10 @@ finish_function (int flags)
       unused_but_set_errorcount = errorcount;
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Genericize before inlining.  */
   if (!processing_template_decl)
     {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f05b0f8..68e9b9b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -868,6 +868,7 @@ grokfield (const cp_declarator *declarator,
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
 	set_underlying_type (value);
 
+      record_locally_defined_typedef (value);
       return value;
     }
 
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1afd9ed..512480c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	      && TYPE_NAME (type)
 	      && TYPE_IDENTIFIER (type))
 	    set_identifier_type_value (DECL_NAME (x), x);
+
+	  /* If this is a locally defined typedef in a function that
+	     is not a template instantation, record it to implement
+	     -Wunused-local-typedefs.  */
+	  if (current_instantiation () == NULL
+	      || (current_instantiation ()->decl != current_function_decl))
+	  record_locally_defined_typedef (x);
 	}
 
       /* Multiple external decls of the same identifier ought to match.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9b3e56d..ba27acc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19572,6 +19572,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (DECL_P (decl))
     check_accessibility_of_qualified_id (decl, object_type, parser->scope);
 
+  maybe_record_typedef_use (decl);
+
   return decl;
 }
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6fd78d5..5430803 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -267,8 +267,9 @@ Objective-C and Objective-C++ Dialects}.
 -Wsystem-headers  -Wtrampolines  -Wtrigraphs  -Wtype-limits  -Wundef @gol
 -Wuninitialized  -Wunknown-pragmas  -Wno-pragmas @gol
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
--Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value @gol
--Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol
+-Wunused-label  -Wunused-local-typedefs -Wunused-parameter @gol
+-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
+-Wunused-but-set-parameter -Wunused-but-set-variable @gol
 -Wvariadic-macros -Wvla -Wvolatile-register-var  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
@@ -3499,6 +3500,10 @@ This warning is enabled by @option{-Wall}.
 To suppress this warning use the @samp{unused} attribute
 (@pxref{Variable Attributes}).
 
+@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
+@opindex Wunused-local-typedefs
+Warn when a typedef locally defined in a function is not used.
+
 @item -Wunused-parameter
 @opindex Wunused-parameter
 @opindex Wno-unused-parameter
diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
new file mode 100644
index 0000000..32fb723
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
@@ -0,0 +1,38 @@
+/*  Origin PR c++/33255
+    { dg-options "-Wunused-local-typedefs" }
+    { dg-do compile }
+*/
+
+void
+test_warn ()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+void
+test0 ()
+{
+    typedef int foo;
+    foo var __attribute__((unused));
+}
+
+void
+test1 ()
+{
+    typedef int foo;
+    const foo *var = 0;
+}
+
+void
+test2 ()
+{
+  typedef int foo;
+  void func(foo);  
+}
+
+void
+test7 (void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
new file mode 100644
index 0000000..87feb52
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
@@ -0,0 +1,146 @@
+// Origin PR c++/33255
+// { dg-options "-Wunused-local-typedefs" }
+// { dg-do compile }
+
+void
+test_warn()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+struct S
+{
+    typedef int T;
+    S() {}
+    S(int) {}
+};
+
+template<class T>
+struct ST
+{
+    typedef T type;
+    ST (int) {}
+    ST () {}
+};
+
+template<class T>
+void
+test0_tmpl(void)
+{
+    typedef struct ST<T> foo;
+    foo(2);
+}
+
+int
+test0(void)
+{
+    test0_tmpl<int>();
+}
+
+void
+test1(void)
+{
+    typedef int foo;
+    ST<foo> a;
+}
+
+
+int
+test2(void)
+{
+    typedef S foo;
+    foo::T i = 0;
+    return i;
+}
+
+template<class T>
+void
+test3_tmpl(void)
+{
+    typedef struct ST<int> foo;
+    ST<int> v;
+    const foo &var = v;
+}
+
+void
+test3(void)
+{
+    test3_tmpl<int>();
+}
+
+void
+test4(void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
+
+void
+test5(void)
+{
+  typedef int T0;
+  typedef char T1;
+  typedef int* T2;
+  typedef unsigned T3;
+  struct C0 { virtual void f(void) {}};
+  struct C1 : C0 {};
+  typedef C0 T4;
+
+  int v0 = (T0) 2;
+  char v1 = static_cast<T1> (0);
+  reinterpret_cast<T2> (&v0);
+  unsigned* const c = 0;
+  unsigned* v2 = const_cast<T3* const> (c);
+  C0 *p0 = 0;
+  C1 *p1 = 0;
+  p0 = dynamic_cast<T4*> (p1);  
+}
+
+void
+test6(void)
+{
+  struct C0 {};
+  typedef C0 foo;
+  C0 *v = new foo;
+}
+
+template<class T, class U>
+struct S7
+{
+  void
+  f()
+  {
+    typedef int foo;
+    sizeof(foo);
+  }
+};
+
+template<class T>
+void
+test7(void)
+{
+  typedef typename ST<T>::T bar; // { dg-warning "locally defined but not used" }
+  typedef typename ST<T>::T foo; // We shouldn't warn for this one, as
+				 // it's used below.
+  S7<int, foo> v;
+}
+
+
+template<class T, class U>
+void
+test8(void)
+{
+  int f(S7<T, U>);
+  void g(int);
+  typedef T foo;
+  g(f(S7<foo, U>()));
+}
+
+int
+test9(void)
+{
+  struct s { typedef int foo;}; // { dg-warning "locally defined but not used" }
+  struct t { typedef int bar;};
+  t::bar b = 0;
+  return b;
+}
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index dd0634b..41b0b1f 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -238,8 +238,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
       __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
 		    const _Tp& __val, _Compare __comp)
       {
-	typedef typename __mv_iter_traits<_ForwardIterator>::value_type
-	  _ValueType;
 	typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
 	  _DistanceType;
 
diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc
index f161016..6bcf2db 100644
--- a/libstdc++-v3/src/istream.cc
+++ b/libstdc++-v3/src/istream.cc
@@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef basic_istream<char>       	__istream_type;
       typedef __istream_type::int_type		__int_type;
-      typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
       typedef __istream_type::__ctype_type	__ctype_type;
@@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<char>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
@@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<wchar_t>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc
index 4d21ab1..5de146b 100644
--- a/libstdc++-v3/src/valarray.cc
+++ b/libstdc++-v3/src/valarray.cc
@@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline size_t
   __valarray_product(const valarray<size_t>& __a)
   {
-    typedef const size_t* __restrict__ _Tp;
     const size_t __n = __a.size();
     // XXX: This ugly cast is necessary because
     //      valarray::operator[]() const return a VALUE!
-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PING] [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-08-08 21:49       ` Dodji Seketeli
@ 2011-09-01 16:52         ` Dodji Seketeli
  2011-09-06 19:24         ` Jason Merrill
  1 sibling, 0 replies; 28+ messages in thread
From: Dodji Seketeli @ 2011-09-01 16:52 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

I am friendly pinging this patch.


Dodji Seketeli <dodji@redhat.com> a écrit:

> Hello,
>
> Jason Merrill <jason@redhat.com> writes:
>
>> On 08/06/2011 06:57 AM, Dodji Seketeli wrote:
>> > @@ -4340,6 +4340,8 @@ c_sizeof_or_alignof_type (location_t loc,
>> >    value = fold_convert_loc (loc, size_type_node, value);
>> >    gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
>> >
>> > +  maybe_record_local_typedef_use (type);
>> 
>> Why is this still needed?
>
> It is not.  I just forgot to remove it.  Done now.
>
>> 
>> > +/* Return TRUE if DECL is declared in the current function.  */
>> > +
>> > +bool
>> > +local_decl_p (tree decl)
>> 
>> I don't think we need to work so hard to compare contexts to
>> current_function_decl; just checking that the decl is in some function
>> should be enough, i.e. decl_function_context is non-null.
>
> Thanks.  I didn't know about decl_function_context.  I grepped for
> functions containing "local" in their names but I was doomed to
> failure.  I am using that now.
>
>> 
>> > +  static int unused_local_typedefs_warn_count;
>> 
>> This could use a comment.
>
> Added.
>
>> 
>> > +/* If T is a typedef variant type or a TYPE_DECL declared locally,
>> > +   mark it as used.  */
>> > +
>> > +void
>> > +maybe_record_local_typedef_use (tree t)
>> 
>> Does this still need to handle types?  And the meaning of TREE_USED
>> shouldn't change depending on a warning flag or whether a decl is
>> local or not; let's just mark all TYPE_DECLs as used.
>
> OK, done.
>
>> 
>> Seems like we don't need local_decl_p at all; at the definition point,
>> if we're in a function, a new declaration must be local enough for our
>> purposes.
>> 
>> > +void
>> > +cp_maybe_record_local_typedef_use (tree t)
>> > +{
>> > +  /*  If the current function is being instantiated, bail out.  */
>> 
>> As above, I think we shouldn't put so many conditions on setting
>> TREE_USED.
>
> I have removed cp_maybe_record_local_typedef_use altogether and just
> use maybe_record_typedef_use now.
>
>> 
>> > @@ -19572,6 +19572,9 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
>> >    if (DECL_P (decl))
>> >      check_accessibility_of_qualified_id (decl, object_type, parser->scope);
>> >
>> > +  cp_maybe_record_local_typedef_use (decl);
>> > +  cp_maybe_record_local_typedef_use (parser->scope);
>> 
>> Why do we need to handle parser->scope?  Wasn't it previously looked up?
>
> Sigh, my bad..  Fixed.
>
> Below is the updated patch that passed bootstrap and regression tests
> on x86_64-unknown-linux-gnu against trunk.
>
> Thanks.
>
> From: Dodji Seketeli <dodji@redhat.com>
> Date: Mon, 25 Jul 2011 19:02:07 +0200
> Subject: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
>
> gcc/
>
> 	* c-decl.c (lookup_name): Use the new
> 	maybe_record_typedef_use.
> 	(pushdecl): Use the new
> 	record_locally_defined_typedef.
> 	(store_parm_decls): Allocate cfun->language.
> 	(finish_function): Use the new maybe_warn_unused_local_typedefs,
> 	and mark cfun->language to be collected.
> 	(c_push_function_context): Allocate cfun->language here only if
> 	needed.
> 	(c_pop_function_context): Likewise, mark cfun->language
> 	for collection only when it should be done.
> 	* c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
> 	maybe_record_local_typedef_use.
>
> gcc/c-family
>
> 	* c-common.h (struct c_language_function::local_typedefs): New
> 	field.
> 	(record_locally_defined_typedef, maybe_record_typedef_use)
> 	(maybe_warn_unused_local_typedefs): Declare new functions.
> 	* c-common.c (record_locally_defined_typedef)
> 	(maybe_record_typedef_use)
> 	(maybe_warn_unused_local_typedefs): Define new functions.
> 	* c.opt: Declare new -Wunused-local-typedefs flag.
>
> gcc/cp
>
> 	* name-lookup.c (pushdecl_maybe_friend_1): Use the new
> 	record_locally_defined_typedef.
> 	* decl.c (finish_function): Use the new
> 	maybe_warn_unused_local_typedefs.
> 	(grokfield): Use the new record_locally_defined_typedef.
> 	* parser.c (lookup_name): Use the new maybe_record_typedef_use.
>
> gcc/doc/
>
> 	* invoke.texi: Update documentation for -Wunused-local-typedefs.
>
> gcc/testsuite/
>
> 	* g++.dg/warn/Wunused-local-typedefs.C: New test file.
> 	* c-c++-common/Wunused-local-typedefs.c: Likewise.
>
> libstdc++-v3/
>
> 	* include/ext/bitmap_allocator.h
> 	(__detail::__mini_vector::__lower_bound): Remove unused typedef.
> 	* src/istream.cc (std::operator>>(basic_istream<char>& __in,
> 	basic_string<char>& __str)): Likewise.
> 	(std::getline): Likewise.
> 	* src/valarray.cc (__valarray_product): Likewise.
> ---
>  gcc/c-decl.c                                       |   38 +++++-
>  gcc/c-family/c-common.c                            |   71 ++++++++++
>  gcc/c-family/c-common.h                            |    7 +
>  gcc/c-family/c.opt                                 |    4 +
>  gcc/cp/decl.c                                      |    4 +
>  gcc/cp/decl2.c                                     |    1 +
>  gcc/cp/name-lookup.c                               |    7 +
>  gcc/cp/parser.c                                    |    2 +
>  gcc/doc/invoke.texi                                |    9 +-
>  .../c-c++-common/Wunused-local-typedefs.c          |   38 +++++
>  gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C |  146 ++++++++++++++++++++
>  libstdc++-v3/include/ext/bitmap_allocator.h        |    2 -
>  libstdc++-v3/src/istream.cc                        |    3 -
>  libstdc++-v3/src/valarray.cc                       |    1 -
>  14 files changed, 319 insertions(+), 14 deletions(-)
>  create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
>  create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
>
> diff --git a/gcc/c-decl.c b/gcc/c-decl.c
> index 33d2615..230f1a7 100644
> --- a/gcc/c-decl.c
> +++ b/gcc/c-decl.c
> @@ -2769,7 +2769,15 @@ pushdecl (tree x)
>  
>   skip_external_and_shadow_checks:
>    if (TREE_CODE (x) == TYPE_DECL)
> -    set_underlying_type (x);
> +    {
> +      /* So this is a typedef, set its underlying type.  */
> +      set_underlying_type (x);
> +
> +      /* If X is a typedef defined in the current function, record it
> +	 for the purpose of implementing the -Wunused-local-typedefs
> +	 warning.  */
> +      record_locally_defined_typedef (x);
> +    }
>  
>    bind (name, x, scope, /*invisible=*/false, nested, locus);
>  
> @@ -3435,7 +3443,10 @@ lookup_name (tree name)
>  {
>    struct c_binding *b = I_SYMBOL_BINDING (name);
>    if (b && !b->invisible)
> -    return b->decl;
> +    {
> +      maybe_record_typedef_use (b->decl);
> +      return b->decl;
> +    }
>    return 0;
>  }
>  
> @@ -8158,6 +8169,9 @@ store_parm_decls (void)
>    /* Initialize the RTL code for the function.  */
>    allocate_struct_function (fndecl, false);
>  
> +  if (warn_unused_local_typedefs)
> +    cfun->language = ggc_alloc_cleared_language_function ();
> +
>    /* Begin the statement tree for this function.  */
>    DECL_SAVED_TREE (fndecl) = push_stmt_list ();
>  
> @@ -8265,6 +8279,10 @@ finish_function (void)
>  		      "parameter %qD set but not used", decl);
>      }
>  
> +  /* Complain about locally defined typedefs that are not used in this
> +     function.  */
> +  maybe_warn_unused_local_typedefs ();
> +
>    /* Store the end of the function, so that we get good line number
>       info for the epilogue.  */
>    cfun->function_end_locus = input_location;
> @@ -8310,6 +8328,8 @@ finish_function (void)
>    if (!decl_function_context (fndecl))
>      undef_nested_function = false;
>  
> +  cfun->language = NULL;
> +
>    /* We're leaving the context of this function, so zap cfun.
>       It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
>       tree_rest_of_compilation.  */
> @@ -8421,9 +8441,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
>  void
>  c_push_function_context (void)
>  {
> -  struct language_function *p;
> -  p = ggc_alloc_language_function ();
> -  cfun->language = p;
> +  struct language_function *p = cfun->language;
> +  /* cfun->language might have been already allocated by the use of
> +     -Wunused-local-typedefs.  In that case, just re-use it.  */
> +  if (p == NULL)
> +    cfun->language = p = ggc_alloc_cleared_language_function ();
>  
>    p->base.x_stmt_tree = c_stmt_tree;
>    c_stmt_tree.x_cur_stmt_list
> @@ -8449,7 +8471,11 @@ c_pop_function_context (void)
>  
>    pop_function_context ();
>    p = cfun->language;
> -  cfun->language = NULL;
> +  /* When -Wunused-local-typedefs is in effect, cfun->languages is
> +     used to store data throughout the life time of the current cfun,
> +     So don't deallocate it.  */
> +  if (!warn_unused_local_typedefs)
> +    cfun->language = NULL;
>  
>    if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
>        && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 96275ba..290240a 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -9604,6 +9604,77 @@ record_types_used_by_current_var_decl (tree decl)
>      }
>  }
>  
> +/* If DECL is a typedef that is declared in the current function,
> +   record it for the purpose of -Wunused-local-typedefs.  */
> +
> +void
> +record_locally_defined_typedef (tree decl)
> +{
> +  struct c_language_function *l;
> +
> +  if (!warn_unused_local_typedefs
> +      || cfun == NULL
> +      /* if this is not a locally defined typedef then we are not
> +	 interested.  */
> +      || !is_typedef_decl (decl)
> +      || !decl_function_context (decl))
> +    return;
> +
> +  l = (struct c_language_function *) cfun->language;
> +  VEC_safe_push (tree, gc, l->local_typedefs, decl);
> +}
> +
> +/* If T is a TYPE_DECL declared locally, mark it as used.  */
> +
> +void
> +maybe_record_typedef_use (tree t)
> +{
> +  /* We want T to be either a type or a TYPE_DECL.   */
> +  if (!is_typedef_decl (t))
> +    return;
> +
> +  TREE_USED (t) = true;
> +}
> +
> +/* Warn if there are some unused locally defined typedefs in the
> +   current function. */
> +
> +void
> +maybe_warn_unused_local_typedefs (void)
> +{
> +  int i;
> +  tree decl;
> +  /* The number of times we have emitted -Wunused-local-typedefs
> +     warnings.  If this is different from errorcount, that means some
> +     unrelated errors have been issued.  In which case, we'll avoid
> +     emitting "unused-local-typedefs" warnings.  */
> +  static int unused_local_typedefs_warn_count;
> +  struct c_language_function *l;
> +
> +  if (cfun == NULL)
> +    return;
> +
> +  if ((l = (struct c_language_function *) cfun->language) == NULL)
> +    return;
> +
> +  if (warn_unused_local_typedefs
> +      && errorcount == unused_local_typedefs_warn_count)
> +    {
> +      FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
> +	if (!TREE_USED (decl))
> +	  warning_at (DECL_SOURCE_LOCATION (decl),
> +		      OPT_Wunused_local_typedefs,
> +		      "typedef %qD locally defined but not used", decl);
> +      unused_local_typedefs_warn_count = errorcount;
> +    }
> +
> +  if (l->local_typedefs)
> +    {
> +      VEC_free (tree, gc, l->local_typedefs);
> +      l->local_typedefs = NULL;
> +    }
> +}
> +
>  /* The C and C++ parsers both use vectors to hold function arguments.
>     For efficiency, we keep a cache of unused vectors.  This is the
>     cache.  */
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index 3a49779..6b324d4 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -505,6 +505,10 @@ struct GTY(()) c_language_function {
>    /* While we are parsing the function, this contains information
>       about the statement-tree that we are building.  */
>    struct stmt_tree_s x_stmt_tree;
> +
> +  /* Vector of locally defined typedefs, for
> +     -Wunused-local-typedefs.  */
> +  VEC(tree,gc) *local_typedefs;
>  };
>  
>  #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
> @@ -986,6 +990,9 @@ extern void warn_for_sign_compare (location_t,
>  extern void do_warn_double_promotion (tree, tree, tree, const char *, 
>  				      location_t);
>  extern void set_underlying_type (tree);
> +extern void record_locally_defined_typedef (tree);
> +extern void maybe_record_typedef_use (tree);
> +extern void maybe_warn_unused_local_typedefs (void);
>  extern VEC(tree,gc) *make_tree_vector (void);
>  extern void release_tree_vector (VEC(tree,gc) *);
>  extern VEC(tree,gc) *make_tree_vector_single (tree);
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 617ea2d..e6ac5dc 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -653,6 +653,10 @@ Wunsuffixed-float-constants
>  C ObjC Var(warn_unsuffixed_float_constants) Warning
>  Warn about unsuffixed float constants
>  
> +Wunused-local-typedefs
> +C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning
> +Warn about
> +
>  Wunused-macros
>  C ObjC C++ ObjC++ Warning
>  Warn about macros defined in the main file that are not used
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index f0d1a1a..cc06682 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -13385,6 +13385,10 @@ finish_function (int flags)
>        unused_but_set_errorcount = errorcount;
>      }
>  
> +  /* Complain about locally defined typedefs that are not used in this
> +     function.  */
> +  maybe_warn_unused_local_typedefs ();
> +
>    /* Genericize before inlining.  */
>    if (!processing_template_decl)
>      {
> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> index f05b0f8..68e9b9b 100644
> --- a/gcc/cp/decl2.c
> +++ b/gcc/cp/decl2.c
> @@ -868,6 +868,7 @@ grokfield (const cp_declarator *declarator,
>            && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
>  	set_underlying_type (value);
>  
> +      record_locally_defined_typedef (value);
>        return value;
>      }
>  
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index 1afd9ed..512480c 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
>  	      && TYPE_NAME (type)
>  	      && TYPE_IDENTIFIER (type))
>  	    set_identifier_type_value (DECL_NAME (x), x);
> +
> +	  /* If this is a locally defined typedef in a function that
> +	     is not a template instantation, record it to implement
> +	     -Wunused-local-typedefs.  */
> +	  if (current_instantiation () == NULL
> +	      || (current_instantiation ()->decl != current_function_decl))
> +	  record_locally_defined_typedef (x);
>  	}
>  
>        /* Multiple external decls of the same identifier ought to match.
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index 9b3e56d..ba27acc 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -19572,6 +19572,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
>    if (DECL_P (decl))
>      check_accessibility_of_qualified_id (decl, object_type, parser->scope);
>  
> +  maybe_record_typedef_use (decl);
> +
>    return decl;
>  }
>  
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 6fd78d5..5430803 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -267,8 +267,9 @@ Objective-C and Objective-C++ Dialects}.
>  -Wsystem-headers  -Wtrampolines  -Wtrigraphs  -Wtype-limits  -Wundef @gol
>  -Wuninitialized  -Wunknown-pragmas  -Wno-pragmas @gol
>  -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
> --Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value @gol
> --Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol
> +-Wunused-label  -Wunused-local-typedefs -Wunused-parameter @gol
> +-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
> +-Wunused-but-set-parameter -Wunused-but-set-variable @gol
>  -Wvariadic-macros -Wvla -Wvolatile-register-var  -Wwrite-strings}
>  
>  @item C and Objective-C-only Warning Options
> @@ -3499,6 +3500,10 @@ This warning is enabled by @option{-Wall}.
>  To suppress this warning use the @samp{unused} attribute
>  (@pxref{Variable Attributes}).
>  
> +@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
> +@opindex Wunused-local-typedefs
> +Warn when a typedef locally defined in a function is not used.
> +
>  @item -Wunused-parameter
>  @opindex Wunused-parameter
>  @opindex Wno-unused-parameter
> diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
> new file mode 100644
> index 0000000..32fb723
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
> @@ -0,0 +1,38 @@
> +/*  Origin PR c++/33255
> +    { dg-options "-Wunused-local-typedefs" }
> +    { dg-do compile }
> +*/
> +
> +void
> +test_warn ()
> +{
> +  typedef int foo; // { dg-warning "locally defined but not used" }
> +}
> +
> +void
> +test0 ()
> +{
> +    typedef int foo;
> +    foo var __attribute__((unused));
> +}
> +
> +void
> +test1 ()
> +{
> +    typedef int foo;
> +    const foo *var = 0;
> +}
> +
> +void
> +test2 ()
> +{
> +  typedef int foo;
> +  void func(foo);  
> +}
> +
> +void
> +test7 (void)
> +{
> +  typedef int foo;
> +  int vec[1] = {sizeof (foo)};
> +}
> diff --git a/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
> new file mode 100644
> index 0000000..87feb52
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
> @@ -0,0 +1,146 @@
> +// Origin PR c++/33255
> +// { dg-options "-Wunused-local-typedefs" }
> +// { dg-do compile }
> +
> +void
> +test_warn()
> +{
> +  typedef int foo; // { dg-warning "locally defined but not used" }
> +}
> +
> +struct S
> +{
> +    typedef int T;
> +    S() {}
> +    S(int) {}
> +};
> +
> +template<class T>
> +struct ST
> +{
> +    typedef T type;
> +    ST (int) {}
> +    ST () {}
> +};
> +
> +template<class T>
> +void
> +test0_tmpl(void)
> +{
> +    typedef struct ST<T> foo;
> +    foo(2);
> +}
> +
> +int
> +test0(void)
> +{
> +    test0_tmpl<int>();
> +}
> +
> +void
> +test1(void)
> +{
> +    typedef int foo;
> +    ST<foo> a;
> +}
> +
> +
> +int
> +test2(void)
> +{
> +    typedef S foo;
> +    foo::T i = 0;
> +    return i;
> +}
> +
> +template<class T>
> +void
> +test3_tmpl(void)
> +{
> +    typedef struct ST<int> foo;
> +    ST<int> v;
> +    const foo &var = v;
> +}
> +
> +void
> +test3(void)
> +{
> +    test3_tmpl<int>();
> +}
> +
> +void
> +test4(void)
> +{
> +  typedef int foo;
> +  int vec[1] = {sizeof (foo)};
> +}
> +
> +void
> +test5(void)
> +{
> +  typedef int T0;
> +  typedef char T1;
> +  typedef int* T2;
> +  typedef unsigned T3;
> +  struct C0 { virtual void f(void) {}};
> +  struct C1 : C0 {};
> +  typedef C0 T4;
> +
> +  int v0 = (T0) 2;
> +  char v1 = static_cast<T1> (0);
> +  reinterpret_cast<T2> (&v0);
> +  unsigned* const c = 0;
> +  unsigned* v2 = const_cast<T3* const> (c);
> +  C0 *p0 = 0;
> +  C1 *p1 = 0;
> +  p0 = dynamic_cast<T4*> (p1);  
> +}
> +
> +void
> +test6(void)
> +{
> +  struct C0 {};
> +  typedef C0 foo;
> +  C0 *v = new foo;
> +}
> +
> +template<class T, class U>
> +struct S7
> +{
> +  void
> +  f()
> +  {
> +    typedef int foo;
> +    sizeof(foo);
> +  }
> +};
> +
> +template<class T>
> +void
> +test7(void)
> +{
> +  typedef typename ST<T>::T bar; // { dg-warning "locally defined but not used" }
> +  typedef typename ST<T>::T foo; // We shouldn't warn for this one, as
> +				 // it's used below.
> +  S7<int, foo> v;
> +}
> +
> +
> +template<class T, class U>
> +void
> +test8(void)
> +{
> +  int f(S7<T, U>);
> +  void g(int);
> +  typedef T foo;
> +  g(f(S7<foo, U>()));
> +}
> +
> +int
> +test9(void)
> +{
> +  struct s { typedef int foo;}; // { dg-warning "locally defined but not used" }
> +  struct t { typedef int bar;};
> +  t::bar b = 0;
> +  return b;
> +}
> diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
> index dd0634b..41b0b1f 100644
> --- a/libstdc++-v3/include/ext/bitmap_allocator.h
> +++ b/libstdc++-v3/include/ext/bitmap_allocator.h
> @@ -238,8 +238,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
>        __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
>  		    const _Tp& __val, _Compare __comp)
>        {
> -	typedef typename __mv_iter_traits<_ForwardIterator>::value_type
> -	  _ValueType;
>  	typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
>  	  _DistanceType;
>  
> diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc
> index f161016..6bcf2db 100644
> --- a/libstdc++-v3/src/istream.cc
> +++ b/libstdc++-v3/src/istream.cc
> @@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      {
>        typedef basic_istream<char>       	__istream_type;
>        typedef __istream_type::int_type		__int_type;
> -      typedef __istream_type::char_type		__char_type;
>        typedef __istream_type::traits_type	__traits_type;
>        typedef __istream_type::__streambuf_type  __streambuf_type;
>        typedef __istream_type::__ctype_type	__ctype_type;
> @@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        typedef __istream_type::char_type		__char_type;
>        typedef __istream_type::traits_type	__traits_type;
>        typedef __istream_type::__streambuf_type  __streambuf_type;
> -      typedef __istream_type::__ctype_type	__ctype_type;
>        typedef basic_string<char>        	__string_type;
>        typedef __string_type::size_type		__size_type;
>  
> @@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        typedef __istream_type::char_type		__char_type;
>        typedef __istream_type::traits_type	__traits_type;
>        typedef __istream_type::__streambuf_type  __streambuf_type;
> -      typedef __istream_type::__ctype_type	__ctype_type;
>        typedef basic_string<wchar_t>        	__string_type;
>        typedef __string_type::size_type		__size_type;
>  
> diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc
> index 4d21ab1..5de146b 100644
> --- a/libstdc++-v3/src/valarray.cc
> +++ b/libstdc++-v3/src/valarray.cc
> @@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    inline size_t
>    __valarray_product(const valarray<size_t>& __a)
>    {
> -    typedef const size_t* __restrict__ _Tp;
>      const size_t __n = __a.size();
>      // XXX: This ugly cast is necessary because
>      //      valarray::operator[]() const return a VALUE!

-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-08-08 21:49       ` Dodji Seketeli
  2011-09-01 16:52         ` [PING] " Dodji Seketeli
@ 2011-09-06 19:24         ` Jason Merrill
  2011-09-07 18:04           ` Dodji Seketeli
  1 sibling, 1 reply; 28+ messages in thread
From: Jason Merrill @ 2011-09-06 19:24 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 08/08/2011 03:52 PM, Dodji Seketeli wrote:
> +  cfun->language = NULL;

Might as well ggc_free it first.

> +  /* We want T to be either a type or a TYPE_DECL.   */

Comment is out of date.

Does __attribute ((used)) on the typedef prevent the warning?

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-06 19:24         ` Jason Merrill
@ 2011-09-07 18:04           ` Dodji Seketeli
  2011-09-07 18:08             ` Jason Merrill
  0 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-09-07 18:04 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 08/08/2011 03:52 PM, Dodji Seketeli wrote:
>> +  cfun->language = NULL;
>
> Might as well ggc_free it first.

Done.

>
>> +  /* We want T to be either a type or a TYPE_DECL.   */
>
> Comment is out of date.

Removed.

>
> Does __attribute ((used)) on the typedef prevent the warning?

No it doesn't.  handle_used_attribute ignores the used attribute on
anything that isn't a variable or a function.  I have changed that in
the patch below.

Note that as handle_used_attribute function is called before the
typedef is properly setup (by calling set_underlying_type), I couldn't
use is_typedef_decl in it.  Is that a problem?

To ease the review, here is the changes I made against the previous
patch.

diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 230f1a7..42730d7 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1,3 +1,4 @@
+
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
    2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
@@ -8328,7 +8329,8 @@ finish_function (void)
   if (!decl_function_context (fndecl))
     undef_nested_function = false;
 
-  cfun->language = NULL;
+  if (cfun->language != NULL)
+    ggc_free (cfun->language);
 
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 290240a..bb57569 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6091,7 +6091,8 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
   tree node = *pnode;
 
   if (TREE_CODE (node) == FUNCTION_DECL
-      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))
+      || (TREE_CODE (node) == TYPE_DECL))
     {
       TREE_USED (node) = 1;
       DECL_PRESERVE_P (node) = 1;
@@ -9629,7 +9630,6 @@ record_locally_defined_typedef (tree decl)
 void
 maybe_record_typedef_use (tree t)
 {
-  /* We want T to be either a type or a TYPE_DECL.   */
   if (!is_typedef_decl (t))
     return;
 
diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
index 32fb723..683019d 100644
--- a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
+++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
@@ -36,3 +36,9 @@ test7 (void)
   typedef int foo;
   int vec[1] = {sizeof (foo)};
 }
+
+void
+test8 (void)
+{
+  typedef int foo __attribute__((used));
+}


The consolidated patch against trunk is below.  Bootstrapped and
tested against trunk on x86_64-unknown-linux-gnu.

gcc/

	* c-decl.c (lookup_name): Use the new
	maybe_record_typedef_use.
	(pushdecl): Use the new
	record_locally_defined_typedef.
	(store_parm_decls): Allocate cfun->language.
	(finish_function): Use the new maybe_warn_unused_local_typedefs,
	and free cfun->language.
	(c_push_function_context): Allocate cfun->language here only if
	needed.
	(c_pop_function_context): Likewise, mark cfun->language
	for collection only when it should be done.
	* c-common.c (handle_used_attribute): Don't ignore TYPE_DECL
	nodes.
	* c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
	maybe_record_local_typedef_use.

gcc/c-family

	* c-common.h (struct c_language_function::local_typedefs): New
	field.
	(record_locally_defined_typedef, maybe_record_typedef_use)
	(maybe_warn_unused_local_typedefs): Declare new functions.
	* c-common.c (record_locally_defined_typedef)
	(maybe_record_typedef_use)
	(maybe_warn_unused_local_typedefs): Define new functions.
	* c.opt: Declare new -Wunused-local-typedefs flag.

gcc/cp

	* name-lookup.c (pushdecl_maybe_friend_1): Use the new
	record_locally_defined_typedef.
	* decl.c (finish_function): Use the new
	maybe_warn_unused_local_typedefs.
	(grokfield): Use the new record_locally_defined_typedef.
	* parser.c (lookup_name): Use the new maybe_record_typedef_use.

gcc/doc/

	* invoke.texi: Update documentation for -Wunused-local-typedefs.

gcc/testsuite/

	* g++.dg/warn/Wunused-local-typedefs.C: New test file.
	* c-c++-common/Wunused-local-typedefs.c: Likewise.

libstdc++-v3/

	* include/ext/bitmap_allocator.h
	(__detail::__mini_vector::__lower_bound): Remove unused typedef.
	* src/istream.cc (std::operator>>(basic_istream<char>& __in,
	basic_string<char>& __str)): Likewise.
	(std::getline): Likewise.
	* src/valarray.cc (__valarray_product): Likewise.
---
 gcc/c-decl.c                                       |   39 +++++-
 gcc/c-family/c-common.c                            |   73 ++++++++++-
 gcc/c-family/c-common.h                            |    7 +
 gcc/c-family/c.opt                                 |    4 +
 gcc/cp/decl.c                                      |    4 +
 gcc/cp/decl2.c                                     |    1 +
 gcc/cp/name-lookup.c                               |    7 +
 gcc/cp/parser.c                                    |    2 +
 gcc/doc/invoke.texi                                |    9 +-
 .../c-c++-common/Wunused-local-typedefs.c          |   44 ++++++
 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C |  146 ++++++++++++++++++++
 libstdc++-v3/include/ext/bitmap_allocator.h        |    2 -
 libstdc++-v3/src/istream.cc                        |    3 -
 libstdc++-v3/src/valarray.cc                       |    1 -
 14 files changed, 327 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C

diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 33d2615..a82ec24 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2769,7 +2769,15 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    set_underlying_type (x);
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+	 for the purpose of implementing the -Wunused-local-typedefs
+	 warning.  */
+      record_locally_defined_typedef (x);
+    }
 
   bind (name, x, scope, /*invisible=*/false, nested, locus);
 
@@ -3435,7 +3443,10 @@ lookup_name (tree name)
 {
   struct c_binding *b = I_SYMBOL_BINDING (name);
   if (b && !b->invisible)
-    return b->decl;
+    {
+      maybe_record_typedef_use (b->decl);
+      return b->decl;
+    }
   return 0;
 }
 
@@ -8158,6 +8169,9 @@ store_parm_decls (void)
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl, false);
 
+  if (warn_unused_local_typedefs)
+    cfun->language = ggc_alloc_cleared_language_function ();
+
   /* Begin the statement tree for this function.  */
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
@@ -8265,6 +8279,10 @@ finish_function (void)
 		      "parameter %qD set but not used", decl);
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -8310,6 +8328,9 @@ finish_function (void)
   if (!decl_function_context (fndecl))
     undef_nested_function = false;
 
+  if (cfun->language != NULL)
+    ggc_free (cfun->language);
+
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
      tree_rest_of_compilation.  */
@@ -8421,9 +8442,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 void
 c_push_function_context (void)
 {
-  struct language_function *p;
-  p = ggc_alloc_language_function ();
-  cfun->language = p;
+  struct language_function *p = cfun->language;
+  /* cfun->language might have been already allocated by the use of
+     -Wunused-local-typedefs.  In that case, just re-use it.  */
+  if (p == NULL)
+    cfun->language = p = ggc_alloc_cleared_language_function ();
 
   p->base.x_stmt_tree = c_stmt_tree;
   c_stmt_tree.x_cur_stmt_list
@@ -8449,7 +8472,11 @@ c_pop_function_context (void)
 
   pop_function_context ();
   p = cfun->language;
-  cfun->language = NULL;
+  /* When -Wunused-local-typedefs is in effect, cfun->languages is
+     used to store data throughout the life time of the current cfun,
+     So don't deallocate it.  */
+  if (!warn_unused_local_typedefs)
+    cfun->language = NULL;
 
   if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
       && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 96275ba..bb57569 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6091,7 +6091,8 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
   tree node = *pnode;
 
   if (TREE_CODE (node) == FUNCTION_DECL
-      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))
+      || (TREE_CODE (node) == TYPE_DECL))
     {
       TREE_USED (node) = 1;
       DECL_PRESERVE_P (node) = 1;
@@ -9604,6 +9605,76 @@ record_types_used_by_current_var_decl (tree decl)
     }
 }
 
+/* If DECL is a typedef that is declared in the current function,
+   record it for the purpose of -Wunused-local-typedefs.  */
+
+void
+record_locally_defined_typedef (tree decl)
+{
+  struct c_language_function *l;
+
+  if (!warn_unused_local_typedefs
+      || cfun == NULL
+      /* if this is not a locally defined typedef then we are not
+	 interested.  */
+      || !is_typedef_decl (decl)
+      || !decl_function_context (decl))
+    return;
+
+  l = (struct c_language_function *) cfun->language;
+  VEC_safe_push (tree, gc, l->local_typedefs, decl);
+}
+
+/* If T is a TYPE_DECL declared locally, mark it as used.  */
+
+void
+maybe_record_typedef_use (tree t)
+{
+  if (!is_typedef_decl (t))
+    return;
+
+  TREE_USED (t) = true;
+}
+
+/* Warn if there are some unused locally defined typedefs in the
+   current function. */
+
+void
+maybe_warn_unused_local_typedefs (void)
+{
+  int i;
+  tree decl;
+  /* The number of times we have emitted -Wunused-local-typedefs
+     warnings.  If this is different from errorcount, that means some
+     unrelated errors have been issued.  In which case, we'll avoid
+     emitting "unused-local-typedefs" warnings.  */
+  static int unused_local_typedefs_warn_count;
+  struct c_language_function *l;
+
+  if (cfun == NULL)
+    return;
+
+  if ((l = (struct c_language_function *) cfun->language) == NULL)
+    return;
+
+  if (warn_unused_local_typedefs
+      && errorcount == unused_local_typedefs_warn_count)
+    {
+      FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
+	if (!TREE_USED (decl))
+	  warning_at (DECL_SOURCE_LOCATION (decl),
+		      OPT_Wunused_local_typedefs,
+		      "typedef %qD locally defined but not used", decl);
+      unused_local_typedefs_warn_count = errorcount;
+    }
+
+  if (l->local_typedefs)
+    {
+      VEC_free (tree, gc, l->local_typedefs);
+      l->local_typedefs = NULL;
+    }
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 3a49779..6b324d4 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -505,6 +505,10 @@ struct GTY(()) c_language_function {
   /* While we are parsing the function, this contains information
      about the statement-tree that we are building.  */
   struct stmt_tree_s x_stmt_tree;
+
+  /* Vector of locally defined typedefs, for
+     -Wunused-local-typedefs.  */
+  VEC(tree,gc) *local_typedefs;
 };
 
 #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
@@ -986,6 +990,9 @@ extern void warn_for_sign_compare (location_t,
 extern void do_warn_double_promotion (tree, tree, tree, const char *, 
 				      location_t);
 extern void set_underlying_type (tree);
+extern void record_locally_defined_typedef (tree);
+extern void maybe_record_typedef_use (tree);
+extern void maybe_warn_unused_local_typedefs (void);
 extern VEC(tree,gc) *make_tree_vector (void);
 extern void release_tree_vector (VEC(tree,gc) *);
 extern VEC(tree,gc) *make_tree_vector_single (tree);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 617ea2d..e6ac5dc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -653,6 +653,10 @@ Wunsuffixed-float-constants
 C ObjC Var(warn_unsuffixed_float_constants) Warning
 Warn about unsuffixed float constants
 
+Wunused-local-typedefs
+C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning
+Warn about
+
 Wunused-macros
 C ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f0d1a1a..cc06682 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13385,6 +13385,10 @@ finish_function (int flags)
       unused_but_set_errorcount = errorcount;
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Genericize before inlining.  */
   if (!processing_template_decl)
     {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f05b0f8..68e9b9b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -868,6 +868,7 @@ grokfield (const cp_declarator *declarator,
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
 	set_underlying_type (value);
 
+      record_locally_defined_typedef (value);
       return value;
     }
 
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 1afd9ed..512480c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	      && TYPE_NAME (type)
 	      && TYPE_IDENTIFIER (type))
 	    set_identifier_type_value (DECL_NAME (x), x);
+
+	  /* If this is a locally defined typedef in a function that
+	     is not a template instantation, record it to implement
+	     -Wunused-local-typedefs.  */
+	  if (current_instantiation () == NULL
+	      || (current_instantiation ()->decl != current_function_decl))
+	  record_locally_defined_typedef (x);
 	}
 
       /* Multiple external decls of the same identifier ought to match.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9b3e56d..ba27acc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19572,6 +19572,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (DECL_P (decl))
     check_accessibility_of_qualified_id (decl, object_type, parser->scope);
 
+  maybe_record_typedef_use (decl);
+
   return decl;
 }
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6fd78d5..5430803 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -267,8 +267,9 @@ Objective-C and Objective-C++ Dialects}.
 -Wsystem-headers  -Wtrampolines  -Wtrigraphs  -Wtype-limits  -Wundef @gol
 -Wuninitialized  -Wunknown-pragmas  -Wno-pragmas @gol
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
--Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value @gol
--Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol
+-Wunused-label  -Wunused-local-typedefs -Wunused-parameter @gol
+-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
+-Wunused-but-set-parameter -Wunused-but-set-variable @gol
 -Wvariadic-macros -Wvla -Wvolatile-register-var  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
@@ -3499,6 +3500,10 @@ This warning is enabled by @option{-Wall}.
 To suppress this warning use the @samp{unused} attribute
 (@pxref{Variable Attributes}).
 
+@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
+@opindex Wunused-local-typedefs
+Warn when a typedef locally defined in a function is not used.
+
 @item -Wunused-parameter
 @opindex Wunused-parameter
 @opindex Wno-unused-parameter
diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
new file mode 100644
index 0000000..683019d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
@@ -0,0 +1,44 @@
+/*  Origin PR c++/33255
+    { dg-options "-Wunused-local-typedefs" }
+    { dg-do compile }
+*/
+
+void
+test_warn ()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+void
+test0 ()
+{
+    typedef int foo;
+    foo var __attribute__((unused));
+}
+
+void
+test1 ()
+{
+    typedef int foo;
+    const foo *var = 0;
+}
+
+void
+test2 ()
+{
+  typedef int foo;
+  void func(foo);  
+}
+
+void
+test7 (void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
+
+void
+test8 (void)
+{
+  typedef int foo __attribute__((used));
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
new file mode 100644
index 0000000..87feb52
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
@@ -0,0 +1,146 @@
+// Origin PR c++/33255
+// { dg-options "-Wunused-local-typedefs" }
+// { dg-do compile }
+
+void
+test_warn()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+struct S
+{
+    typedef int T;
+    S() {}
+    S(int) {}
+};
+
+template<class T>
+struct ST
+{
+    typedef T type;
+    ST (int) {}
+    ST () {}
+};
+
+template<class T>
+void
+test0_tmpl(void)
+{
+    typedef struct ST<T> foo;
+    foo(2);
+}
+
+int
+test0(void)
+{
+    test0_tmpl<int>();
+}
+
+void
+test1(void)
+{
+    typedef int foo;
+    ST<foo> a;
+}
+
+
+int
+test2(void)
+{
+    typedef S foo;
+    foo::T i = 0;
+    return i;
+}
+
+template<class T>
+void
+test3_tmpl(void)
+{
+    typedef struct ST<int> foo;
+    ST<int> v;
+    const foo &var = v;
+}
+
+void
+test3(void)
+{
+    test3_tmpl<int>();
+}
+
+void
+test4(void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
+
+void
+test5(void)
+{
+  typedef int T0;
+  typedef char T1;
+  typedef int* T2;
+  typedef unsigned T3;
+  struct C0 { virtual void f(void) {}};
+  struct C1 : C0 {};
+  typedef C0 T4;
+
+  int v0 = (T0) 2;
+  char v1 = static_cast<T1> (0);
+  reinterpret_cast<T2> (&v0);
+  unsigned* const c = 0;
+  unsigned* v2 = const_cast<T3* const> (c);
+  C0 *p0 = 0;
+  C1 *p1 = 0;
+  p0 = dynamic_cast<T4*> (p1);  
+}
+
+void
+test6(void)
+{
+  struct C0 {};
+  typedef C0 foo;
+  C0 *v = new foo;
+}
+
+template<class T, class U>
+struct S7
+{
+  void
+  f()
+  {
+    typedef int foo;
+    sizeof(foo);
+  }
+};
+
+template<class T>
+void
+test7(void)
+{
+  typedef typename ST<T>::T bar; // { dg-warning "locally defined but not used" }
+  typedef typename ST<T>::T foo; // We shouldn't warn for this one, as
+				 // it's used below.
+  S7<int, foo> v;
+}
+
+
+template<class T, class U>
+void
+test8(void)
+{
+  int f(S7<T, U>);
+  void g(int);
+  typedef T foo;
+  g(f(S7<foo, U>()));
+}
+
+int
+test9(void)
+{
+  struct s { typedef int foo;}; // { dg-warning "locally defined but not used" }
+  struct t { typedef int bar;};
+  t::bar b = 0;
+  return b;
+}
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index dd0634b..41b0b1f 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -238,8 +238,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
       __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
 		    const _Tp& __val, _Compare __comp)
       {
-	typedef typename __mv_iter_traits<_ForwardIterator>::value_type
-	  _ValueType;
 	typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
 	  _DistanceType;
 
diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc
index f161016..6bcf2db 100644
--- a/libstdc++-v3/src/istream.cc
+++ b/libstdc++-v3/src/istream.cc
@@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef basic_istream<char>       	__istream_type;
       typedef __istream_type::int_type		__int_type;
-      typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
       typedef __istream_type::__ctype_type	__ctype_type;
@@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<char>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
@@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<wchar_t>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc
index 4d21ab1..5de146b 100644
--- a/libstdc++-v3/src/valarray.cc
+++ b/libstdc++-v3/src/valarray.cc
@@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline size_t
   __valarray_product(const valarray<size_t>& __a)
   {
-    typedef const size_t* __restrict__ _Tp;
     const size_t __n = __a.size();
     // XXX: This ugly cast is necessary because
     //      valarray::operator[]() const return a VALUE!
-- 
1.7.6



-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-07 18:04           ` Dodji Seketeli
@ 2011-09-07 18:08             ` Jason Merrill
  2011-09-07 20:15               ` Dodji Seketeli
  0 siblings, 1 reply; 28+ messages in thread
From: Jason Merrill @ 2011-09-07 18:08 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 09/07/2011 02:01 PM, Dodji Seketeli wrote:
> +
>   /* Process declarations and variables for C compiler.

Blank line at the top of the file?

>      Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
>      2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
> @@ -8328,7 +8329,8 @@ finish_function (void)
>     if (!decl_function_context (fndecl))
>       undef_nested_function = false;
>
> -  cfun->language = NULL;
> +  if (cfun->language != NULL)
> +    ggc_free (cfun->language);

You'll still want to set it to NULL after freeing it.

OK with those changes.

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-07 18:08             ` Jason Merrill
@ 2011-09-07 20:15               ` Dodji Seketeli
  2011-09-08 16:15                 ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-09-07 20:15 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 09/07/2011 02:01 PM, Dodji Seketeli wrote:
>> +
>>   /* Process declarations and variables for C compiler.
>
> Blank line at the top of the file?

Oops, I noticed it and changed it in the aggregated patch I sent, but
forgot to update the diff against the previous.  Sorry for that.

>>      Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
>>      2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
>> @@ -8328,7 +8329,8 @@ finish_function (void)
>>     if (!decl_function_context (fndecl))
>>       undef_nested_function = false;
>>
>> -  cfun->language = NULL;
>> +  if (cfun->language != NULL)
>> +    ggc_free (cfun->language);
>
> You'll still want to set it to NULL after freeing it.

Fixed.

> OK with those changes.

Thanks.

Here is the patch I will commit in a short while.

gcc/

	* c-decl.c (lookup_name): Use the new
	maybe_record_typedef_use.
	(pushdecl): Use the new
	record_locally_defined_typedef.
	(store_parm_decls): Allocate cfun->language.
	(finish_function): Use the new maybe_warn_unused_local_typedefs,
	and free cfun->language.
	(c_push_function_context): Allocate cfun->language here only if
	needed.
	(c_pop_function_context): Likewise, mark cfun->language
	for collection only when it should be done.
	* c-common.c (handle_used_attribute): Don't ignore TYPE_DECL
	nodes.
	* c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
	maybe_record_local_typedef_use.

gcc/c-family

	* c-common.h (struct c_language_function::local_typedefs): New
	field.
	(record_locally_defined_typedef, maybe_record_typedef_use)
	(maybe_warn_unused_local_typedefs): Declare new functions.
	* c-common.c (record_locally_defined_typedef)
	(maybe_record_typedef_use)
	(maybe_warn_unused_local_typedefs): Define new functions.
	* c.opt: Declare new -Wunused-local-typedefs flag.

gcc/cp

	* name-lookup.c (pushdecl_maybe_friend_1): Use the new
	record_locally_defined_typedef.
	* decl.c (finish_function): Use the new
	maybe_warn_unused_local_typedefs.
	(grokfield): Use the new record_locally_defined_typedef.
	* parser.c (lookup_name): Use the new maybe_record_typedef_use.

gcc/doc/

	* invoke.texi: Update documentation for -Wunused-local-typedefs.

gcc/testsuite/

	* g++.dg/warn/Wunused-local-typedefs.C: New test file.
	* c-c++-common/Wunused-local-typedefs.c: Likewise.

libstdc++-v3/

	* include/ext/bitmap_allocator.h
	(__detail::__mini_vector::__lower_bound): Remove unused typedef.
	* src/istream.cc (std::operator>>(basic_istream<char>& __in,
	basic_string<char>& __str)): Likewise.
	(std::getline): Likewise.
	* src/valarray.cc (__valarray_product): Likewise.
---
 gcc/c-decl.c                                       |   42 +++++-
 gcc/c-family/c-common.c                            |   73 ++++++++++-
 gcc/c-family/c-common.h                            |    7 +
 gcc/c-family/c.opt                                 |    4 +
 gcc/cp/decl.c                                      |    4 +
 gcc/cp/decl2.c                                     |    1 +
 gcc/cp/name-lookup.c                               |    7 +
 gcc/cp/parser.c                                    |    2 +
 gcc/doc/invoke.texi                                |    9 +-
 .../c-c++-common/Wunused-local-typedefs.c          |   44 ++++++
 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C |  146 ++++++++++++++++++++
 libstdc++-v3/include/ext/bitmap_allocator.h        |    2 -
 libstdc++-v3/src/istream.cc                        |    3 -
 libstdc++-v3/src/valarray.cc                       |    1 -
 14 files changed, 330 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
 create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C

diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index d683d4e..5d4564a 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2769,7 +2769,15 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    set_underlying_type (x);
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+	 for the purpose of implementing the -Wunused-local-typedefs
+	 warning.  */
+      record_locally_defined_typedef (x);
+    }
 
   bind (name, x, scope, /*invisible=*/false, nested, locus);
 
@@ -3435,7 +3443,10 @@ lookup_name (tree name)
 {
   struct c_binding *b = I_SYMBOL_BINDING (name);
   if (b && !b->invisible)
-    return b->decl;
+    {
+      maybe_record_typedef_use (b->decl);
+      return b->decl;
+    }
   return 0;
 }
 
@@ -8192,6 +8203,9 @@ store_parm_decls (void)
   /* Initialize the RTL code for the function.  */
   allocate_struct_function (fndecl, false);
 
+  if (warn_unused_local_typedefs)
+    cfun->language = ggc_alloc_cleared_language_function ();
+
   /* Begin the statement tree for this function.  */
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
@@ -8299,6 +8313,10 @@ finish_function (void)
 		      "parameter %qD set but not used", decl);
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
@@ -8344,6 +8362,12 @@ finish_function (void)
   if (!decl_function_context (fndecl))
     undef_nested_function = false;
 
+  if (cfun->language != NULL)
+    {
+      ggc_free (cfun->language);
+      cfun->language = NULL;
+    }
+
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
      tree_rest_of_compilation.  */
@@ -8455,9 +8479,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
 void
 c_push_function_context (void)
 {
-  struct language_function *p;
-  p = ggc_alloc_language_function ();
-  cfun->language = p;
+  struct language_function *p = cfun->language;
+  /* cfun->language might have been already allocated by the use of
+     -Wunused-local-typedefs.  In that case, just re-use it.  */
+  if (p == NULL)
+    cfun->language = p = ggc_alloc_cleared_language_function ();
 
   p->base.x_stmt_tree = c_stmt_tree;
   c_stmt_tree.x_cur_stmt_list
@@ -8483,7 +8509,11 @@ c_pop_function_context (void)
 
   pop_function_context ();
   p = cfun->language;
-  cfun->language = NULL;
+  /* When -Wunused-local-typedefs is in effect, cfun->languages is
+     used to store data throughout the life time of the current cfun,
+     So don't deallocate it.  */
+  if (!warn_unused_local_typedefs)
+    cfun->language = NULL;
 
   if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
       && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d8028d3..e2852b6 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6133,7 +6133,8 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
   tree node = *pnode;
 
   if (TREE_CODE (node) == FUNCTION_DECL
-      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))
+      || (TREE_CODE (node) == TYPE_DECL))
     {
       TREE_USED (node) = 1;
       DECL_PRESERVE_P (node) = 1;
@@ -9646,6 +9647,76 @@ record_types_used_by_current_var_decl (tree decl)
     }
 }
 
+/* If DECL is a typedef that is declared in the current function,
+   record it for the purpose of -Wunused-local-typedefs.  */
+
+void
+record_locally_defined_typedef (tree decl)
+{
+  struct c_language_function *l;
+
+  if (!warn_unused_local_typedefs
+      || cfun == NULL
+      /* if this is not a locally defined typedef then we are not
+	 interested.  */
+      || !is_typedef_decl (decl)
+      || !decl_function_context (decl))
+    return;
+
+  l = (struct c_language_function *) cfun->language;
+  VEC_safe_push (tree, gc, l->local_typedefs, decl);
+}
+
+/* If T is a TYPE_DECL declared locally, mark it as used.  */
+
+void
+maybe_record_typedef_use (tree t)
+{
+  if (!is_typedef_decl (t))
+    return;
+
+  TREE_USED (t) = true;
+}
+
+/* Warn if there are some unused locally defined typedefs in the
+   current function. */
+
+void
+maybe_warn_unused_local_typedefs (void)
+{
+  int i;
+  tree decl;
+  /* The number of times we have emitted -Wunused-local-typedefs
+     warnings.  If this is different from errorcount, that means some
+     unrelated errors have been issued.  In which case, we'll avoid
+     emitting "unused-local-typedefs" warnings.  */
+  static int unused_local_typedefs_warn_count;
+  struct c_language_function *l;
+
+  if (cfun == NULL)
+    return;
+
+  if ((l = (struct c_language_function *) cfun->language) == NULL)
+    return;
+
+  if (warn_unused_local_typedefs
+      && errorcount == unused_local_typedefs_warn_count)
+    {
+      FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
+	if (!TREE_USED (decl))
+	  warning_at (DECL_SOURCE_LOCATION (decl),
+		      OPT_Wunused_local_typedefs,
+		      "typedef %qD locally defined but not used", decl);
+      unused_local_typedefs_warn_count = errorcount;
+    }
+
+  if (l->local_typedefs)
+    {
+      VEC_free (tree, gc, l->local_typedefs);
+      l->local_typedefs = NULL;
+    }
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 7ad82c0..7241d66 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -506,6 +506,10 @@ struct GTY(()) c_language_function {
   /* While we are parsing the function, this contains information
      about the statement-tree that we are building.  */
   struct stmt_tree_s x_stmt_tree;
+
+  /* Vector of locally defined typedefs, for
+     -Wunused-local-typedefs.  */
+  VEC(tree,gc) *local_typedefs;
 };
 
 #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
@@ -988,6 +992,9 @@ extern void warn_for_sign_compare (location_t,
 extern void do_warn_double_promotion (tree, tree, tree, const char *, 
 				      location_t);
 extern void set_underlying_type (tree);
+extern void record_locally_defined_typedef (tree);
+extern void maybe_record_typedef_use (tree);
+extern void maybe_warn_unused_local_typedefs (void);
 extern VEC(tree,gc) *make_tree_vector (void);
 extern void release_tree_vector (VEC(tree,gc) *);
 extern VEC(tree,gc) *make_tree_vector_single (tree);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 617ea2d..e6ac5dc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -653,6 +653,10 @@ Wunsuffixed-float-constants
 C ObjC Var(warn_unsuffixed_float_constants) Warning
 Warn about unsuffixed float constants
 
+Wunused-local-typedefs
+C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning
+Warn about
+
 Wunused-macros
 C ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index eed4535..2712758 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13388,6 +13388,10 @@ finish_function (int flags)
       unused_but_set_errorcount = errorcount;
     }
 
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
   /* Genericize before inlining.  */
   if (!processing_template_decl)
     {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f05b0f8..68e9b9b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -868,6 +868,7 @@ grokfield (const cp_declarator *declarator,
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
 	set_underlying_type (value);
 
+      record_locally_defined_typedef (value);
       return value;
     }
 
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 64456b4..4219548 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	      && TYPE_NAME (type)
 	      && TYPE_IDENTIFIER (type))
 	    set_identifier_type_value (DECL_NAME (x), x);
+
+	  /* If this is a locally defined typedef in a function that
+	     is not a template instantation, record it to implement
+	     -Wunused-local-typedefs.  */
+	  if (current_instantiation () == NULL
+	      || (current_instantiation ()->decl != current_function_decl))
+	  record_locally_defined_typedef (x);
 	}
 
       /* Multiple external decls of the same identifier ought to match.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7d766d1..20bba89 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19576,6 +19576,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (DECL_P (decl))
     check_accessibility_of_qualified_id (decl, object_type, parser->scope);
 
+  maybe_record_typedef_use (decl);
+
   return decl;
 }
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b1ff187..3aa9611 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -268,8 +268,9 @@ Objective-C and Objective-C++ Dialects}.
 -Wsystem-headers  -Wtrampolines  -Wtrigraphs  -Wtype-limits  -Wundef @gol
 -Wuninitialized  -Wunknown-pragmas  -Wno-pragmas @gol
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
--Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value @gol
--Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol
+-Wunused-label  -Wunused-local-typedefs -Wunused-parameter @gol
+-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
+-Wunused-but-set-parameter -Wunused-but-set-variable @gol
 -Wvariadic-macros -Wvla -Wvolatile-register-var  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
@@ -3501,6 +3502,10 @@ This warning is enabled by @option{-Wall}.
 To suppress this warning use the @samp{unused} attribute
 (@pxref{Variable Attributes}).
 
+@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
+@opindex Wunused-local-typedefs
+Warn when a typedef locally defined in a function is not used.
+
 @item -Wunused-parameter
 @opindex Wunused-parameter
 @opindex Wno-unused-parameter
diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
new file mode 100644
index 0000000..683019d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c
@@ -0,0 +1,44 @@
+/*  Origin PR c++/33255
+    { dg-options "-Wunused-local-typedefs" }
+    { dg-do compile }
+*/
+
+void
+test_warn ()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+void
+test0 ()
+{
+    typedef int foo;
+    foo var __attribute__((unused));
+}
+
+void
+test1 ()
+{
+    typedef int foo;
+    const foo *var = 0;
+}
+
+void
+test2 ()
+{
+  typedef int foo;
+  void func(foo);  
+}
+
+void
+test7 (void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
+
+void
+test8 (void)
+{
+  typedef int foo __attribute__((used));
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
new file mode 100644
index 0000000..87feb52
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C
@@ -0,0 +1,146 @@
+// Origin PR c++/33255
+// { dg-options "-Wunused-local-typedefs" }
+// { dg-do compile }
+
+void
+test_warn()
+{
+  typedef int foo; // { dg-warning "locally defined but not used" }
+}
+
+struct S
+{
+    typedef int T;
+    S() {}
+    S(int) {}
+};
+
+template<class T>
+struct ST
+{
+    typedef T type;
+    ST (int) {}
+    ST () {}
+};
+
+template<class T>
+void
+test0_tmpl(void)
+{
+    typedef struct ST<T> foo;
+    foo(2);
+}
+
+int
+test0(void)
+{
+    test0_tmpl<int>();
+}
+
+void
+test1(void)
+{
+    typedef int foo;
+    ST<foo> a;
+}
+
+
+int
+test2(void)
+{
+    typedef S foo;
+    foo::T i = 0;
+    return i;
+}
+
+template<class T>
+void
+test3_tmpl(void)
+{
+    typedef struct ST<int> foo;
+    ST<int> v;
+    const foo &var = v;
+}
+
+void
+test3(void)
+{
+    test3_tmpl<int>();
+}
+
+void
+test4(void)
+{
+  typedef int foo;
+  int vec[1] = {sizeof (foo)};
+}
+
+void
+test5(void)
+{
+  typedef int T0;
+  typedef char T1;
+  typedef int* T2;
+  typedef unsigned T3;
+  struct C0 { virtual void f(void) {}};
+  struct C1 : C0 {};
+  typedef C0 T4;
+
+  int v0 = (T0) 2;
+  char v1 = static_cast<T1> (0);
+  reinterpret_cast<T2> (&v0);
+  unsigned* const c = 0;
+  unsigned* v2 = const_cast<T3* const> (c);
+  C0 *p0 = 0;
+  C1 *p1 = 0;
+  p0 = dynamic_cast<T4*> (p1);  
+}
+
+void
+test6(void)
+{
+  struct C0 {};
+  typedef C0 foo;
+  C0 *v = new foo;
+}
+
+template<class T, class U>
+struct S7
+{
+  void
+  f()
+  {
+    typedef int foo;
+    sizeof(foo);
+  }
+};
+
+template<class T>
+void
+test7(void)
+{
+  typedef typename ST<T>::T bar; // { dg-warning "locally defined but not used" }
+  typedef typename ST<T>::T foo; // We shouldn't warn for this one, as
+				 // it's used below.
+  S7<int, foo> v;
+}
+
+
+template<class T, class U>
+void
+test8(void)
+{
+  int f(S7<T, U>);
+  void g(int);
+  typedef T foo;
+  g(f(S7<foo, U>()));
+}
+
+int
+test9(void)
+{
+  struct s { typedef int foo;}; // { dg-warning "locally defined but not used" }
+  struct t { typedef int bar;};
+  t::bar b = 0;
+  return b;
+}
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index 51bdc6ffb..cb6fc38 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -237,8 +237,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
       __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
 		    const _Tp& __val, _Compare __comp)
       {
-	typedef typename __mv_iter_traits<_ForwardIterator>::value_type
-	  _ValueType;
 	typedef typename __mv_iter_traits<_ForwardIterator>::difference_type
 	  _DistanceType;
 
diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc
index f161016..6bcf2db 100644
--- a/libstdc++-v3/src/istream.cc
+++ b/libstdc++-v3/src/istream.cc
@@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef basic_istream<char>       	__istream_type;
       typedef __istream_type::int_type		__int_type;
-      typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
       typedef __istream_type::__ctype_type	__ctype_type;
@@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<char>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
@@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __istream_type::char_type		__char_type;
       typedef __istream_type::traits_type	__traits_type;
       typedef __istream_type::__streambuf_type  __streambuf_type;
-      typedef __istream_type::__ctype_type	__ctype_type;
       typedef basic_string<wchar_t>        	__string_type;
       typedef __string_type::size_type		__size_type;
 
diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc
index 4d21ab1..5de146b 100644
--- a/libstdc++-v3/src/valarray.cc
+++ b/libstdc++-v3/src/valarray.cc
@@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline size_t
   __valarray_product(const valarray<size_t>& __a)
   {
-    typedef const size_t* __restrict__ _Tp;
     const size_t __n = __a.size();
     // XXX: This ugly cast is necessary because
     //      valarray::operator[]() const return a VALUE!
-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-07 20:15               ` Dodji Seketeli
@ 2011-09-08 16:15                 ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2011-09-08 16:15 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, Paolo Carlini, GCC Patches

On Wed, Sep 7, 2011 at 12:57 PM, Dodji Seketeli <dodji@redhat.com> wrote:
> Jason Merrill <jason@redhat.com> writes:
>
>> On 09/07/2011 02:01 PM, Dodji Seketeli wrote:
>>> +
>>>   /* Process declarations and variables for C compiler.
>>
>> Blank line at the top of the file?
>
> Oops, I noticed it and changed it in the aggregated patch I sent, but
> forgot to update the diff against the previous.  Sorry for that.
>
>>>      Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
>>>      2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
>>> @@ -8328,7 +8329,8 @@ finish_function (void)
>>>     if (!decl_function_context (fndecl))
>>>       undef_nested_function = false;
>>>
>>> -  cfun->language = NULL;
>>> +  if (cfun->language != NULL)
>>> +    ggc_free (cfun->language);
>>
>> You'll still want to set it to NULL after freeing it.
>
> Fixed.
>
>> OK with those changes.
>
> Thanks.
>
> Here is the patch I will commit in a short while.
>
> gcc/
>
>        * c-decl.c (lookup_name): Use the new
>        maybe_record_typedef_use.
>        (pushdecl): Use the new
>        record_locally_defined_typedef.
>        (store_parm_decls): Allocate cfun->language.
>        (finish_function): Use the new maybe_warn_unused_local_typedefs,
>        and free cfun->language.
>        (c_push_function_context): Allocate cfun->language here only if
>        needed.
>        (c_pop_function_context): Likewise, mark cfun->language
>        for collection only when it should be done.
>        * c-common.c (handle_used_attribute): Don't ignore TYPE_DECL
>        nodes.
>        * c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new
>        maybe_record_local_typedef_use.
>
> gcc/c-family
>
>        * c-common.h (struct c_language_function::local_typedefs): New
>        field.
>        (record_locally_defined_typedef, maybe_record_typedef_use)
>        (maybe_warn_unused_local_typedefs): Declare new functions.
>        * c-common.c (record_locally_defined_typedef)
>        (maybe_record_typedef_use)
>        (maybe_warn_unused_local_typedefs): Define new functions.
>        * c.opt: Declare new -Wunused-local-typedefs flag.
>
> gcc/cp
>
>        * name-lookup.c (pushdecl_maybe_friend_1): Use the new
>        record_locally_defined_typedef.
>        * decl.c (finish_function): Use the new
>        maybe_warn_unused_local_typedefs.
>        (grokfield): Use the new record_locally_defined_typedef.
>        * parser.c (lookup_name): Use the new maybe_record_typedef_use.
>
> gcc/doc/
>
>        * invoke.texi: Update documentation for -Wunused-local-typedefs.
>
> gcc/testsuite/
>
>        * g++.dg/warn/Wunused-local-typedefs.C: New test file.
>        * c-c++-common/Wunused-local-typedefs.c: Likewise.
>
> libstdc++-v3/
>
>        * include/ext/bitmap_allocator.h
>        (__detail::__mini_vector::__lower_bound): Remove unused typedef.
>        * src/istream.cc (std::operator>>(basic_istream<char>& __in,
>        basic_string<char>& __str)): Likewise.
>        (std::getline): Likewise.
>        * src/valarray.cc (__valarray_product): Likewise.

This may have caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50332

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-07-29 17:12     ` Jason Merrill
  2011-07-29 17:40       ` Dodji Seketeli
@ 2011-09-08 21:13       ` Dodji Seketeli
  2011-09-08 21:45         ` Jason Merrill
  1 sibling, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-09-08 21:13 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> I think -Wunused and -Wall should imply -Wunused-local-typedefs unless
> the user specifies -Wno-unused-local-typedefs.

Dodji Seketeli <dodji@redhat.com> writes:

> I actually first tried this (actually adding it to -Wall -extra and
> -Wunused) and found out the following issue.
> 
> A typedef can be defined in a macro in a system header, be expanded in
> a function and not be used by the function.  In this case we shouldn't
> warn, but PR preprocessor/7263 makes us warn nonetheless.  There are
> many spots of that kind in the libstdc++ test suite.
> 

Jason Merrill <jason@redhat.com> writes:

> Does your set of linemap patches fix the issue?  In that case, we can
> add it when those go in.  Speaking of which, sorry I haven't found the
> time to review them yet.

So, in prevision of when the patch for PR preprocessor/7263 goes in, I
am proposing this patchlet that turns on -Wunused-local-typedefs
whenever -Wunused (and so -Wall) is turned on.

I have tested it on a synthetic tree made of my current patch series for
PR preprocessor/7263, and trunk that contains -Wunused-local-typedefs
support.

Is this be OK for trunk when PR preprocessor/7263 gets in, assuming it
passes bootstrap and tests on trunk at that moment?

Thanks.


    Enable -Wunused-local-typedefs when -Wall or -Wunused
    
    gcc/
    
    	* opts.c (finish_options): Activate -Wunused-local-typedefs if
    	-Wunused is activated.
    	* doc/invoke.texi: Update blurb of -Wunused-local-typedefs.

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3aa9611..5f4afe3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3505,6 +3505,7 @@ To suppress this warning use the @samp{unused} attribute
 @item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
 @opindex Wunused-local-typedefs
 Warn when a typedef locally defined in a function is not used.
+This warning is enabled by @option{-Wall}.
 
 @item -Wunused-parameter
 @opindex Wunused-parameter
diff --git a/gcc/opts.c b/gcc/opts.c
index 5d5bcb9..ebb99d0 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -830,6 +830,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   if (opts->x_warn_unused_value == -1)
     opts->x_warn_unused_value = opts->x_warn_unused;
 
+  /* Wunused-local-typedefs is enabled by -Wunused or -Wall.  */
+  if (opts->x_warn_unused_local_typedefs == -1)
+    opts->x_warn_unused_local_typedefs = opts->x_warn_unused;
+
   /* This replaces set_Wextra.  */
   if (opts->x_warn_uninitialized == -1)
     opts->x_warn_uninitialized = opts->x_extra_warnings;
-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-08 21:13       ` Dodji Seketeli
@ 2011-09-08 21:45         ` Jason Merrill
  2011-09-09  3:07           ` Dodji Seketeli
  0 siblings, 1 reply; 28+ messages in thread
From: Jason Merrill @ 2011-09-08 21:45 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 09/08/2011 04:50 PM, Dodji Seketeli wrote:
> Is this be OK for trunk when PR preprocessor/7263 gets in, assuming it
> passes bootstrap and tests on trunk at that moment?

Yes, except...

> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -3505,6 +3505,7 @@ To suppress this warning use the @samp{unused} attribute
>   @item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
>   @opindex Wunused-local-typedefs
>   Warn when a typedef locally defined in a function is not used.
> +This warning is enabled by @option{-Wall}.

Don't you want to say "This warning is also enabled by 
@option{-Wunused}, which is enabled by @option{-Wall}."?

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-08 21:45         ` Jason Merrill
@ 2011-09-09  3:07           ` Dodji Seketeli
  2011-09-09  6:52             ` Jason Merrill
  0 siblings, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2011-09-09  3:07 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 09/08/2011 04:50 PM, Dodji Seketeli wrote:
>> Is this be OK for trunk when PR preprocessor/7263 gets in, assuming it
>> passes bootstrap and tests on trunk at that moment?
>
> Yes, except...
>
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -3505,6 +3505,7 @@ To suppress this warning use the @samp{unused} attribute
>>   @item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
>>   @opindex Wunused-local-typedefs
>>   Warn when a typedef locally defined in a function is not used.
>> +This warning is enabled by @option{-Wall}.
>
> Don't you want to say "This warning is also enabled by
> @option{-Wunused}, which is enabled by @option{-Wall}."?

For the sake of consistency, I followed the pattern used for the other
-Wunused-* options in that same file.

I thought I didn't have to mention that -Wunused triggers
-Wunused-local-typedefs because a bit below this, the text for -Wunused
reads:

    All the above @option{-Wunused} options combined.

And before that, each relevant -Wunused-* option is said to be triggered
by -Wall, as I did.

I would also find your phrasing more logical, if it wasn't for the
consistency constraint.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-09  3:07           ` Dodji Seketeli
@ 2011-09-09  6:52             ` Jason Merrill
  2011-11-07 17:58               ` Jason Merrill
  2012-05-04 16:41               ` [PATCH C/C++] Enable -Wunused-local-typedefs when -Wall or -Wunused is on Dodji Seketeli
  0 siblings, 2 replies; 28+ messages in thread
From: Jason Merrill @ 2011-09-09  6:52 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

On 09/08/2011 05:54 PM, Dodji Seketeli wrote:
> Jason Merrill<jason@redhat.com>  writes:
>
>> Don't you want to say "This warning is also enabled by
>> @option{-Wunused}, which is enabled by @option{-Wall}."?
>
> For the sake of consistency, I followed the pattern used for the other
> -Wunused-* options in that same file.

OK.

Jason

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning
  2011-09-09  6:52             ` Jason Merrill
@ 2011-11-07 17:58               ` Jason Merrill
  2012-05-04 16:41               ` [PATCH C/C++] Enable -Wunused-local-typedefs when -Wall or -Wunused is on Dodji Seketeli
  1 sibling, 0 replies; 28+ messages in thread
From: Jason Merrill @ 2011-11-07 17:58 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 196 bytes --]

The bootstrap issues with a recent patch of mine led me to run make 
check-g++-strict-gc, which turned up a GC problem with this code, fixed 
thus.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: 33255-gc.patch --]
[-- Type: text/x-patch, Size: 512 bytes --]

commit f2f82e0908b807a0d339a00b434913fc0886c0cc
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Nov 7 09:19:27 2011 -0500

    	PR c++/33255
    	* decl.c (save_function_data): Clear local_typedefs.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3b283d8..63da51d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13021,6 +13021,7 @@ save_function_data (tree decl)
   f->base.x_stmt_tree.x_cur_stmt_list = NULL;
   f->bindings = NULL;
   f->x_local_names = NULL;
+  f->base.local_typedefs = NULL;
 }
 
 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH C/C++] Enable -Wunused-local-typedefs when -Wall or -Wunused is on
  2011-09-09  6:52             ` Jason Merrill
  2011-11-07 17:58               ` Jason Merrill
@ 2012-05-04 16:41               ` Dodji Seketeli
  2012-05-04 16:49                 ` Paolo Carlini
  1 sibling, 1 reply; 28+ messages in thread
From: Dodji Seketeli @ 2012-05-04 16:41 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, GCC Patches

Hello,

Now that the libstdc++ testsuite is run with -ftrack-macro-location by
default, this patch triggers the -Wunused-local-typedefs warning when
-Wunused (and -Wall) is turned on.

The patch has been reviewed and accepted[1] a while ago, but was waiting
for the -ftrack-macro-expansion work to go in first.

Bootstrapped and tested again on x86_64-unknown-linux-gnu against
trunk.

Applied to the mainline.

[1]: http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00605.html

gcc/

	* opts.c (finish_options): Activate -Wunused-local-typedefs if
	-Wunused is activated.
	* doc/invoke.texi: Update blurb of -Wunused-local-typedefs.
---
 gcc/ChangeLog       |    7 +++++++
 gcc/doc/invoke.texi |    1 +
 gcc/opts.c          |    4 ++++
 3 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2e3fa0c..d372a4f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2012-05-04  Dodji Seketeli  <dodji@redhat.com>
+
+	Enable -Wunused-local-typedefs when -Wall or -Wunused is on
+	* opts.c (finish_options): Activate -Wunused-local-typedefs if
+    	-Wunused is activated.
+	* doc/invoke.texi: Update blurb of -Wunused-local-typedefs.
+
 2012-05-04  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
 	* config/s390/s390.md (*movmem_short, *clrmem_short)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5550c71..86698fc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3622,6 +3622,7 @@ To suppress this warning use the @samp{unused} attribute
 @item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)}
 @opindex Wunused-local-typedefs
 Warn when a typedef locally defined in a function is not used.
+This warning is enabled by @option{-Wall}.
 
 @item -Wunused-parameter
 @opindex Wunused-parameter
diff --git a/gcc/opts.c b/gcc/opts.c
index 22c7590..b6c786f 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -835,6 +835,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   if (opts->x_warn_unused_value == -1)
     opts->x_warn_unused_value = opts->x_warn_unused;
 
+  /* Wunused-local-typedefs is enabled by -Wunused or -Wall.  */
+  if (opts->x_warn_unused_local_typedefs == -1)
+    opts->x_warn_unused_local_typedefs = opts->x_warn_unused;
+
   /* This replaces set_Wextra.  */
   if (opts->x_warn_uninitialized == -1)
     opts->x_warn_uninitialized = opts->x_extra_warnings;
-- 
		Dodji

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH C/C++] Enable -Wunused-local-typedefs when -Wall or -Wunused is on
  2012-05-04 16:41               ` [PATCH C/C++] Enable -Wunused-local-typedefs when -Wall or -Wunused is on Dodji Seketeli
@ 2012-05-04 16:49                 ` Paolo Carlini
  0 siblings, 0 replies; 28+ messages in thread
From: Paolo Carlini @ 2012-05-04 16:49 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, GCC Patches

On 05/04/2012 06:40 PM, Dodji Seketeli wrote:
> Hello,
>
> Now that the libstdc++ testsuite is run with -ftrack-macro-location by
> default, this patch triggers the -Wunused-local-typedefs warning when
> -Wunused (and -Wall) is turned on.
Yeah!!!

Paolo.

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2012-05-04 16:49 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-27 21:35 [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning Dodji Seketeli
2011-07-29  9:35 ` Jason Merrill
2011-07-29 10:25   ` Paolo Carlini
2011-07-29 11:34   ` Dodji Seketeli
2011-07-29 12:37     ` Paolo Carlini
2011-07-29 17:12     ` Jason Merrill
2011-07-29 17:40       ` Dodji Seketeli
2011-09-08 21:13       ` Dodji Seketeli
2011-09-08 21:45         ` Jason Merrill
2011-09-09  3:07           ` Dodji Seketeli
2011-09-09  6:52             ` Jason Merrill
2011-11-07 17:58               ` Jason Merrill
2012-05-04 16:41               ` [PATCH C/C++] Enable -Wunused-local-typedefs when -Wall or -Wunused is on Dodji Seketeli
2012-05-04 16:49                 ` Paolo Carlini
2011-07-29 15:58   ` [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning Dodji Seketeli
2011-07-29 17:10     ` Jason Merrill
2011-07-29 17:56       ` Dodji Seketeli
2011-07-29 22:41         ` Jason Merrill
2011-07-30 16:44           ` Joseph S. Myers
2011-08-06 12:49   ` Dodji Seketeli
2011-08-07  7:46     ` Jason Merrill
2011-08-08 21:49       ` Dodji Seketeli
2011-09-01 16:52         ` [PING] " Dodji Seketeli
2011-09-06 19:24         ` Jason Merrill
2011-09-07 18:04           ` Dodji Seketeli
2011-09-07 18:08             ` Jason Merrill
2011-09-07 20:15               ` Dodji Seketeli
2011-09-08 16:15                 ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).