diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2012-03-19 15:51:25 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2012-03-19 15:51:25 +0000 |
commit | 04398fa84e070560d18d59ffe898bd46e8ddbeb7 (patch) | |
tree | eb01dfeebfb11d2b3e7c2be23d3c53d59ce5da9e /gcc/cp | |
parent | b199074d13335fef7220ac5372bab4a898131f65 (diff) | |
download | gcc-04398fa84e070560d18d59ffe898bd46e8ddbeb7.zip gcc-04398fa84e070560d18d59ffe898bd46e8ddbeb7.tar.gz gcc-04398fa84e070560d18d59ffe898bd46e8ddbeb7.tar.bz2 |
re PR c++/14710 (Warning about useless casts)
2012-03-16 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/14710
* doc/invoke.texi: Document -Wuseless-cast.
/c-family
2012-03-16 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/14710
* c.opt ([Wuseless-cast]): Add.
/cp
2012-03-16 Paolo Carlini <paolo.carlini@oracle.com>
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 <paolo.carlini@oracle.com>
PR c++/14710
* g++.dg/warn/Wuseless-cast.C: New.
From-SVN: r185524
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 21 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 11 | ||||
-rw-r--r-- | gcc/cp/tree.c | 11 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 55 |
6 files changed, 97 insertions, 18 deletions
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 <paolo.carlini@oracle.com> + + 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 <jason@redhat.com> 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); |