From 324ca37733c5bb9e18452a5e81a12f6f42fd1e4d Mon Sep 17 00:00:00 2001 From: emsr Date: Thu, 29 Nov 2012 02:30:44 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193918 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/c-family/ChangeLog | 13 ++++++ gcc/c-family/c-common.c | 4 +- gcc/c-family/c-common.h | 14 +++++- gcc/c-family/c-lex.c | 59 +++++++++++++++++-------- gcc/cp/ChangeLog | 6 +++ gcc/cp/parser.c | 18 +++++++- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C | 18 ++++++++ gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C | 19 ++++++++ 9 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ab68f3abd05..fb39e9dd799 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -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 PR c/35634 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 0c9cccd3146..5927edf5ef0 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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; } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index afd8f07e72f..609be73a8ff 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -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); diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index de9fa698edc..95ec2df2183 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -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. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8c30eaae87e..c202bdf5025 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 PR bootstrap/54279 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a2d8062d7eb..1fe6246f032 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 79faf383f1b..cea4e76a88c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 PR debug/36728 diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C new file mode 100644 index 00000000000..ed2de22e49d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C @@ -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 } diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C new file mode 100644 index 00000000000..85c15721887 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C @@ -0,0 +1,19 @@ +// { dg-options -std=c++0x } +// PR c++/52654 + +int +operator"" _w(const char*) +{ return 0; } + +template + 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; -- 2.11.4.GIT