}
}
-/*
- 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)
{
}
}
+/* 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
/* 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
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;
}
/* 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
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;
}
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);
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;
}
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;
}
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))
--- /dev/null
+// { 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));
+}