typeck.c (build_static_cast): Don't allow static_casts that cast away constness.

* typeck.c (build_static_cast): Don't allow static_casts that cast
	away constness.
	(casts_away_constness_r): New function.
	(casts_away_constness): Likewise.

From-SVN: r27128
This commit is contained in:
Mark Mitchell 1999-05-24 15:26:25 +00:00 committed by Mark Mitchell
parent 671d0648e0
commit af7b990290
3 changed files with 139 additions and 0 deletions

View File

@ -1,5 +1,10 @@
1999-05-24 Mark Mitchell <mark@codesourcery.com>
* typeck.c (build_static_cast): Don't allow static_casts that cast
away constness.
(casts_away_constness_r): New function.
(casts_away_constness): Likewise.
* decl.c (lookup_tag): Remove code no longer needed after
name-lookup improvements.
* decl2.c (handle_class_head): Make error-recovery more robust.

View File

@ -59,6 +59,8 @@ static tree build_component_addr PROTO((tree, tree));
static tree qualify_type PROTO((tree, tree));
static tree get_delta_difference PROTO((tree, tree, int));
static int comp_cv_target_types PROTO((tree, tree, int));
static void casts_away_constness_r PROTO((tree *, tree *));
static int casts_away_constness PROTO ((tree, tree));
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
@ -5546,6 +5548,17 @@ build_static_cast (type, expr)
&& can_convert (intype, type))
ok = 1;
/* [expr.static.cast]
The static_cast operator shall not be used to cast away
constnes. */
if (ok && casts_away_constness (intype, type))
{
cp_error ("static_cast from `%T' to `%T' casts away constness",
intype, type);
return error_mark_node;
}
if (ok)
return build_c_cast (type, expr);
@ -7738,3 +7751,114 @@ cp_has_mutable_p (type)
return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
}
/* Subroutine of casts_away_constness. Make T1 and T2 point at
exemplar types such that casting T1 to T2 is casting away castness
if and only if there is no implicit conversion from T1 to T2. */
static void
casts_away_constness_r (t1, t2)
tree *t1;
tree *t2;
{
int quals1;
int quals2;
/* [expr.const.cast]
For multi-level pointer to members and multi-level mixed pointers
and pointers to members (conv.qual), the "member" aspect of a
pointer to member level is ignored when determining if a const
cv-qualifier has been cast away. */
if (TYPE_PTRMEM_P (*t1))
*t1 = build_pointer_type (TREE_TYPE (*t1));
if (TYPE_PTRMEM_P (*t2))
*t2 = build_pointer_type (TREE_TYPE (*t2));
/* [expr.const.cast]
For two pointer types:
X1 is T1cv1,1 * ... cv1,N * where T1 is not a pointer type
X2 is T2cv2,1 * ... cv2,M * where T2 is not a pointer type
K is min(N,M)
casting from X1 to X2 casts away constness if, for a non-pointer
type T there does not exist an implicit conversion (clause
_conv_) from:
Tcv1,(N-K+1) * cv1,(N-K+2) * ... cv1,N *
to
Tcv2,(M-K+1) * cv2,(M-K+2) * ... cv2,M *. */
if (TREE_CODE (*t1) != POINTER_TYPE
|| TREE_CODE (*t2) != POINTER_TYPE)
{
*t1 = cp_build_qualified_type (void_type_node,
CP_TYPE_QUALS (*t1));
*t2 = cp_build_qualified_type (void_type_node,
CP_TYPE_QUALS (*t2));
return;
}
quals1 = CP_TYPE_QUALS (*t1);
quals2 = CP_TYPE_QUALS (*t2);
*t1 = TREE_TYPE (*t1);
*t2 = TREE_TYPE (*t2);
casts_away_constness_r (t1, t2);
*t1 = build_pointer_type (*t1);
*t2 = build_pointer_type (*t2);
*t1 = cp_build_qualified_type (*t1, quals1);
*t2 = cp_build_qualified_type (*t2, quals2);
}
/* Returns non-zero if casting from TYPE1 to TYPE2 casts away
constness. */
static int
casts_away_constness (t1, t2)
tree t1;
tree t2;
{
if (TREE_CODE (t2) == REFERENCE_TYPE)
{
/* [expr.const.cast]
Casting from an lvalue of type T1 to an lvalue of type T2
using a reference cast casts away constness if a cast from an
rvalue of type "pointer to T1" to the type "pointer to T2"
casts away constness. */
t1 = (TREE_CODE (t1) == REFERENCE_TYPE
? TREE_TYPE (t1) : t1);
return casts_away_constness (build_pointer_type (t1),
build_pointer_type (TREE_TYPE (t2)));
}
if (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))
/* [expr.const.cast]
Casting from an rvalue of type "pointer to data member of X
of type T1" to the type "pointer to data member of Y of type
T2" casts away constness if a cast from an rvalue of type
"poitner to T1" to the type "pointer to T2" casts away
constness. */
return casts_away_constness (build_pointer_type (TREE_TYPE (t1)),
build_pointer_type (TREE_TYPE (t2)));
/* Casting away constness is only something that makes sense for
pointer or reference types. */
if (TREE_CODE (t1) != POINTER_TYPE
|| TREE_CODE (t2) != POINTER_TYPE)
return 0;
/* Top-level qualifiers don't matter. */
t1 = TYPE_MAIN_VARIANT (t1);
t2 = TYPE_MAIN_VARIANT (t2);
casts_away_constness_r (&t1, &t2);
if (!can_convert (t2, t1))
return 1;
return 0;
}

View File

@ -0,0 +1,10 @@
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
void f() {
int *i = 0;
const int *c = 0;
static_cast <const int *>(i);
static_cast <int *>(c); // ERROR - casts away constness
}