Commit 9e115cec by Jason Merrill Committed by Jason Merrill

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
parent 1b2c3293
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> 2010-11-06 Jason Merrill <jason@redhat.com>
PR c++/46348 PR c++/46348
......
...@@ -2797,11 +2797,14 @@ check_bitfield_decl (tree field) ...@@ -2797,11 +2797,14 @@ check_bitfield_decl (tree field)
} }
else else
{ {
location_t loc = input_location;
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (w); STRIP_NOPS (w);
/* detect invalid field size. */ /* detect invalid field size. */
input_location = DECL_SOURCE_LOCATION (field);
w = cxx_constant_value (w); w = cxx_constant_value (w);
input_location = loc;
if (TREE_CODE (w) != INTEGER_CST) if (TREE_CODE (w) != INTEGER_CST)
{ {
......
...@@ -543,12 +543,35 @@ force_rvalue (tree expr) ...@@ -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 tree
cp_fold_convert (tree type, tree expr) 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. */ /* C++ conversions, preference to static cast conversions. */
...@@ -661,6 +684,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) ...@@ -661,6 +684,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (INTEGRAL_CODE_P (code)) if (INTEGRAL_CODE_P (code))
{ {
tree intype = TREE_TYPE (e); tree intype = TREE_TYPE (e);
tree converted;
if (TREE_CODE (type) == ENUMERAL_TYPE) if (TREE_CODE (type) == ENUMERAL_TYPE)
{ {
...@@ -705,7 +729,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags) ...@@ -705,7 +729,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (code == BOOLEAN_TYPE) if (code == BOOLEAN_TYPE)
return cp_truthvalue_conversion (e); 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)) if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e))
return nullptr_node; return nullptr_node;
......
...@@ -11823,7 +11823,6 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) ...@@ -11823,7 +11823,6 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
if (TREE_CODE (value) == INTEGER_CST) if (TREE_CODE (value) == INTEGER_CST)
{ {
value = perform_integral_promotions (value); value = perform_integral_promotions (value);
constant_expression_warning (value);
} }
else else
{ {
......
...@@ -1054,7 +1054,6 @@ grokbitfield (const cp_declarator *declarator, ...@@ -1054,7 +1054,6 @@ grokbitfield (const cp_declarator *declarator,
if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width))) if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width)))
error ("width of bit-field %qD has non-integral type %qT", value, error ("width of bit-field %qD has non-integral type %qT", value,
TREE_TYPE (width)); TREE_TYPE (width));
constant_expression_warning (width);
DECL_INITIAL (value) = width; DECL_INITIAL (value) = width;
SET_DECL_C_BIT_FIELD (value); SET_DECL_C_BIT_FIELD (value);
} }
......
...@@ -2469,7 +2469,9 @@ location_of (tree t) ...@@ -2469,7 +2469,9 @@ location_of (tree t)
else if (TREE_CODE (t) == OVERLOAD) else if (TREE_CODE (t) == OVERLOAD)
t = OVL_FUNCTION (t); 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 /* 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) ...@@ -5789,7 +5789,7 @@ adjust_temp_type (tree type, tree temp)
if (TREE_CODE (temp) == CONSTRUCTOR) if (TREE_CODE (temp) == CONSTRUCTOR)
return build_constructor (type, CONSTRUCTOR_ELTS (temp)); return build_constructor (type, CONSTRUCTOR_ELTS (temp));
gcc_assert (SCALAR_TYPE_P (type)); gcc_assert (SCALAR_TYPE_P (type));
return fold_convert (type, temp); return cp_fold_convert (type, temp);
} }
/* Subroutine of cxx_eval_call_expression. /* Subroutine of cxx_eval_call_expression.
...@@ -6003,13 +6003,13 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, ...@@ -6003,13 +6003,13 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
return result; return result;
} }
/* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */
bool bool
reduced_constant_expression_p (tree t) reduced_constant_expression_p (tree t)
{ {
/* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */ if (TREE_OVERFLOW_P (t))
if (cxx_dialect >= cxx0x && TREE_OVERFLOW_P (t)) /* Integer overflow makes this not a constant expression. */
/* In C++0x, integer overflow makes this not a constant expression.
FIXME arithmetic overflow is different from conversion truncation */
return false; return false;
/* FIXME are we calling this too much? */ /* FIXME are we calling this too much? */
return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE; 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) ...@@ -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 (!*non_constant_p && !reduced_constant_expression_p (t))
{ {
if (!allow_non_constant) 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; *non_constant_p = true;
} }
return *non_constant_p; return *non_constant_p;
...@@ -6895,12 +6908,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant) ...@@ -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, tree r = cxx_eval_constant_expression (NULL, t, allow_non_constant,
false, &non_constant_p); false, &non_constant_p);
if (!non_constant_p && !reduced_constant_expression_p (r)) verify_constant (r, allow_non_constant, &non_constant_p);
{
if (!allow_non_constant)
error ("%qE is not a constant expression", t);
non_constant_p = true;
}
if (non_constant_p && !allow_non_constant) if (non_constant_p && !allow_non_constant)
return error_mark_node; return error_mark_node;
......
...@@ -5717,33 +5717,6 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, ...@@ -5717,33 +5717,6 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
allow_inverse_p, c_cast_p, complain); 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, /* 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 this static_cast is being attempted as one of the possible casts
allowed by a C-style cast. (In that case, accessibility of base 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, ...@@ -5757,7 +5730,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
{ {
tree intype; tree intype;
tree result; tree result;
tree orig;
/* Assume the cast is valid. */ /* Assume the cast is valid. */
*valid_p = true; *valid_p = true;
...@@ -5814,8 +5786,14 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -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), expr = build_base_path (MINUS_EXPR, build_address (expr),
base, /*nonnull=*/false); base, /*nonnull=*/false);
/* Convert the pointer to a reference -- but then remember that /* Convert the pointer to a reference -- but then remember that
there are no expressions with reference type in C++. */ there are no expressions with reference type in C++.
return convert_from_reference (cp_fold_convert (type, expr));
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 /* "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, ...@@ -5830,8 +5808,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
return convert_from_reference (expr); return convert_from_reference (expr);
} }
orig = expr;
/* Resolve overloaded address here rather than once in /* Resolve overloaded address here rather than once in
implicit_conversion and again in the inverse code below. */ implicit_conversion and again in the inverse code below. */
if (TYPE_PTRMEMFUNC_P (type) && type_unknown_p (expr)) 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, ...@@ -5852,9 +5828,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
{ {
result = convert_from_reference (result); result = convert_from_reference (result);
/* Ignore any integer overflow caused by the cast. */
result = ignore_overflows (result, orig);
/* [expr.static.cast] /* [expr.static.cast]
If T is a reference type, the result is an lvalue; otherwise, 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, ...@@ -5894,13 +5867,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
|| SCALAR_FLOAT_TYPE_P (type)) || SCALAR_FLOAT_TYPE_P (type))
&& (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
|| SCALAR_FLOAT_TYPE_P (intype))) || SCALAR_FLOAT_TYPE_P (intype)))
{ return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
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;
}
if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
&& CLASS_TYPE_P (TREE_TYPE (type)) && CLASS_TYPE_P (TREE_TYPE (type))
......
2010-11-08 Jason Merrill <jason@redhat.com>
* g++.dg/expr/overflow1.C: New.
* g++.dg/warn/overflow-warn-1.C: Add expected diagnostics.
* g++.dg/warn/overflow-warn-3.C: Remove unnecessary line number.
* g++.dg/warn/overflow-warn-4.C: Add expected diagnostics.
* g++.dg/warn/overflow-warn-5.C: Don't expect wrong warning.
2010-11-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> 2010-11-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gcc.dg/pr35442.c: Adapt warning. * gcc.dg/pr35442.c: Adapt warning.
......
#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 */
};
/* Test for diagnostics for constant overflow. */ /* Test for diagnostics for constant overflow. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */ /* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "" } */ /* { dg-options "-fpermissive" } */
#include <limits.h> #include <limits.h>
...@@ -19,8 +19,10 @@ enum e { ...@@ -19,8 +19,10 @@ enum e {
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ /* { 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" } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
/* Again, overflow in evaluated subexpression. */ /* Again, overflow in evaluated subexpression. */
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */ 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. */ /* A cast does not constitute overflow in conversion. */
E7 = (char) INT_MAX E7 = (char) INT_MAX
}; };
...@@ -29,6 +31,7 @@ struct s { ...@@ -29,6 +31,7 @@ struct s {
int a; int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 33 } */
}; };
void void
...@@ -49,10 +52,10 @@ void *n = 0; ...@@ -49,10 +52,10 @@ void *n = 0;
constants. The third has the overflow in an unevaluated constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */ subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ 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" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 53 } */ /* { 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 *-*-* } 55 } */ void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
void void
g (int i) g (int i)
...@@ -62,6 +65,7 @@ g (int i) ...@@ -62,6 +65,7 @@ g (int i)
case 0 * (1/0): /* { dg-warning "division by zero" } */ case 0 * (1/0): /* { dg-warning "division by zero" } */
; ;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ 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" } ...@@ -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" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */ /* { 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 void
g (int i) g (int i)
......
...@@ -11,7 +11,7 @@ enum e { ...@@ -11,7 +11,7 @@ enum e {
E1 = UINT_MAX + 1, E1 = UINT_MAX + 1,
/* Overflow in an unevaluated part of an expression is OK (example /* Overflow in an unevaluated part of an expression is OK (example
in the standard). */ 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" } */ 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 } */ /* { 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 /* But as in DR#031, the 1/0 in an evaluated subexpression means the
...@@ -20,9 +20,11 @@ enum e { ...@@ -20,9 +20,11 @@ enum e {
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ /* { 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" } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */ /* { 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. */ /* Again, overflow in evaluated subexpression. */
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */ 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. */ /* A cast does not constitute overflow in conversion. */
E7 = (char) INT_MAX E7 = (char) INT_MAX
}; };
...@@ -31,7 +33,8 @@ struct s { ...@@ -31,7 +33,8 @@ struct s {
int a; int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ 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 void
...@@ -53,11 +56,11 @@ void *n = 0; ...@@ -53,11 +56,11 @@ void *n = 0;
constants. The third has the overflow in an unevaluated constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */ subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ 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" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */ /* { 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 *-*-* } 60 } */ void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
void void
g (int i) g (int i)
...@@ -67,7 +70,7 @@ g (int i) ...@@ -67,7 +70,7 @@ g (int i)
case 0 * (1/0): /* { dg-warning "division by zero" } */ case 0 * (1/0): /* { dg-warning "division by zero" } */
; ;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ 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 } */
; ;
} }
} }
......
/* PR c/27273 */ /* PR c/27273 */
/* { dg-do compile } */ /* { 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) { unsigned char rx_async(unsigned char p) {
return p & 512; /* { dg-warning "overflow in implicit constant conversion" } */ return p & 512; /* { dg-warning "" "" { xfail *-*-* } } */
} }
2010-11-08 Jason Merrill <jason@redhat.com>
* testsuite/20_util/ratio/cons/cons_overflow_neg.cc: Adjust
expected error.
2010-11-08 Benjamin Kosnik <bkoz@redhat.com> 2010-11-08 Benjamin Kosnik <bkoz@redhat.com>
* include/std/complex (operator==, !=): Mark constexpr. * include/std/complex (operator==, !=): Mark constexpr.
......
...@@ -52,6 +52,6 @@ test04() ...@@ -52,6 +52,6 @@ test04()
// { dg-error "denominator cannot be zero" "" { target *-*-* } 153 } // { dg-error "denominator cannot be zero" "" { target *-*-* } 153 }
// { dg-error "out of range" "" { target *-*-* } 154 } // { dg-error "out of range" "" { target *-*-* } 154 }
// { dg-error "non-constant expression" "" { target *-*-* } 59 } // { 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 member" "" { target *-*-* } 162 }
// { dg-error "not a valid template argument" "" { target *-*-* } 164 } // { dg-error "not a valid template argument" "" { target *-*-* } 164 }
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