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 <do...@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

Reply via email to