diff options
author | Jason Merrill <jason@redhat.com> | 2010-11-08 15:17:42 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-11-08 15:17:42 -0500 |
commit | 9e115cec97350099177071bb16b3efcbbacc9445 (patch) | |
tree | 29e021e2fec06d40962f55e47d182c721d950eae /gcc/cp | |
parent | 1b2c3293fbe12f7fa3254af12e9d0ca98d89c5aa (diff) | |
download | gcc-9e115cec97350099177071bb16b3efcbbacc9445.zip gcc-9e115cec97350099177071bb16b3efcbbacc9445.tar.gz gcc-9e115cec97350099177071bb16b3efcbbacc9445.tar.bz2 |
Correct conversion/overflow behavior.
* cvt.c (ignore_overflows): Move here from typeck.c.
(ocp_convert): Use it.
(cp_fold_convert): Use it. Don't call rvalue.
* typeck.c (build_static_cast_1): Don't use it. Do call rvalue.
* error.c (location_of): Handle expressions, too.
* class.c (check_bitfield_decl): Set input_location around call to
cxx_constant_value.
* semantics.c (cxx_eval_outermost_constant_expr): Don't
print the expression if it already had TREE_OVERFLOW set.
(reduced_constant_expression_p): Check TREE_OVERFLOW_P for C++98, too.
(verify_constant): Allow overflow with a permerror if we're
enforcing.
(cxx_eval_outermost_constant_expr): Use verify_constant.
(adjust_temp_type): Use cp_fold_convert.
* decl.c (build_enumerator): Don't call constant_expression_warning.
* decl2.c (grokbitfield): Likewise.
From-SVN: r166453
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cp/class.c | 3 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 33 | ||||
-rw-r--r-- | gcc/cp/decl.c | 1 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 1 | ||||
-rw-r--r-- | gcc/cp/error.c | 4 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 32 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 51 |
8 files changed, 85 insertions, 60 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1a40ee0..4f08ec3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,23 @@ +2010-11-08 Jason Merrill <jason@redhat.com> + + Correct conversion/overflow behavior. + * cvt.c (ignore_overflows): Move here from typeck.c. + (ocp_convert): Use it. + (cp_fold_convert): Use it. Don't call rvalue. + * typeck.c (build_static_cast_1): Don't use it. Do call rvalue. + * error.c (location_of): Handle expressions, too. + * class.c (check_bitfield_decl): Set input_location around call to + cxx_constant_value. + * semantics.c (cxx_eval_outermost_constant_expr): Don't + print the expression if it already had TREE_OVERFLOW set. + (reduced_constant_expression_p): Check TREE_OVERFLOW_P for C++98, too. + (verify_constant): Allow overflow with a permerror if we're + enforcing. + (cxx_eval_outermost_constant_expr): Use verify_constant. + (adjust_temp_type): Use cp_fold_convert. + * decl.c (build_enumerator): Don't call constant_expression_warning. + * decl2.c (grokbitfield): Likewise. + 2010-11-06 Jason Merrill <jason@redhat.com> PR c++/46348 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 435fa71..03951cf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2797,11 +2797,14 @@ check_bitfield_decl (tree field) } else { + location_t loc = input_location; /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ STRIP_NOPS (w); /* detect invalid field size. */ + input_location = DECL_SOURCE_LOCATION (field); w = cxx_constant_value (w); + input_location = loc; if (TREE_CODE (w) != INTEGER_CST) { diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index d2d6f4a..2f7823f 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -543,12 +543,35 @@ force_rvalue (tree expr) } -/* Fold away simple conversions, but make sure the result is an rvalue. */ +/* If EXPR and ORIG are INTEGER_CSTs, return a version of EXPR that has + TREE_OVERFLOW set only if it is set in ORIG. Otherwise, return EXPR + unchanged. */ + +static tree +ignore_overflows (tree expr, tree orig) +{ + if (TREE_CODE (expr) == INTEGER_CST + && TREE_CODE (orig) == INTEGER_CST + && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig)) + { + gcc_assert (!TREE_OVERFLOW (orig)); + /* Ensure constant sharing. */ + expr = build_int_cst_wide (TREE_TYPE (expr), + TREE_INT_CST_LOW (expr), + TREE_INT_CST_HIGH (expr)); + } + return expr; +} + +/* Fold away simple conversions, but make sure TREE_OVERFLOW is set + properly. */ tree cp_fold_convert (tree type, tree expr) { - return rvalue (fold_convert (type, expr)); + tree conv = fold_convert (type, expr); + conv = ignore_overflows (conv, expr); + return conv; } /* C++ conversions, preference to static cast conversions. */ @@ -661,6 +684,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); + tree converted; if (TREE_CODE (type) == ENUMERAL_TYPE) { @@ -705,7 +729,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags) if (code == BOOLEAN_TYPE) return cp_truthvalue_conversion (e); - return fold_if_not_in_template (convert_to_integer (type, e)); + converted = fold_if_not_in_template (convert_to_integer (type, e)); + + /* Ignore any integer overflow caused by the conversion. */ + return ignore_overflows (converted, e); } if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) return nullptr_node; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index fb5ca7f..c372840 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -11823,7 +11823,6 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) if (TREE_CODE (value) == INTEGER_CST) { value = perform_integral_promotions (value); - constant_expression_warning (value); } else { diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a805c6b..e00549e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1054,7 +1054,6 @@ grokbitfield (const cp_declarator *declarator, if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width))) error ("width of bit-field %qD has non-integral type %qT", value, TREE_TYPE (width)); - constant_expression_warning (width); DECL_INITIAL (value) = width; SET_DECL_C_BIT_FIELD (value); } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 6f60c06..1560fc6 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2469,7 +2469,9 @@ location_of (tree t) else if (TREE_CODE (t) == OVERLOAD) t = OVL_FUNCTION (t); - return DECL_SOURCE_LOCATION (t); + if (DECL_P (t)) + return DECL_SOURCE_LOCATION (t); + return EXPR_LOC_OR_HERE (t); } /* Now the interfaces from error et al to dump_type et al. Each takes an diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fd7da34..494247e7 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5789,7 +5789,7 @@ adjust_temp_type (tree type, tree temp) if (TREE_CODE (temp) == CONSTRUCTOR) return build_constructor (type, CONSTRUCTOR_ELTS (temp)); gcc_assert (SCALAR_TYPE_P (type)); - return fold_convert (type, temp); + return cp_fold_convert (type, temp); } /* Subroutine of cxx_eval_call_expression. @@ -6003,13 +6003,13 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, return result; } +/* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */ + bool reduced_constant_expression_p (tree t) { - /* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */ - if (cxx_dialect >= cxx0x && TREE_OVERFLOW_P (t)) - /* In C++0x, integer overflow makes this not a constant expression. - FIXME arithmetic overflow is different from conversion truncation */ + if (TREE_OVERFLOW_P (t)) + /* Integer overflow makes this not a constant expression. */ return false; /* FIXME are we calling this too much? */ return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE; @@ -6030,7 +6030,20 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p) if (!*non_constant_p && !reduced_constant_expression_p (t)) { if (!allow_non_constant) - error ("%qE is not a constant expression", t); + { + /* If T was already folded to a _CST with TREE_OVERFLOW set, + printing the folded constant isn't helpful. */ + if (TREE_OVERFLOW_P (t)) + { + permerror (input_location, "overflow in constant expression"); + /* If we're being permissive (and are in an enforcing + context), consider this constant. */ + if (flag_permissive) + return false; + } + else + error ("%q+E is not a constant expression", t); + } *non_constant_p = true; } return *non_constant_p; @@ -6895,12 +6908,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant) tree r = cxx_eval_constant_expression (NULL, t, allow_non_constant, false, &non_constant_p); - if (!non_constant_p && !reduced_constant_expression_p (r)) - { - if (!allow_non_constant) - error ("%qE is not a constant expression", t); - non_constant_p = true; - } + verify_constant (r, allow_non_constant, &non_constant_p); if (non_constant_p && !allow_non_constant) return error_mark_node; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 6a52fc4..cad8817 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5717,33 +5717,6 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, allow_inverse_p, c_cast_p, complain); } -/* If EXPR is an INTEGER_CST and ORIG is an arithmetic constant, return - a version of EXPR that has TREE_OVERFLOW set if it is set in ORIG. - Otherwise, return EXPR unchanged. */ - -static tree -ignore_overflows (tree expr, tree orig) -{ - if (TREE_CODE (expr) == INTEGER_CST - && CONSTANT_CLASS_P (orig) - && TREE_CODE (orig) != STRING_CST - && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig)) - { - if (!TREE_OVERFLOW (orig)) - /* Ensure constant sharing. */ - expr = build_int_cst_wide (TREE_TYPE (expr), - TREE_INT_CST_LOW (expr), - TREE_INT_CST_HIGH (expr)); - else - { - /* Avoid clobbering a shared constant. */ - expr = copy_node (expr); - TREE_OVERFLOW (expr) = TREE_OVERFLOW (orig); - } - } - return expr; -} - /* Perform a static_cast from EXPR to TYPE. When C_CAST_P is true, this static_cast is being attempted as one of the possible casts allowed by a C-style cast. (In that case, accessibility of base @@ -5757,7 +5730,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, { tree intype; tree result; - tree orig; /* Assume the cast is valid. */ *valid_p = true; @@ -5814,8 +5786,14 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, expr = build_base_path (MINUS_EXPR, build_address (expr), base, /*nonnull=*/false); /* Convert the pointer to a reference -- but then remember that - there are no expressions with reference type in C++. */ - return convert_from_reference (cp_fold_convert (type, expr)); + there are no expressions with reference type in C++. + + We call rvalue so that there's an actual tree code + (NON_LVALUE_EXPR) for the static_cast; otherwise, if the operand + is a variable with the same type, the conversion would get folded + away, leaving just the variable and causing lvalue_kind to give + the wrong answer. */ + return convert_from_reference (rvalue (cp_fold_convert (type, expr))); } /* "An lvalue of type cv1 T1 can be cast to type rvalue reference to @@ -5830,8 +5808,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, return convert_from_reference (expr); } - orig = expr; - /* Resolve overloaded address here rather than once in implicit_conversion and again in the inverse code below. */ if (TYPE_PTRMEMFUNC_P (type) && type_unknown_p (expr)) @@ -5852,9 +5828,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, { result = convert_from_reference (result); - /* Ignore any integer overflow caused by the cast. */ - result = ignore_overflows (result, orig); - /* [expr.static.cast] If T is a reference type, the result is an lvalue; otherwise, @@ -5894,13 +5867,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - { - expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); - - /* Ignore any integer overflow caused by the cast. */ - expr = ignore_overflows (expr, orig); - return expr; - } + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) |