Commit 3f89235e by Jason Merrill Committed by Jason Merrill

re PR c++/48450 ([C++0x][SFINAE] Hard errors with static_cast expressions)

	PR c++/48450
	* typeck.c (check_for_casting_away_constness): Take complain.
	(build_static_cast_1, build_reinterpret_cast_1): Pass it.
	(build_const_cast_1): Pass it.  Take full complain parm.
	(build_const_cast, cp_build_c_cast): Adjust.

From-SVN: r172145
parent 3cf0ca23
2011-04-07 Jason Merrill <jason@redhat.com> 2011-04-07 Jason Merrill <jason@redhat.com>
PR c++/48450
* typeck.c (check_for_casting_away_constness): Take complain.
(build_static_cast_1, build_reinterpret_cast_1): Pass it.
(build_const_cast_1): Pass it. Take full complain parm.
(build_const_cast, cp_build_c_cast): Adjust.
* tree.c (build_aggr_init_expr): Always return error_mark_node * tree.c (build_aggr_init_expr): Always return error_mark_node
on abstract violation. on abstract violation.
......
...@@ -5579,42 +5579,47 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain) ...@@ -5579,42 +5579,47 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
} }
/* Issue a diagnostic message if casting from SRC_TYPE to DEST_TYPE /* Issue a diagnostic message if casting from SRC_TYPE to DEST_TYPE
casts away constness. CAST gives the type of cast. casts away constness. CAST gives the type of cast. Returns true
if the cast is ill-formed, false if it is well-formed.
??? This function warns for casting away any qualifier not just ??? This function warns for casting away any qualifier not just
const. We would like to specify exactly what qualifiers are casted const. We would like to specify exactly what qualifiers are casted
away. away.
*/ */
static void static bool
check_for_casting_away_constness (tree src_type, tree dest_type, check_for_casting_away_constness (tree src_type, tree dest_type,
enum tree_code cast) enum tree_code cast, tsubst_flags_t complain)
{ {
/* C-style casts are allowed to cast away constness. With /* C-style casts are allowed to cast away constness. With
WARN_CAST_QUAL, we still want to issue a warning. */ WARN_CAST_QUAL, we still want to issue a warning. */
if (cast == CAST_EXPR && !warn_cast_qual) if (cast == CAST_EXPR && !warn_cast_qual)
return; return false;
if (!casts_away_constness (src_type, dest_type)) if (!casts_away_constness (src_type, dest_type))
return; return false;
switch (cast) switch (cast)
{ {
case CAST_EXPR: case CAST_EXPR:
warning (OPT_Wcast_qual, if (complain & tf_warning)
"cast from type %qT to type %qT casts away qualifiers", warning (OPT_Wcast_qual,
src_type, dest_type); "cast from type %qT to type %qT casts away qualifiers",
return; src_type, dest_type);
return false;
case STATIC_CAST_EXPR: case STATIC_CAST_EXPR:
error ("static_cast from type %qT to type %qT casts away qualifiers", if (complain & tf_error)
src_type, dest_type); error ("static_cast from type %qT to type %qT casts away qualifiers",
return; src_type, dest_type);
return true;
case REINTERPRET_CAST_EXPR: case REINTERPRET_CAST_EXPR:
error ("reinterpret_cast from type %qT to type %qT casts away qualifiers", if (complain & tf_error)
src_type, dest_type); error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
return; src_type, dest_type);
return true;
default: default:
gcc_unreachable(); gcc_unreachable();
} }
...@@ -5832,8 +5837,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -5832,8 +5837,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
{ {
tree base; tree base;
if (!c_cast_p) if (!c_cast_p
check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR); && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
complain))
return error_mark_node;
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check, c_cast_p ? ba_unique : ba_check,
NULL); NULL);
...@@ -5868,10 +5875,13 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -5868,10 +5875,13 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
} }
if (can_convert (t1, t2) || can_convert (t2, t1)) if (can_convert (t1, t2) || can_convert (t2, t1))
{ {
if (!c_cast_p) if (!c_cast_p
check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR); && check_for_casting_away_constness (intype, type,
STATIC_CAST_EXPR,
complain))
return error_mark_node;
return convert_ptrmem (type, expr, /*allow_inverse_p=*/1, return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
c_cast_p, tf_warning_or_error); c_cast_p, complain);
} }
} }
...@@ -5885,8 +5895,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -5885,8 +5895,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
&& VOID_TYPE_P (TREE_TYPE (intype)) && VOID_TYPE_P (TREE_TYPE (intype))
&& TYPE_PTROB_P (type)) && TYPE_PTROB_P (type))
{ {
if (!c_cast_p) if (!c_cast_p
check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR); && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
complain))
return error_mark_node;
return build_nop (type, expr); return build_nop (type, expr);
} }
...@@ -6090,8 +6102,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -6090,8 +6102,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
{ {
tree sexpr = expr; tree sexpr = expr;
if (!c_cast_p) if (!c_cast_p
check_for_casting_away_constness (intype, type, REINTERPRET_CAST_EXPR); && check_for_casting_away_constness (intype, type,
REINTERPRET_CAST_EXPR,
complain))
return error_mark_node;
/* Warn about possible alignment problems. */ /* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT && warn_cast_align if (STRICT_ALIGNMENT && warn_cast_align
&& (complain & tf_warning) && (complain & tf_warning)
...@@ -6168,7 +6183,7 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -6168,7 +6183,7 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain)
whether or not the conversion succeeded. */ whether or not the conversion succeeded. */
static tree static tree
build_const_cast_1 (tree dst_type, tree expr, bool complain, build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
bool *valid_p) bool *valid_p)
{ {
tree src_type; tree src_type;
...@@ -6187,7 +6202,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, ...@@ -6187,7 +6202,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
if (!POINTER_TYPE_P (dst_type) && !TYPE_PTRMEM_P (dst_type)) if (!POINTER_TYPE_P (dst_type) && !TYPE_PTRMEM_P (dst_type))
{ {
if (complain) if (complain & tf_error)
error ("invalid use of const_cast with type %qT, " error ("invalid use of const_cast with type %qT, "
"which is not a pointer, " "which is not a pointer, "
"reference, nor a pointer-to-data-member type", dst_type); "reference, nor a pointer-to-data-member type", dst_type);
...@@ -6196,7 +6211,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, ...@@ -6196,7 +6211,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE) if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE)
{ {
if (complain) if (complain & tf_error)
error ("invalid use of const_cast with type %qT, which is a pointer " error ("invalid use of const_cast with type %qT, which is a pointer "
"or reference to a function type", dst_type); "or reference to a function type", dst_type);
return error_mark_node; return error_mark_node;
...@@ -6221,7 +6236,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, ...@@ -6221,7 +6236,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
reference_type = dst_type; reference_type = dst_type;
if (! real_lvalue_p (expr)) if (! real_lvalue_p (expr))
{ {
if (complain) if (complain & tf_error)
error ("invalid const_cast of an rvalue of type %qT to type %qT", error ("invalid const_cast of an rvalue of type %qT to type %qT",
src_type, dst_type); src_type, dst_type);
return error_mark_node; return error_mark_node;
...@@ -6248,12 +6263,12 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, ...@@ -6248,12 +6263,12 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
*valid_p = true; *valid_p = true;
/* This cast is actually a C-style cast. Issue a warning if /* This cast is actually a C-style cast. Issue a warning if
the user is making a potentially unsafe cast. */ the user is making a potentially unsafe cast. */
check_for_casting_away_constness (src_type, dst_type, CAST_EXPR); check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
complain);
} }
if (reference_type) if (reference_type)
{ {
expr = cp_build_addr_expr (expr, expr = cp_build_addr_expr (expr, complain);
complain ? tf_warning_or_error : tf_none);
expr = build_nop (reference_type, expr); expr = build_nop (reference_type, expr);
return convert_from_reference (expr); return convert_from_reference (expr);
} }
...@@ -6270,7 +6285,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, ...@@ -6270,7 +6285,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
} }
} }
if (complain) if (complain & tf_error)
error ("invalid const_cast from type %qT to type %qT", error ("invalid const_cast from type %qT to type %qT",
src_type, dst_type); src_type, dst_type);
return error_mark_node; return error_mark_node;
...@@ -6293,7 +6308,7 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -6293,7 +6308,7 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain)
return convert_from_reference (t); return convert_from_reference (t);
} }
return build_const_cast_1 (type, expr, complain & tf_error, return build_const_cast_1 (type, expr, complain,
/*valid_p=*/NULL); /*valid_p=*/NULL);
} }
...@@ -6379,7 +6394,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) ...@@ -6379,7 +6394,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
"cast to pointer from integer of different size"); "cast to pointer from integer of different size");
/* A C-style cast can be a const_cast. */ /* A C-style cast can be a const_cast. */
result = build_const_cast_1 (type, value, /*complain=*/false, result = build_const_cast_1 (type, value, complain & tf_warning,
&valid_p); &valid_p);
if (valid_p) if (valid_p)
return result; return result;
......
2011-04-07 Jason Merrill <jason@redhat.com> 2011-04-07 Jason Merrill <jason@redhat.com>
* c-c++-common/Wcast-qual-1.c: Move here from...
* gcc.dg/cast-qual-3.c: ...here, and...
* g++.dg/warn/Wcast-qual2.C: ...here.
* g++.dg/cpp0x/sfinae8.C: New. * g++.dg/cpp0x/sfinae8.C: New.
* g++.dg/cpp0x/sfinae7.C: New. * g++.dg/cpp0x/sfinae7.C: New.
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-Wcast-qual" } */ /* { dg-options "-Wcast-qual" } */
/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
duals. they are intended to show that gcc -Wcast-qual and g++
-Wcast-qual emit warnings in the same cases. If you change this
file, please also change the other one. */
void void
f1 (void *bar) f1 (void *bar)
{ {
......
/* { dg-do compile } */
/* { dg-options "-Wcast-qual" } */
/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
duals. they are intended to show that gcc -Wcast-qual and g++
-Wcast-qual emit warnings in the same cases. If you change this
file, please also change the other one. */
void
f1 (void *bar)
{
const void *p1 = (const void *) bar;
const char *p2 = (const char *) bar;
const void **p3 = (const void **) bar;
const char **p4 = (const char **) bar;
const void * const *p5 = (const void * const *) bar;
const char * const *p6 = (const char * const *) bar;
void * const *p7 = (void * const *) bar;
char * const *p8 = (char * const *) bar;
const void ***p9 = (const void ***) bar;
const char ***p10 = (const char ***) bar;
void * const **p11 = (void * const **) bar;
char * const **p12 = (char * const **) bar;
void ** const *p13 = (void ** const *) bar;
char ** const *p14 = (char ** const *) bar;
const void * const **p15 = (const void * const **) bar;
const char * const **p16 = (const char * const **) bar;
const void ** const *p17 = (const void ** const *) bar;
const char ** const *p18 = (const char ** const *) bar;
void * const * const * p19 = (void * const * const *) bar;
char * const * const * p20 = (char * const * const *) bar;
const void * const * const *p21 = (const void * const * const *) bar;
const char * const * const *p22 = (const char * const * const *) bar;
}
void
f2 (void **bar)
{
const void *p1 = (const void *) bar;
const char *p2 = (const char *) bar;
const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
const char **p4 = (const char **) bar;
const void * const *p5 = (const void * const *) bar;
const char * const *p6 = (const char * const *) bar;
void * const *p7 = (void * const *) bar;
char * const *p8 = (char * const *) bar;
const void ***p9 = (const void ***) bar;
const char ***p10 = (const char ***) bar;
void * const **p11 = (void * const **) bar;
char * const **p12 = (char * const **) bar;
void ** const *p13 = (void ** const *) bar;
char ** const *p14 = (char ** const *) bar;
const void * const **p15 = (const void * const **) bar;
const char * const **p16 = (const char * const **) bar;
const void ** const *p17 = (const void ** const *) bar;
const char ** const *p18 = (const char ** const *) bar;
void * const * const * p19 = (void * const * const *) bar;
char * const * const * p20 = (char * const * const *) bar;
const void * const * const *p21 = (const void * const * const *) bar;
const char * const * const *p22 = (const char * const * const *) bar;
}
void
f3 (void ***bar)
{
const void *p1 = (const void *) bar;
const char *p2 = (const char *) bar;
const void **p3 = (const void **) bar;
const char **p4 = (const char **) bar;
const void * const *p5 = (const void * const *) bar;
const char * const *p6 = (const char * const *) bar;
void * const *p7 = (void * const *) bar;
char * const *p8 = (char * const *) bar;
const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
const char ***p10 = (const char ***) bar;
void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
char * const **p12 = (char * const **) bar;
void ** const *p13 = (void ** const *) bar;
char ** const *p14 = (char ** const *) bar;
const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
const char * const **p16 = (const char * const **) bar;
const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
const char ** const *p18 = (const char ** const *) bar;
void * const * const * p19 = (void * const * const *) bar;
char * const * const * p20 = (char * const * const *) bar;
const void * const * const *p21 = (const void * const * const *) bar;
const char * const * const *p22 = (const char * const * const *) bar;
}
void
f4 (void * const **bar)
{
const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
void * const **p11 = (void * const **) bar;
void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
void * const * const * p19 = (void * const * const *) bar;
const void * const * const *p21 = (const void * const * const *) bar;
}
void
f5 (char ***bar)
{
volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
volatile char * const * const * p19 = (volatile char * const * const *) bar;
volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
}
void
f6 (char ***bar)
{
const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
char * volatile * const *p13 = (char * volatile * const *) bar;
const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
char * volatile const * const * p19 = (char * volatile const * const *) bar;
const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
}
void
f7 (char ***bar)
{
const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
char ** volatile const *p13 = (char ** volatile const *) bar;
const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
char * const * volatile const * p19 = (char * const * volatile const *) bar;
const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
}
typedef int (intfn) (int);
typedef intfn *pintfn;
typedef const intfn *constfn;
void
f8 (constfn ***bar)
{
const constfn *p1 = (const constfn *) bar;
const pintfn *p2 = (const pintfn *) bar;
const constfn **p3 = (const constfn **) bar;
const pintfn **p4 = (const pintfn **) bar;
const constfn * const *p5 = (const constfn * const *) bar;
const pintfn * const *p6 = (const pintfn * const *) bar;
constfn * const *p7 = (constfn * const *) bar;
pintfn * const *p8 = (pintfn * const *) bar;
const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
constfn ** const *p13 = (constfn ** const *) bar;
pintfn ** const *p14 = (pintfn ** const *) bar;
const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
constfn * const * const * p19 = (constfn * const * const *) bar;
pintfn * const * const * p20 = (pintfn * const * const *) bar;
const constfn * const * const *p21 = (const constfn * const * const *) bar;
const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
}
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