From 3f89235e9d26a56e848d99a812177e149d87df3c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 7 Apr 2011 17:47:38 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 6 + gcc/cp/typeck.c | 83 +++++---- gcc/testsuite/ChangeLog | 4 + .../Wcast-qual-1.c} | 5 - gcc/testsuite/gcc.dg/cast-qual-3.c | 167 ------------------ 5 files changed, 59 insertions(+), 206 deletions(-) rename gcc/testsuite/{g++.dg/warn/Wcast-qual2.C => c-c++-common/Wcast-qual-1.c} (96%) delete mode 100644 gcc/testsuite/gcc.dg/cast-qual-3.c diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0d9251ce689..26159e02d6a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2011-04-07 Jason Merrill + 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. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 71cfd8c6cf0..8e3796e2757 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7aace9fd007..288bd1feb9d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2011-04-07 Jason Merrill + * 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. diff --git a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C b/gcc/testsuite/c-c++-common/Wcast-qual-1.c similarity index 96% rename from gcc/testsuite/g++.dg/warn/Wcast-qual2.C rename to gcc/testsuite/c-c++-common/Wcast-qual-1.c index 88fdcfb38f5..640e4f0b683 100644 --- a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C +++ b/gcc/testsuite/c-c++-common/Wcast-qual-1.c @@ -1,11 +1,6 @@ /* { 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) { diff --git a/gcc/testsuite/gcc.dg/cast-qual-3.c b/gcc/testsuite/gcc.dg/cast-qual-3.c deleted file mode 100644 index 88fdcfb38f5..00000000000 --- a/gcc/testsuite/gcc.dg/cast-qual-3.c +++ /dev/null @@ -1,167 +0,0 @@ -/* { 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; -} -- 2.30.2