From 62206d34fbed0af4ecde1cbea17997577afb1377 Mon Sep 17 00:00:00 2001 From: paolo Date: Mon, 19 Mar 2012 15:51:25 +0000 Subject: [PATCH] 2012-03-16 Paolo Carlini PR c++/14710 * doc/invoke.texi: Document -Wuseless-cast. /c-family 2012-03-16 Paolo Carlini PR c++/14710 * c.opt ([Wuseless-cast]): Add. /cp 2012-03-16 Paolo Carlini PR c++/14710 * cp-tree.h (maybe_warn_about_useless_cast): Declare. * typeck.c (maybe_warn_about_useless_cast): Define. (build_reinterpret_cast, build_const_cast, build_static_cast, cp_build_c_cast): Use it. * rtti.c (build_dynamic_cast): Likewise. * pt.c (tsubst_copy_and_build, case CAST_EXPR): Increment/decrement c_inhibit_evaluation_warnings before/after the build_* calls. /testsuite 2012-03-16 Paolo Carlini PR c++/14710 * g++.dg/warn/Wuseless-cast.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185524 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 ++ gcc/c-family/ChangeLog | 5 ++ gcc/c-family/c.opt | 4 + gcc/cp/ChangeLog | 12 +++ gcc/cp/cp-tree.h | 5 +- gcc/cp/pt.c | 21 +++-- gcc/cp/rtti.c | 11 ++- gcc/cp/tree.c | 11 ++- gcc/cp/typeck.c | 55 +++++++++++-- gcc/doc/invoke.texi | 9 ++- gcc/testsuite/g++.dg/warn/Wuseless-cast.C | 123 ++++++++++++++++++++++++++++++ 11 files changed, 241 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wuseless-cast.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 670361e..050d379 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2012-03-19 Paolo Carlini + + PR c++/14710 + * doc/invoke.texi: Document -Wuseless-cast. + 2012-03-19 Eric Botcazou * tree.def (REALPART_EXPR, IMAGPART_EXPR, VIEW_CONVERT_EXPR): Move. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index dd7b77b..1b586e5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2012-03-19 Paolo Carlini + + PR c++/14710 + * c.opt ([Wuseless-cast]): Add. + 2012-03-16 Richard Guenther * c-pretty-print.c (pp_c_initializer_list): Adjust. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index a14514a..1ec5504 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -697,6 +697,10 @@ Wzero-as-null-pointer-constant C++ ObjC++ Var(warn_zero_as_null_pointer_constant) Warning Warn when a literal '0' is used as null pointer +Wuseless-cast +C++ ObjC++ Var(warn_useless_cast) Warning +Warn about useless casts + ansi C ObjC C++ ObjC++ A synonym for -std=c89 (for C) or -std=c++98 (for C++) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cf4d453..7908bb3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2012-03-19 Paolo Carlini + + PR c++/14710 + * cp-tree.h (xvalue_p, maybe_warn_about_useless_cast): Declare. + * tree.c (xvalue_p): Define. + * typeck.c (maybe_warn_about_useless_cast): Define. + (build_reinterpret_cast, build_const_cast, + build_static_cast, cp_build_c_cast): Use maybe_warn_about_useless_cast. + * rtti.c (build_dynamic_cast): Likewise. + * pt.c (tsubst_copy_and_build, case CAST_EXPR): Increment/decrement + c_inhibit_evaluation_warnings before/after the build_* calls. + 2012-03-15 Jason Merrill PR c++/52582 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d24c596..fc60d86 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1,6 +1,7 @@ /* Definitions for C++ parsing and type checking. Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) @@ -5661,6 +5662,7 @@ extern int member_p (const_tree); extern cp_lvalue_kind real_lvalue_p (const_tree); extern cp_lvalue_kind lvalue_kind (const_tree); extern bool lvalue_or_rvalue_with_address_p (const_tree); +extern bool xvalue_p (const_tree); extern bool builtin_valid_in_constant_expr_p (const_tree); extern tree build_min (enum tree_code, tree, ...); extern tree build_min_nt (enum tree_code, ...); @@ -5860,6 +5862,7 @@ extern int lvalue_or_else (tree, enum lvalue_use, extern void check_template_keyword (tree); extern bool check_raw_literal_operator (const_tree decl); extern bool check_literal_operator_args (const_tree, bool *, bool *); +extern void maybe_warn_about_useless_cast (tree, tree, tsubst_flags_t); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6dd004e..b36e49d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13444,7 +13444,7 @@ tsubst_copy_and_build (tree t, case STATIC_CAST_EXPR: { tree type; - tree op; + tree op, r = NULL_TREE; type = tsubst (TREE_TYPE (t), args, complain, in_decl); if (integral_constant_expression_p @@ -13458,21 +13458,30 @@ tsubst_copy_and_build (tree t, op = RECUR (TREE_OPERAND (t, 0)); + ++c_inhibit_evaluation_warnings; switch (TREE_CODE (t)) { case CAST_EXPR: - return build_functional_cast (type, op, complain); + r = build_functional_cast (type, op, complain); + break; case REINTERPRET_CAST_EXPR: - return build_reinterpret_cast (type, op, complain); + r = build_reinterpret_cast (type, op, complain); + break; case CONST_CAST_EXPR: - return build_const_cast (type, op, complain); + r = build_const_cast (type, op, complain); + break; case DYNAMIC_CAST_EXPR: - return build_dynamic_cast (type, op, complain); + r = build_dynamic_cast (type, op, complain); + break; case STATIC_CAST_EXPR: - return build_static_cast (type, op, complain); + r = build_static_cast (type, op, complain); + break; default: gcc_unreachable (); } + --c_inhibit_evaluation_warnings; + + return r; } case POSTDECREMENT_EXPR: diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 30383ed..2ca8fa5 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -1,6 +1,6 @@ /* RunTime Type Identification Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Mostly written by Jason Merrill (jason@cygnus.com). @@ -774,6 +774,8 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) tree build_dynamic_cast (tree type, tree expr, tsubst_flags_t complain) { + tree r; + if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -784,9 +786,12 @@ build_dynamic_cast (tree type, tree expr, tsubst_flags_t complain) return convert_from_reference (expr); } - return convert_from_reference (build_dynamic_cast_1 (type, expr, complain)); + r = convert_from_reference (build_dynamic_cast_1 (type, expr, complain)); + if (r != error_mark_node) + maybe_warn_about_useless_cast (type, expr, complain); + return r; } - + /* Return the runtime bit mask encoding the qualifiers of TYPE. */ static int diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index b80b52a..87e9be8 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1,6 +1,7 @@ /* Language-dependent node constructors for parse phase of GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -274,6 +275,14 @@ lvalue_or_rvalue_with_address_p (const_tree ref) return (kind != clk_none); } +/* Returns true if REF is an xvalue, false otherwise. */ + +bool +xvalue_p (const_tree ref) +{ + return (lvalue_kind (ref) == clk_rvalueref); +} + /* Test whether DECL is a builtin that may appear in a constant-expression. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 643454c..d2d6c4e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5749,6 +5749,28 @@ check_for_casting_away_constness (tree src_type, tree dest_type, } } +/* + Warns if the cast from expression EXPR to type TYPE is useless. + */ +void +maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain) +{ + if (warn_useless_cast + && complain & tf_warning + && c_inhibit_evaluation_warnings == 0) + { + if (REFERENCE_REF_P (expr)) + expr = TREE_OPERAND (expr, 0); + + if ((TREE_CODE (type) == REFERENCE_TYPE + && (TYPE_REF_IS_RVALUE (type) + ? xvalue_p (expr) : real_lvalue_p (expr)) + && same_type_p (TREE_TYPE (expr), TREE_TYPE (type))) + || same_type_p (TREE_TYPE (expr), type)) + warning (OPT_Wuseless_cast, "useless cast to type %qT", type); + } +} + /* Convert EXPR (an expression with pointer-to-member type) to TYPE (another pointer-to-member type in the same hierarchy) and return the converted expression. If ALLOW_INVERSE_P is permitted, a @@ -6078,7 +6100,11 @@ build_static_cast (tree type, tree expr, tsubst_flags_t complain) result = build_static_cast_1 (type, expr, /*c_cast_p=*/false, &valid_p, complain); if (valid_p) - return result; + { + if (result != error_mark_node) + maybe_warn_about_useless_cast (type, expr, complain); + return result; + } if (complain & tf_error) error ("invalid static_cast from type %qT to type %qT", @@ -6305,6 +6331,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, tree build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain) { + tree r; + if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -6319,8 +6347,11 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain) return convert_from_reference (t); } - return build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false, - /*valid_p=*/NULL, complain); + r = build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false, + /*valid_p=*/NULL, complain); + if (r != error_mark_node) + maybe_warn_about_useless_cast (type, expr, complain); + return r; } /* Perform a const_cast from EXPR to TYPE. If the cast is valid, @@ -6464,6 +6495,8 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain, tree build_const_cast (tree type, tree expr, tsubst_flags_t complain) { + tree r; + if (type == error_mark_node || error_operand_p (expr)) return error_mark_node; @@ -6478,8 +6511,10 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain) return convert_from_reference (t); } - return build_const_cast_1 (type, expr, complain, - /*valid_p=*/NULL); + r = build_const_cast_1 (type, expr, complain, /*valid_p=*/NULL); + if (r != error_mark_node) + maybe_warn_about_useless_cast (type, expr, complain); + return r; } /* Like cp_build_c_cast, but for the c-common bits. */ @@ -6567,7 +6602,11 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) result = build_const_cast_1 (type, value, complain & tf_warning, &valid_p); if (valid_p) - return result; + { + if (result != error_mark_node) + maybe_warn_about_useless_cast (type, value, complain); + return result; + } /* Or a static cast. */ result = build_static_cast_1 (type, value, /*c_cast_p=*/true, @@ -6580,11 +6619,13 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) const_cast. */ if (valid_p /* A valid cast may result in errors if, for example, a - conversion to am ambiguous base class is required. */ + conversion to an ambiguous base class is required. */ && !error_operand_p (result)) { tree result_type; + maybe_warn_about_useless_cast (type, value, complain); + /* Non-class rvalues always have cv-unqualified type. */ if (!CLASS_TYPE_P (type)) type = TYPE_MAIN_VARIANT (type); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8571a8b..bf821ff 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -274,8 +274,8 @@ Objective-C and Objective-C++ Dialects}. -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 -Wvector-operation-performance -Wvla --Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant} +-Wuseless-cast -Wvariadic-macros -Wvector-operation-performance @gol +-Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant} @item C and Objective-C-only Warning Options @gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol @@ -4199,6 +4199,11 @@ types. @option{-Wconversion-null} is enabled by default. Warn when a literal '0' is used as null pointer constant. This can be useful to facilitate the conversion to @code{nullptr} in C++11. +@item -Wuseless-cast @r{(C++ and Objective-C++ only)} +@opindex Wuseless-cast +@opindex Wno-useless-cast +Warn when an expression is casted to its own type. + @item -Wempty-body @opindex Wempty-body @opindex Wno-empty-body diff --git a/gcc/testsuite/g++.dg/warn/Wuseless-cast.C b/gcc/testsuite/g++.dg/warn/Wuseless-cast.C new file mode 100644 index 0000000..8000d93 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wuseless-cast.C @@ -0,0 +1,123 @@ +// { dg-options "-Wuseless-cast" } + +template + void tmpl_f1(T& t) + { + (int)(t); + static_cast(t); + reinterpret_cast(t); + + (int*)(&t); + const_cast(&t); + static_cast(&t); + reinterpret_cast(&t); + + (int&)(t); + const_cast(t); + static_cast(t); + reinterpret_cast(t); + } + +template + void tmpl_f2(T t) + { + (int&)(t); + const_cast(t); + static_cast(t); + reinterpret_cast(t); + } + +struct A { }; + +template + void tmpl_f3(T& t) + { + (A)(t); + static_cast(t); + + (A*)(&t); + const_cast(&t); + static_cast(&t); + reinterpret_cast(&t); + dynamic_cast(&t); + + (A&)(t); + const_cast(t); + static_cast(t); + reinterpret_cast(t); + dynamic_cast(t); + } + +template + void tmpl_f4(T t) + { + (A&)(t); + const_cast(t); + static_cast(t); + reinterpret_cast(t); + dynamic_cast(t); + } + +void f() +{ + int n; + + (int)(n); // { dg-warning "useless cast" } + static_cast(n); // { dg-warning "useless cast" } + reinterpret_cast(n); // { dg-warning "useless cast" } + + (int*)(&n); // { dg-warning "useless cast" } + const_cast(&n); // { dg-warning "useless cast" } + static_cast(&n); // { dg-warning "useless cast" } + reinterpret_cast(&n); // { dg-warning "useless cast" } + + int& m = n; + + (int&)(m); // { dg-warning "useless cast" } + const_cast(m); // { dg-warning "useless cast" } + static_cast(m); // { dg-warning "useless cast" } + reinterpret_cast(m); // { dg-warning "useless cast" } + + tmpl_f1(m); + + (int&)(n); // { dg-warning "useless cast" } + const_cast(n); // { dg-warning "useless cast" } + static_cast(n); // { dg-warning "useless cast" } + reinterpret_cast(n); // { dg-warning "useless cast" } + + tmpl_f2(n); + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + (int&&)(42); + static_cast(42); +#endif + + A a; + + (A)(a); // { dg-warning "useless cast" } + static_cast(a); // { dg-warning "useless cast" } + + (A*)(&a); // { dg-warning "useless cast" } + const_cast(&a); // { dg-warning "useless cast" } + static_cast(&a); // { dg-warning "useless cast" } + reinterpret_cast(&a); // { dg-warning "useless cast" } + dynamic_cast(&a); // { dg-warning "useless cast" } + + A& b = a; + + (A&)(b); // { dg-warning "useless cast" } + const_cast(b); // { dg-warning "useless cast" } + static_cast(b); // { dg-warning "useless cast" } + static_cast(b); // { dg-warning "useless cast" } + dynamic_cast(b); // { dg-warning "useless cast" } + + tmpl_f3(b); + + (A&)(a); // { dg-warning "useless cast" } + const_cast(a); // { dg-warning "useless cast" } + static_cast(a); // { dg-warning "useless cast" } + reinterpret_cast(a); // { dg-warning "useless cast" } + dynamic_cast(a); // { dg-warning "useless cast" } + + tmpl_f4(a); +} -- 2.7.4