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
This commit is contained in:
Jonathan Wakely 2017-05-24 23:16:59 +01:00 committed by Jonathan Wakely
parent 3cd211af99
commit d4a760d8c4
5 changed files with 101 additions and 7 deletions

View File

@ -1,3 +1,14 @@
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>
PR c/80731

View File

@ -6043,6 +6043,7 @@ reshape_init (tree type, tree init, tsubst_flags_t complain)
if (is_direct_enum_init (type, init))
{
tree elt = CONSTRUCTOR_ELT (init, 0)->value;
type = cv_unqualified (type);
if (check_narrowing (ENUM_UNDERLYING_TYPE (type), elt, complain))
return cp_build_c_cast (type, elt, tf_warning_or_error);
else

View File

@ -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
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
(another pointer-to-member type in the same hierarchy) and return
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,
/* Save casted types in the function's used types hash table. */
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]
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)
if (valid_p)
{
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;
}
@ -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. */
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]
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
@ -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,
/*valid_p=*/NULL, complain);
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;
}
@ -7335,6 +7361,9 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
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. */
used_types_insert (dst_type);
@ -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);
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;
}
@ -7558,7 +7590,10 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
if (valid_p)
{
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;
}
@ -7579,6 +7614,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
tree result_type;
maybe_warn_about_useless_cast (type, value, complain);
maybe_warn_about_cast_ignoring_quals (type, complain);
/* Non-class rvalues always have cv-unqualified type. */
if (!CLASS_TYPE_P (type))

View File

@ -1,3 +1,8 @@
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>
PR c/80731

View File

@ -0,0 +1,41 @@
// { 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));
}