aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2011-09-08 13:54:24 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2011-09-08 15:54:24 +0200
commit3797cb21ffb893336be1c6b0d4e3bfd8b35fe884 (patch)
tree27754af02dd2eee09863de910cfb346079141257 /gcc
parentd275ab8b8056a692e67d0f1a46bc766762f62806 (diff)
downloadgcc-3797cb21ffb893336be1c6b0d4e3bfd8b35fe884.zip
gcc-3797cb21ffb893336be1c6b0d4e3bfd8b35fe884.tar.gz
gcc-3797cb21ffb893336be1c6b0d4e3bfd8b35fe884.tar.bz2
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 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. From-SVN: r178692
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/c-decl.c42
-rw-r--r--gcc/c-family/ChangeLog12
-rw-r--r--gcc/c-family/c-common.c73
-rw-r--r--gcc/c-family/c-common.h7
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/decl2.c1
-rw-r--r--gcc/cp/name-lookup.c7
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/c-c++-common/Wunused-local-typedefs.c44
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C146
15 files changed, 378 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a0a89bb..9c6b1ee 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2011-09-08 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/33255 - Support -Wunused-local-typedefs warning
+ * 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.
+ * doc/invoke.texi: Update documentation for
+ -Wunused-local-typedefs.
+
2011-09-08 Enkovich Ilya <ilya.enkovich@intel.com>
* config/i386/i386-protos.h (ix86_lea_outperforms): New.
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/ChangeLog b/gcc/c-family/ChangeLog
index 347d904..080d42a 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,15 @@
+2011-09-08 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/33255 - Support -Wunused-local-typedefs warning
+ * 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.
+
2011-09-06 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/50266
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/ChangeLog b/gcc/cp/ChangeLog
index 9810d7d..8ee3087 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2011-09-08 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/33255 - Support -Wunused-local-typedefs warning
+ * 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.
+
2011-09-07 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50309
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e30fe18..a68bcb1240 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13392,6 +13392,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 6346aa0..03f75fc 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19587,6 +19587,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/ChangeLog b/gcc/testsuite/ChangeLog
index fecb2f4..e6c4db0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-09-08 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/33255 - Support -Wunused-local-typedefs warning
+ * g++.dg/warn/Wunused-local-typedefs.C: New test file.
+ * c-c++-common/Wunused-local-typedefs.c: Likewise.
+
2011-09-08 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/50287
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;
+}