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>
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
on abstract violation.
......
......@@ -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
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
const. We would like to specify exactly what qualifiers are casted
away.
*/
static void
static bool
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
WARN_CAST_QUAL, we still want to issue a warning. */
if (cast == CAST_EXPR && !warn_cast_qual)
return;
return false;
if (!casts_away_constness (src_type, dest_type))
return;
return false;
switch (cast)
{
case CAST_EXPR:
warning (OPT_Wcast_qual,
"cast from type %qT to type %qT casts away qualifiers",
src_type, dest_type);
return;
if (complain & tf_warning)
warning (OPT_Wcast_qual,
"cast from type %qT to type %qT casts away qualifiers",
src_type, dest_type);
return false;
case STATIC_CAST_EXPR:
error ("static_cast from type %qT to type %qT casts away qualifiers",
src_type, dest_type);
return;
if (complain & tf_error)
error ("static_cast from type %qT to type %qT casts away qualifiers",
src_type, dest_type);
return true;
case REINTERPRET_CAST_EXPR:
error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
src_type, dest_type);
return;
if (complain & tf_error)
error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
src_type, dest_type);
return true;
default:
gcc_unreachable();
}
......@@ -5832,8 +5837,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
{
tree base;
if (!c_cast_p)
check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
if (!c_cast_p
&& check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
complain))
return error_mark_node;
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check,
NULL);
......@@ -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 (!c_cast_p)
check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
if (!c_cast_p
&& check_for_casting_away_constness (intype, type,
STATIC_CAST_EXPR,
complain))
return error_mark_node;
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,
&& VOID_TYPE_P (TREE_TYPE (intype))
&& TYPE_PTROB_P (type))
{
if (!c_cast_p)
check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
if (!c_cast_p
&& check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
complain))
return error_mark_node;
return build_nop (type, expr);
}
......@@ -6090,8 +6102,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
{
tree sexpr = expr;
if (!c_cast_p)
check_for_casting_away_constness (intype, type, REINTERPRET_CAST_EXPR);
if (!c_cast_p
&& check_for_casting_away_constness (intype, type,
REINTERPRET_CAST_EXPR,
complain))
return error_mark_node;
/* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT && warn_cast_align
&& (complain & tf_warning)
......@@ -6168,7 +6183,7 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain)
whether or not the conversion succeeded. */
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)
{
tree src_type;
......@@ -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 (complain)
if (complain & tf_error)
error ("invalid use of const_cast with type %qT, "
"which is not a pointer, "
"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,
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 "
"or reference to a function type", dst_type);
return error_mark_node;
......@@ -6221,7 +6236,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
reference_type = dst_type;
if (! real_lvalue_p (expr))
{
if (complain)
if (complain & tf_error)
error ("invalid const_cast of an rvalue of type %qT to type %qT",
src_type, dst_type);
return error_mark_node;
......@@ -6248,12 +6263,12 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
*valid_p = true;
/* This cast is actually a C-style cast. Issue a warning if
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)
{
expr = cp_build_addr_expr (expr,
complain ? tf_warning_or_error : tf_none);
expr = cp_build_addr_expr (expr, complain);
expr = build_nop (reference_type, expr);
return convert_from_reference (expr);
}
......@@ -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",
src_type, dst_type);
return error_mark_node;
......@@ -6293,7 +6308,7 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain)
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);
}
......@@ -6379,7 +6394,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
"cast to pointer from integer of different size");
/* 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);
if (valid_p)
return result;
......
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/sfinae7.C: New.
......
/* { 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)
{
......
/* { 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