re PR c++/52654 ([C++11] Warn on overflow in user-defined literals)
gcc/c-family/ 2012-11-29 Ed Smith-Rowland <3dw4rd@verizon.net> PR c++/52654 * c-common.h (overflow_type): New enum. (build_userdef_literal): Add overflow_type argument. (tree_userdef_literal): Add overflow_type. (USERDEF_LITERAL_OVERFLOW): New access macro. * c-common.c (build_userdef_literal): Add overflow_type argument. * c-lex.c (c_lex_with_flags): Add overflow_type to build_userdef_literal calls. (interpret_integer, interpret_float): Add overflow_type argument. gcc/cp/ 2012-11-29 Ed Smith-Rowland <3dw4rd@verizon.net> PR c++/52654 * parser.c (cp_parser_string_literal): Add overflow_type arg. (cp_parser_userdef_numeric_literal): Warn on numeric overflow. gcc/testsuite/ 2012-11-29 Ed Smith-Rowland <3dw4rd@verizon.net> PR c++/52654 * g++.dg/cpp0x/udlit-overflow.C: New. * g++.dg/cpp0x/udlit-overflow-neg.C: New. From-SVN: r193918
This commit is contained in:
parent
48ac1c945b
commit
2d7aa5780c
|
@ -1,3 +1,16 @@
|
|||
2012-11-29 Ed Smith-Rowland <3dw4rd@verizon.net>
|
||||
|
||||
PR c++/52654
|
||||
* c-common.h (overflow_type): New enum.
|
||||
(build_userdef_literal): Add overflow_type argument.
|
||||
(tree_userdef_literal): Add overflow_type.
|
||||
(USERDEF_LITERAL_OVERFLOW): New access macro.
|
||||
* c-common.c (build_userdef_literal): Add overflow_type
|
||||
argument.
|
||||
* c-lex.c (c_lex_with_flags): Add overflow_type to
|
||||
build_userdef_literal calls.
|
||||
(interpret_integer, interpret_float): Add overflow_type argument.
|
||||
|
||||
2012-11-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR c/35634
|
||||
|
|
|
@ -11395,11 +11395,13 @@ c_common_init_ts (void)
|
|||
with identifier SUFFIX. */
|
||||
|
||||
tree
|
||||
build_userdef_literal (tree suffix_id, tree value, tree num_string)
|
||||
build_userdef_literal (tree suffix_id, tree value,
|
||||
enum overflow_type overflow, tree num_string)
|
||||
{
|
||||
tree literal = make_node (USERDEF_LITERAL);
|
||||
USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
|
||||
USERDEF_LITERAL_VALUE (literal) = value;
|
||||
USERDEF_LITERAL_OVERFLOW (literal) = overflow;
|
||||
USERDEF_LITERAL_NUM_STRING (literal) = num_string;
|
||||
return literal;
|
||||
}
|
||||
|
|
|
@ -1089,11 +1089,18 @@ extern tree find_tm_attribute (tree);
|
|||
|
||||
/* A suffix-identifier value doublet that represents user-defined literals
|
||||
for C++-0x. */
|
||||
enum overflow_type {
|
||||
OT_UNDERFLOW = -1,
|
||||
OT_NONE,
|
||||
OT_OVERFLOW
|
||||
};
|
||||
|
||||
struct GTY(()) tree_userdef_literal {
|
||||
struct tree_base base;
|
||||
tree suffix_id;
|
||||
tree value;
|
||||
tree num_string;
|
||||
enum overflow_type overflow;
|
||||
};
|
||||
|
||||
#define USERDEF_LITERAL_SUFFIX_ID(NODE) \
|
||||
|
@ -1102,13 +1109,18 @@ struct GTY(()) tree_userdef_literal {
|
|||
#define USERDEF_LITERAL_VALUE(NODE) \
|
||||
(((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
|
||||
|
||||
#define USERDEF_LITERAL_OVERFLOW(NODE) \
|
||||
(((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->overflow)
|
||||
|
||||
#define USERDEF_LITERAL_NUM_STRING(NODE) \
|
||||
(((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
|
||||
|
||||
#define USERDEF_LITERAL_TYPE(NODE) \
|
||||
(TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
|
||||
|
||||
extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
|
||||
extern tree build_userdef_literal (tree suffix_id, tree value,
|
||||
enum overflow_type overflow,
|
||||
tree num_string);
|
||||
|
||||
extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
|
||||
|
||||
|
|
|
@ -43,8 +43,10 @@ static splay_tree file_info_tree;
|
|||
int pending_lang_change; /* If we need to switch languages - C++ only */
|
||||
int c_header_level; /* depth in C headers - C++ only */
|
||||
|
||||
static tree interpret_integer (const cpp_token *, unsigned int);
|
||||
static tree interpret_float (const cpp_token *, unsigned int, const char *);
|
||||
static tree interpret_integer (const cpp_token *, unsigned int,
|
||||
enum overflow_type *);
|
||||
static tree interpret_float (const cpp_token *, unsigned int, const char *,
|
||||
enum overflow_type *);
|
||||
static tree interpret_fixed (const cpp_token *, unsigned int);
|
||||
static enum integer_type_kind narrowest_unsigned_type
|
||||
(unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
|
||||
|
@ -293,6 +295,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
|
|||
const cpp_token *tok;
|
||||
enum cpp_ttype type;
|
||||
unsigned char add_flags = 0;
|
||||
enum overflow_type overflow = OT_NONE;
|
||||
|
||||
timevar_push (TV_CPP);
|
||||
retry:
|
||||
|
@ -326,11 +329,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
|
|||
Set PURE_ZERO to pass this information to the C++ parser. */
|
||||
if (tok->val.str.len == 1 && *tok->val.str.text == '0')
|
||||
add_flags = PURE_ZERO;
|
||||
*value = interpret_integer (tok, flags);
|
||||
*value = interpret_integer (tok, flags, &overflow);
|
||||
break;
|
||||
|
||||
case CPP_N_FLOATING:
|
||||
*value = interpret_float (tok, flags, suffix);
|
||||
*value = interpret_float (tok, flags, suffix, &overflow);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -351,8 +354,8 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
|
|||
num_string = fix_string_type (num_string);
|
||||
str = CONST_CAST (char *, TREE_STRING_POINTER (num_string));
|
||||
str[len] = '\0';
|
||||
literal = build_userdef_literal (suffix_id, *value,
|
||||
num_string);
|
||||
literal = build_userdef_literal (suffix_id, *value, overflow,
|
||||
num_string);
|
||||
*value = literal;
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +446,8 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
|
|||
temp_tok.val.str.len -= strlen (suffix);
|
||||
temp_tok.type = cpp_userdef_char_remove_type (type);
|
||||
literal = build_userdef_literal (get_identifier (suffix),
|
||||
lex_charconst (&temp_tok), NULL_TREE);
|
||||
lex_charconst (&temp_tok),
|
||||
OT_NONE, NULL_TREE);
|
||||
*value = literal;
|
||||
}
|
||||
break;
|
||||
|
@ -466,7 +470,7 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
|
|||
string = build_string (tok->val.str.len - strlen (suffix),
|
||||
(const char *) tok->val.str.text);
|
||||
literal = build_userdef_literal (get_identifier (suffix),
|
||||
string, NULL_TREE);
|
||||
string, OT_NONE, NULL_TREE);
|
||||
*value = literal;
|
||||
}
|
||||
break;
|
||||
|
@ -587,15 +591,20 @@ narrowest_signed_type (unsigned HOST_WIDE_INT low,
|
|||
|
||||
/* Interpret TOKEN, an integer with FLAGS as classified by cpplib. */
|
||||
static tree
|
||||
interpret_integer (const cpp_token *token, unsigned int flags)
|
||||
interpret_integer (const cpp_token *token, unsigned int flags,
|
||||
enum overflow_type *overflow)
|
||||
{
|
||||
tree value, type;
|
||||
enum integer_type_kind itk;
|
||||
cpp_num integer;
|
||||
cpp_options *options = cpp_get_options (parse_in);
|
||||
|
||||
*overflow = OT_NONE;
|
||||
|
||||
integer = cpp_interpret_integer (parse_in, token, flags);
|
||||
integer = cpp_num_sign_extend (integer, options->precision);
|
||||
if (integer.overflow)
|
||||
*overflow = OT_OVERFLOW;
|
||||
|
||||
/* The type of a constant with a U suffix is straightforward. */
|
||||
if (flags & CPP_N_UNSIGNED)
|
||||
|
@ -673,7 +682,7 @@ interpret_integer (const cpp_token *token, unsigned int flags)
|
|||
by cpplib. For C++0X SUFFIX may contain a user-defined literal suffix. */
|
||||
static tree
|
||||
interpret_float (const cpp_token *token, unsigned int flags,
|
||||
const char *suffix)
|
||||
const char *suffix, enum overflow_type *overflow)
|
||||
{
|
||||
tree type;
|
||||
tree const_type;
|
||||
|
@ -683,6 +692,8 @@ interpret_float (const cpp_token *token, unsigned int flags,
|
|||
char *copy;
|
||||
size_t copylen;
|
||||
|
||||
*overflow = OT_NONE;
|
||||
|
||||
/* Default (no suffix) depends on whether the FLOAT_CONST_DECIMAL64
|
||||
pragma has been used and is either double or _Decimal64. Types
|
||||
that are not allowed with decimal float default to double. */
|
||||
|
@ -786,19 +797,31 @@ interpret_float (const cpp_token *token, unsigned int flags,
|
|||
if (REAL_VALUE_ISINF (real)
|
||||
|| (const_type != type && REAL_VALUE_ISINF (real_trunc)))
|
||||
{
|
||||
if (!MODE_HAS_INFINITIES (TYPE_MODE (type)))
|
||||
pedwarn (input_location, 0, "floating constant exceeds range of %qT", type);
|
||||
else
|
||||
warning (OPT_Woverflow, "floating constant exceeds range of %qT", type);
|
||||
*overflow = OT_OVERFLOW;
|
||||
if (!(flags & CPP_N_USERDEF))
|
||||
{
|
||||
if (!MODE_HAS_INFINITIES (TYPE_MODE (type)))
|
||||
pedwarn (input_location, 0,
|
||||
"floating constant exceeds range of %qT", type);
|
||||
else
|
||||
warning (OPT_Woverflow,
|
||||
"floating constant exceeds range of %qT", type);
|
||||
}
|
||||
}
|
||||
/* We also give a warning if the value underflows. */
|
||||
else if (REAL_VALUES_EQUAL (real, dconst0)
|
||||
|| (const_type != type && REAL_VALUES_EQUAL (real_trunc, dconst0)))
|
||||
|| (const_type != type
|
||||
&& REAL_VALUES_EQUAL (real_trunc, dconst0)))
|
||||
{
|
||||
REAL_VALUE_TYPE realvoidmode;
|
||||
int overflow = real_from_string (&realvoidmode, copy);
|
||||
if (overflow < 0 || !REAL_VALUES_EQUAL (realvoidmode, dconst0))
|
||||
warning (OPT_Woverflow, "floating constant truncated to zero");
|
||||
int oflow = real_from_string (&realvoidmode, copy);
|
||||
*overflow = (oflow == 0 ? OT_NONE
|
||||
: (oflow < 0 ? OT_UNDERFLOW : OT_OVERFLOW));
|
||||
if (!(flags & CPP_N_USERDEF))
|
||||
{
|
||||
if (oflow < 0 || !REAL_VALUES_EQUAL (realvoidmode, dconst0))
|
||||
warning (OPT_Woverflow, "floating constant truncated to zero");
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a node with determined type and value. */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2012-11-29 Ed Smith-Rowland <3dw4rd@verizon.net>
|
||||
|
||||
PR c++/52654
|
||||
* parser.c (cp_parser_string_literal): Add overflow_type arg.
|
||||
(cp_parser_userdef_numeric_literal): Warn on numeric overflow.
|
||||
|
||||
2012-11-28 Andrew Pinski <apinski@cavium.com>
|
||||
|
||||
PR bootstrap/54279
|
||||
|
|
|
@ -3529,7 +3529,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
|
|||
|
||||
if (have_suffix_p)
|
||||
{
|
||||
tree literal = build_userdef_literal (suffix_id, value, NULL_TREE);
|
||||
tree literal = build_userdef_literal (suffix_id, value,
|
||||
OT_NONE, NULL_TREE);
|
||||
tok->u.value = literal;
|
||||
return cp_parser_userdef_string_literal (tok);
|
||||
}
|
||||
|
@ -3661,6 +3662,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
|
|||
tree literal = token->u.value;
|
||||
tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
|
||||
tree value = USERDEF_LITERAL_VALUE (literal);
|
||||
int overflow = USERDEF_LITERAL_OVERFLOW (literal);
|
||||
tree num_string = USERDEF_LITERAL_NUM_STRING (literal);
|
||||
tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
|
||||
tree decl, result;
|
||||
|
@ -3676,6 +3678,20 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
|
|||
result = finish_call_expr (decl, &args, false, true, tf_none);
|
||||
if (result != error_mark_node)
|
||||
{
|
||||
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && overflow > 0)
|
||||
warning_at (token->location, OPT_Woverflow,
|
||||
"integer literal exceeds range of %qT type",
|
||||
long_long_unsigned_type_node);
|
||||
else
|
||||
{
|
||||
if (overflow > 0)
|
||||
warning_at (token->location, OPT_Woverflow,
|
||||
"floating literal exceeds range of %qT type",
|
||||
long_double_type_node);
|
||||
else if (overflow < 0)
|
||||
warning_at (token->location, OPT_Woverflow,
|
||||
"floating literal truncated to zero");
|
||||
}
|
||||
release_tree_vector (args);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2012-11-29 Ed Smith-Rowland <3dw4rd@verizon.net>
|
||||
|
||||
PR c++/52654
|
||||
* g++.dg/cpp0x/udlit-overflow.C: New.
|
||||
* g++.dg/cpp0x/udlit-overflow-neg.C: New.
|
||||
|
||||
2012-11-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR debug/36728
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// { dg-options "-std=c++0x -Woverflow" }
|
||||
// PR c++/52654
|
||||
|
||||
int
|
||||
operator"" _w(unsigned long long)
|
||||
{ return 0; }
|
||||
|
||||
int
|
||||
operator"" _w(long double)
|
||||
{ return 0.0L; }
|
||||
|
||||
int i = 12345678901234567890123456789012345678901234567890_w;
|
||||
int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w;
|
||||
int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w;
|
||||
|
||||
// { dg-warning "integer literal exceeds range of " "" { target *-*-* } 12 }
|
||||
// { dg-warning "floating literal exceeds range of " "" { target *-*-* } 13 }
|
||||
// { dg-warning "floating literal truncated to zero" "" { target *-*-* } 14 }
|
|
@ -0,0 +1,19 @@
|
|||
// { dg-options -std=c++0x }
|
||||
// PR c++/52654
|
||||
|
||||
int
|
||||
operator"" _w(const char*)
|
||||
{ return 0; }
|
||||
|
||||
template<char...>
|
||||
int
|
||||
operator"" _tw()
|
||||
{ return 0; }
|
||||
|
||||
int i = 12345678901234567890123456789012345678901234567890_w;
|
||||
int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w;
|
||||
int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w;
|
||||
|
||||
int ti = 12345678901234567890123456789012345678901234567890_tw;
|
||||
int tj = 12345678901234567890123456789.012345678901234567890e+1234567890_tw;
|
||||
int tk = 12345678901234567890123456789.012345678901234567890e-1234567890_tw;
|
Loading…
Reference in New Issue