Patchwork PR c++/33255 - Support -Wunused-local-typedefs warning

login
register
mail settings
Submitter Dodji Seketeli
Date Aug. 6, 2011, 10:57 a.m.
Message ID <m3hb5uvmc5.fsf@redhat.com>
Download mbox | patch
Permalink /patch/108768/
State New
Headers show

Comments

Dodji Seketeli - Aug. 6, 2011, 10:57 a.m.
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
Jason Merrill - Aug. 7, 2011, 3:38 a.m.
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?

Patch

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!