@@ -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)
{
@@ -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;
@@ -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
{
@@ -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);
}
@@ -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
@@ -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;
@@ -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))
new file mode 100644
@@ -0,0 +1,8 @@
+#include <limits.h>
+
+enum E {
+ A = (unsigned char)-1, /* OK */
+ B = (signed char)UCHAR_MAX, /* implementation-defined */
+ C = INT_MAX+1, /* undefined (C)/ill-formed (C++) { dg-message "" } */
+ D = UINT_MAX+1 /* OK */
+};
@@ -1,7 +1,7 @@
/* Test for diagnostics for constant overflow. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-fpermissive" } */
#include <limits.h>
@@ -19,8 +19,10 @@ enum e {
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
+ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
/* Again, overflow in evaluated subexpression. */
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
+ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 24 } */
/* A cast does not constitute overflow in conversion. */
E7 = (char) INT_MAX
};
@@ -29,6 +31,7 @@ struct s {
int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
+ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 33 } */
};
void
@@ -49,10 +52,10 @@ void *n = 0;
constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
-/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 51 } */
+/* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 54 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 53 } */
-void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } 55 } */
+/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 56 } */
+void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
void
g (int i)
@@ -62,6 +65,7 @@ g (int i)
case 0 * (1/0): /* { dg-warning "division by zero" } */
;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
+ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 67 } */
;
}
}
@@ -57,7 +57,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */
-void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } 60 } */
+void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
void
g (int i)
@@ -11,7 +11,7 @@ enum e {
E1 = UINT_MAX + 1,
/* Overflow in an unevaluated part of an expression is OK (example
in the standard). */
- E2 = 2 || 1 / 0, /* { dg-bogus "warning: division by zero" "" { xfail *-*-* } 14 } */
+ E2 = 2 || 1 / 0, /* { dg-bogus "warning: division by zero" "" { xfail *-*-* } } */
E3 = 1 / 0, /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E3' is not an integer constant|not a constant expression" "enum error" { target *-*-* } 15 } */
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
@@ -20,9 +20,11 @@ enum e {
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
+ /* { dg-error "enumerator value for 'E5' is not an integer constant" "enum error" { target *-*-* } 21 } */
/* Again, overflow in evaluated subexpression. */
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
- /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 24 } */
+ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 25 } */
+ /* { dg-error "enumerator value for 'E6' is not an integer constant" "enum error" { target *-*-* } 25 } */
/* A cast does not constitute overflow in conversion. */
E7 = (char) INT_MAX
};
@@ -31,7 +33,8 @@ struct s {
int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
- /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 33 } */
+ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 35 } */
+ /* { dg-error "bit-field .* width not an integer constant" "" { target *-*-* } 35 } */
};
void
@@ -53,11 +56,11 @@ void *n = 0;
constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
-/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 55 } */
+/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */
-void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } 60 } */
+/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 61 } */
+void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
void
g (int i)
@@ -67,7 +70,7 @@ g (int i)
case 0 * (1/0): /* { dg-warning "division by zero" } */
;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
- /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 69 } */
+ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 72 } */
;
}
}
@@ -1,7 +1,11 @@
/* PR c/27273 */
/* { dg-do compile } */
-/* { dg-options "-Woverflow" } */
+
+// This used to warn about "overflow in implicit constant conversion",
+// which was wrong; 512 is never converted to unsigned char. Rather, an
+// appropriate warning would be that the & expression always evaluates to 0
+// because of the limited range of unsigned char.
unsigned char rx_async(unsigned char p) {
- return p & 512; /* { dg-warning "overflow in implicit constant conversion" } */
+ return p & 512; /* { dg-warning "" "" { xfail *-*-* } } */
}
@@ -52,6 +52,6 @@ test04()
// { dg-error "denominator cannot be zero" "" { target *-*-* } 153 }
// { dg-error "out of range" "" { target *-*-* } 154 }
// { dg-error "non-constant expression" "" { target *-*-* } 59 }
-// { dg-error "is not a constant expression" "" { target *-*-* } 59 }
+// { dg-error "overflow in constant expression" "" { target *-*-* } 59 }
// { dg-error "not a member" "" { target *-*-* } 162 }
// { dg-error "not a valid template argument" "" { target *-*-* } 164 }
As recently discussed, in C++0x mode we were incorrectly treating (int)(unsigned)-1 as a non-constant expression; the standard does not consider that to be overflow, even though the middle end does. This patch fixes that. It also changes arithmetic overflow to be handled the same way in both C++98 and C++0x modes, making it a permerror rather than an error (previous C++0x) or conditional pedwarn (C++98). Tested x86_64-pc-linux-gnu, applied to trunk. commit 332427e690734016e14badac94e354d61cac812c Author: Jason Merrill <jason@redhat.com> Date: Sun Nov 7 17:12:02 2010 -0500 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.