Commit d4a760d8 by Jonathan Wakely Committed by Jonathan Wakely

PR c++/80544 strip cv-quals from cast results

gcc/cp:

	PR c++/80544
	* tree.c (reshape_init): Use unqualified type for direct enum init.
	* typeck.c (maybe_warn_about_cast_ignoring_quals): New.
	(build_static_cast_1, build_reinterpret_cast_1): Strip cv-quals from
	non-class destination types.
	(build_const_cast_1): Strip cv-quals from destination types.
	(build_static_cast, build_reinterpret_cast, build_const_cast)
	(cp_build_c_cast): Add calls to maybe_warn_about_cast_ignoring_quals.

gcc/testsuite:

	PR c++/80544
	* g++.dg/expr/cast11.C: New test.

From-SVN: r248432
parent 3cd211af
2017-05-24 Jonathan Wakely <jwakely@redhat.com>
PR c++/80544
* tree.c (reshape_init): Use unqualified type for direct enum init.
* typeck.c (maybe_warn_about_cast_ignoring_quals): New.
(build_static_cast_1, build_reinterpret_cast_1): Strip cv-quals from
non-class destination types.
(build_const_cast_1): Strip cv-quals from destination types.
(build_static_cast, build_reinterpret_cast, build_const_cast)
(cp_build_c_cast): Add calls to maybe_warn_about_cast_ignoring_quals.
2017-05-24 Martin Sebor <msebor@redhat.com> 2017-05-24 Martin Sebor <msebor@redhat.com>
PR c/80731 PR c/80731
......
...@@ -6043,6 +6043,7 @@ reshape_init (tree type, tree init, tsubst_flags_t complain) ...@@ -6043,6 +6043,7 @@ reshape_init (tree type, tree init, tsubst_flags_t complain)
if (is_direct_enum_init (type, init)) if (is_direct_enum_init (type, init))
{ {
tree elt = CONSTRUCTOR_ELT (init, 0)->value; tree elt = CONSTRUCTOR_ELT (init, 0)->value;
type = cv_unqualified (type);
if (check_narrowing (ENUM_UNDERLYING_TYPE (type), elt, complain)) if (check_narrowing (ENUM_UNDERLYING_TYPE (type), elt, complain))
return cp_build_c_cast (type, elt, tf_warning_or_error); return cp_build_c_cast (type, elt, tf_warning_or_error);
else else
......
...@@ -6655,9 +6655,7 @@ check_for_casting_away_constness (tree src_type, tree dest_type, ...@@ -6655,9 +6655,7 @@ check_for_casting_away_constness (tree src_type, tree dest_type,
} }
} }
/* /* Warns if the cast from expression EXPR to type TYPE is useless. */
Warns if the cast from expression EXPR to type TYPE is useless.
*/
void void
maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain) maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain)
{ {
...@@ -6673,6 +6671,20 @@ maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -6673,6 +6671,20 @@ maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain)
} }
} }
/* Warns if the cast ignores cv-qualifiers on TYPE. */
void
maybe_warn_about_cast_ignoring_quals (tree type, tsubst_flags_t complain)
{
if (warn_ignored_qualifiers
&& complain & tf_warning
&& !CLASS_TYPE_P (type)
&& (cp_type_quals (type) & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE)))
{
warning (OPT_Wignored_qualifiers, "type qualifiers ignored on cast "
"result type");
}
}
/* Convert EXPR (an expression with pointer-to-member type) to TYPE /* Convert EXPR (an expression with pointer-to-member type) to TYPE
(another pointer-to-member type in the same hierarchy) and return (another pointer-to-member type in the same hierarchy) and return
the converted expression. If ALLOW_INVERSE_P is permitted, a the converted expression. If ALLOW_INVERSE_P is permitted, a
...@@ -6746,6 +6758,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -6746,6 +6758,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
/* Save casted types in the function's used types hash table. */ /* Save casted types in the function's used types hash table. */
used_types_insert (type); used_types_insert (type);
/* A prvalue of non-class type is cv-unqualified. */
if (!CLASS_TYPE_P (type))
type = cv_unqualified (type);
/* [expr.static.cast] /* [expr.static.cast]
An lvalue of type "cv1 B", where B is a class type, can be cast An lvalue of type "cv1 B", where B is a class type, can be cast
...@@ -7035,7 +7051,10 @@ build_static_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -7035,7 +7051,10 @@ build_static_cast (tree type, tree expr, tsubst_flags_t complain)
if (valid_p) if (valid_p)
{ {
if (result != error_mark_node) if (result != error_mark_node)
{
maybe_warn_about_useless_cast (type, expr, complain); maybe_warn_about_useless_cast (type, expr, complain);
maybe_warn_about_cast_ignoring_quals (type, complain);
}
return result; return result;
} }
...@@ -7108,6 +7127,10 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -7108,6 +7127,10 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
/* Save casted types in the function's used types hash table. */ /* Save casted types in the function's used types hash table. */
used_types_insert (type); used_types_insert (type);
/* A prvalue of non-class type is cv-unqualified. */
if (!CLASS_TYPE_P (type))
type = cv_unqualified (type);
/* [expr.reinterpret.cast] /* [expr.reinterpret.cast]
An lvalue expression of type T1 can be cast to the type An lvalue expression of type T1 can be cast to the type
"reference to T2" if an expression of type "pointer to T1" can be "reference to T2" if an expression of type "pointer to T1" can be
...@@ -7289,7 +7312,10 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -7289,7 +7312,10 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain)
r = build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false, r = build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false,
/*valid_p=*/NULL, complain); /*valid_p=*/NULL, complain);
if (r != error_mark_node) if (r != error_mark_node)
{
maybe_warn_about_useless_cast (type, expr, complain); maybe_warn_about_useless_cast (type, expr, complain);
maybe_warn_about_cast_ignoring_quals (type, complain);
}
return r; return r;
} }
...@@ -7335,6 +7361,9 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain, ...@@ -7335,6 +7361,9 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
return error_mark_node; return error_mark_node;
} }
/* A prvalue of non-class type is cv-unqualified. */
dst_type = cv_unqualified (dst_type);
/* Save casted types in the function's used types hash table. */ /* Save casted types in the function's used types hash table. */
used_types_insert (dst_type); used_types_insert (dst_type);
...@@ -7455,7 +7484,10 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -7455,7 +7484,10 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain)
r = 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) if (r != error_mark_node)
{
maybe_warn_about_useless_cast (type, expr, complain); maybe_warn_about_useless_cast (type, expr, complain);
maybe_warn_about_cast_ignoring_quals (type, complain);
}
return r; return r;
} }
...@@ -7558,7 +7590,10 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -7558,7 +7590,10 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
if (valid_p) if (valid_p)
{ {
if (result != error_mark_node) if (result != error_mark_node)
{
maybe_warn_about_useless_cast (type, value, complain); maybe_warn_about_useless_cast (type, value, complain);
maybe_warn_about_cast_ignoring_quals (type, complain);
}
return result; return result;
} }
...@@ -7579,6 +7614,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -7579,6 +7614,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
tree result_type; tree result_type;
maybe_warn_about_useless_cast (type, value, complain); maybe_warn_about_useless_cast (type, value, complain);
maybe_warn_about_cast_ignoring_quals (type, complain);
/* Non-class rvalues always have cv-unqualified type. */ /* Non-class rvalues always have cv-unqualified type. */
if (!CLASS_TYPE_P (type)) if (!CLASS_TYPE_P (type))
......
2017-05-24 Jonathan Wakely <jwakely@redhat.com>
PR c++/80544
* g++.dg/expr/cast11.C: New test.
2017-05-24 Martin Sebor <msebor@redhat.com> 2017-05-24 Martin Sebor <msebor@redhat.com>
PR c/80731 PR c/80731
......
// { dg-do compile { target c++11 } }
// { dg-options "-Wignored-qualifiers" }
// c++/80544 cast expressions returned cv-qualified prvalues
template<typename T> void f(T&&) { }
template<typename T> void f(T const&&) = delete;
template<typename T> void g(T&&) = delete;
template<typename T> void g(T const&&) { }
struct B { int i; const char c; } b = {};
void f1()
{
int i = 0;
f((long const)i); // { dg-warning "qualifiers ignored" }
f((int* const)&i); // { dg-warning "qualifiers ignored" }
f((int const* const)&i); // { dg-warning "qualifiers ignored" }
f((long* const)&i); // { dg-warning "qualifiers ignored" }
f(static_cast<long const>(i)); // { dg-warning "qualifiers ignored" }
f(reinterpret_cast<long const>(&i)); // { dg-warning "qualifiers ignored" }
f(static_cast<int* const>(&i)); // { dg-warning "qualifiers ignored" }
f(const_cast<int* const>(&i)); // { dg-warning "qualifiers ignored" }
f(reinterpret_cast<long* const>(&i)); // { dg-warning "qualifiers ignored" }
using ptrmem = int B::*;
f(static_cast<ptrmem const>(&B::i)); // { dg-warning "qualifiers ignored" }
f(const_cast<ptrmem const>(&B::i)); // { dg-warning "qualifiers ignored" }
f(reinterpret_cast<ptrmem const>(&B::i)); // { dg-warning "qualifiers ignored" }
// No warnings, not a cv-qualified type:
using ptrmem2 = const char B::*;
f(static_cast<ptrmem2>(&B::c));
f(const_cast<ptrmem2>(&B::c));
f(reinterpret_cast<ptrmem2>(&B::c));
// prvalue of class type can have cv-quals:
g(static_cast<const B>(b));
}
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