aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-11-08 15:17:42 -0500
committerJason Merrill <jason@gcc.gnu.org>2010-11-08 15:17:42 -0500
commit9e115cec97350099177071bb16b3efcbbacc9445 (patch)
tree29e021e2fec06d40962f55e47d182c721d950eae /gcc/cp
parent1b2c3293fbe12f7fa3254af12e9d0ca98d89c5aa (diff)
downloadgcc-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/ChangeLog20
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/cp/cvt.c33
-rw-r--r--gcc/cp/decl.c1
-rw-r--r--gcc/cp/decl2.c1
-rw-r--r--gcc/cp/error.c4
-rw-r--r--gcc/cp/semantics.c32
-rw-r--r--gcc/cp/typeck.c51
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))