Commit 04398fa8 by Paolo Carlini Committed by Paolo Carlini

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
parent b199074d
2012-03-19 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/14710
* doc/invoke.texi: Document -Wuseless-cast.
2012-03-19 Eric Botcazou <ebotcazou@adacore.com>
* tree.def (REALPART_EXPR, IMAGPART_EXPR, VIEW_CONVERT_EXPR): Move.
......
2012-03-19 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/14710
* c.opt ([Wuseless-cast]): Add.
2012-03-16 Richard Guenther <rguenther@suse.de>
* c-pretty-print.c (pp_c_initializer_list): Adjust.
......
......@@ -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++)
......
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
......
/* 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);
......
......@@ -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:
......
/* 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
......
/* 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. */
......
......@@ -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);
......
......@@ -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
......
// { dg-options "-Wuseless-cast" }
template<typename T>
void tmpl_f1(T& t)
{
(int)(t);
static_cast<int>(t);
reinterpret_cast<int>(t);
(int*)(&t);
const_cast<int*>(&t);
static_cast<int*>(&t);
reinterpret_cast<int*>(&t);
(int&)(t);
const_cast<int&>(t);
static_cast<int&>(t);
reinterpret_cast<int&>(t);
}
template<typename T>
void tmpl_f2(T t)
{
(int&)(t);
const_cast<int&>(t);
static_cast<int&>(t);
reinterpret_cast<int&>(t);
}
struct A { };
template<typename T>
void tmpl_f3(T& t)
{
(A)(t);
static_cast<A>(t);
(A*)(&t);
const_cast<A*>(&t);
static_cast<A*>(&t);
reinterpret_cast<A*>(&t);
dynamic_cast<A*>(&t);
(A&)(t);
const_cast<A&>(t);
static_cast<A&>(t);
reinterpret_cast<A&>(t);
dynamic_cast<A&>(t);
}
template<typename T>
void tmpl_f4(T t)
{
(A&)(t);
const_cast<A&>(t);
static_cast<A&>(t);
reinterpret_cast<A&>(t);
dynamic_cast<A&>(t);
}
void f()
{
int n;
(int)(n); // { dg-warning "useless cast" }
static_cast<int>(n); // { dg-warning "useless cast" }
reinterpret_cast<int>(n); // { dg-warning "useless cast" }
(int*)(&n); // { dg-warning "useless cast" }
const_cast<int*>(&n); // { dg-warning "useless cast" }
static_cast<int*>(&n); // { dg-warning "useless cast" }
reinterpret_cast<int*>(&n); // { dg-warning "useless cast" }
int& m = n;
(int&)(m); // { dg-warning "useless cast" }
const_cast<int&>(m); // { dg-warning "useless cast" }
static_cast<int&>(m); // { dg-warning "useless cast" }
reinterpret_cast<int&>(m); // { dg-warning "useless cast" }
tmpl_f1(m);
(int&)(n); // { dg-warning "useless cast" }
const_cast<int&>(n); // { dg-warning "useless cast" }
static_cast<int&>(n); // { dg-warning "useless cast" }
reinterpret_cast<int&>(n); // { dg-warning "useless cast" }
tmpl_f2(n);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
(int&&)(42);
static_cast<int&&>(42);
#endif
A a;
(A)(a); // { dg-warning "useless cast" }
static_cast<A>(a); // { dg-warning "useless cast" }
(A*)(&a); // { dg-warning "useless cast" }
const_cast<A*>(&a); // { dg-warning "useless cast" }
static_cast<A*>(&a); // { dg-warning "useless cast" }
reinterpret_cast<A*>(&a); // { dg-warning "useless cast" }
dynamic_cast<A*>(&a); // { dg-warning "useless cast" }
A& b = a;
(A&)(b); // { dg-warning "useless cast" }
const_cast<A&>(b); // { dg-warning "useless cast" }
static_cast<A&>(b); // { dg-warning "useless cast" }
static_cast<A&>(b); // { dg-warning "useless cast" }
dynamic_cast<A&>(b); // { dg-warning "useless cast" }
tmpl_f3(b);
(A&)(a); // { dg-warning "useless cast" }
const_cast<A&>(a); // { dg-warning "useless cast" }
static_cast<A&>(a); // { dg-warning "useless cast" }
reinterpret_cast<A&>(a); // { dg-warning "useless cast" }
dynamic_cast<A&>(a); // { dg-warning "useless cast" }
tmpl_f4(a);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment