* [PATCH, PR52654, C++11] Warn on overflow in user-defined literals
@ 2012-11-28 3:13 Ed Smith-Rowland
2012-11-28 10:26 ` Paolo Carlini
0 siblings, 1 reply; 3+ messages in thread
From: Ed Smith-Rowland @ 2012-11-28 3:13 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 226 bytes --]
Here is a final patch for PR52654 hopefully.
Ultimately we should probably revisit this and 54413 by parsing the literal
numbers in the C++ front end. That won't happen for 4.8.
This builds and passes on x86_64-linux.
Ed
[-- Attachment #2: patch_overflow5 --]
[-- Type: text/plain, Size: 11379 bytes --]
Index: gcc/c-family/c-lex.c
===================================================================
--- gcc/c-family/c-lex.c (revision 193844)
+++ gcc/c-family/c-lex.c (working copy)
@@ -43,8 +43,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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. */
@@ -779,26 +790,38 @@
would overflow. */
real_convert (&real_trunc, TYPE_MODE (type), &real);
- /* Both C and C++ require a diagnostic for a floating constant
- outside the range of representable values of its type. Since we
- have __builtin_inf* to produce an infinity, this is now a
- mandatory pedwarn if the target does not support infinities. */
+ /* Both C and C++ require a diagnostic for a floating constant
+ outside the range of representable values of its type. Since we
+ have __builtin_inf* to produce an infinity, this is now a
+ mandatory pedwarn if the target does not support infinities. */
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. */
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c (revision 193844)
+++ gcc/c-family/c-common.c (working copy)
@@ -11395,11 +11395,13 @@
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;
}
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h (revision 193844)
+++ gcc/c-family/c-common.h (working copy)
@@ -1089,11 +1089,18 @@
/* 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 @@
#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);
Index: gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C (revision 0)
@@ -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;
Index: gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C (revision 0)
@@ -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 }
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revision 193844)
+++ gcc/cp/parser.c (working copy)
@@ -3529,7 +3529,8 @@
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 @@
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 @@
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;
}
[-- Attachment #3: CL_overflow --]
[-- Type: text/plain, Size: 752 bytes --]
2012-11-19 Ed Smith-Rowland <3dw4rd@verizon.net>
PR c++/52654
* gcc/c-family/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.
* gcc/c-family/c-common.c (build_userdef_literal): Add overflow_type
argument.
* gcc/c-family/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/parser.c (cp_parser_string_literal): Add overflow_type arg.
(cp_parser_userdef_numeric_literal): Warn on numeric overflow.
* gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C: New.
* gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C: New.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH, PR52654, C++11] Warn on overflow in user-defined literals
2012-11-28 3:13 [PATCH, PR52654, C++11] Warn on overflow in user-defined literals Ed Smith-Rowland
@ 2012-11-28 10:26 ` Paolo Carlini
0 siblings, 0 replies; 3+ messages in thread
From: Paolo Carlini @ 2012-11-28 10:26 UTC (permalink / raw)
To: Ed Smith-Rowland; +Cc: gcc-patches, Jason Merrill
On 11/28/2012 04:12 AM, Ed Smith-Rowland wrote:
> Here is a final patch for PR52654 hopefully.
>
> Ultimately we should probably revisit this and 54413 by parsing the
> literal
> numbers in the C++ front end. That won't happen for 4.8.
>
> This builds and passes on x86_64-linux
Thanks. Let's make sure Jason gets your message in CC.
Paolo.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH, PR52654, C++11] Warn on overflow in user-defined literals
[not found] <50B69AA0.2000102@verizon.net>
@ 2012-11-29 0:31 ` Jason Merrill
0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2012-11-29 0:31 UTC (permalink / raw)
To: Ed Smith-Rowland; +Cc: gcc-patches List
On 11/28/2012 06:13 PM, Ed Smith-Rowland wrote:
> Ultimately we should probably revisit this and 54413 by parsing the literal
> numbers in the C++ front end. That won't happen for 4.8.
That sounds like you're proposing to duplicate code?
> - /* Both C and C++ require a diagnostic for a floating constant
> - outside the range of representable values of its type. Since we
> - have __builtin_inf* to produce an infinity, this is now a
> - mandatory pedwarn if the target does not support infinities. */
> + /* Both C and C++ require a diagnostic for a floating constant
> + outside the range of representable values of its type. Since we
> + have __builtin_inf* to produce an infinity, this is now a
> + mandatory pedwarn if the target does not support infinities. */
This seems unintentional.
OK with that indentation change removed.
Jason
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-11-29 0:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-28 3:13 [PATCH, PR52654, C++11] Warn on overflow in user-defined literals Ed Smith-Rowland
2012-11-28 10:26 ` Paolo Carlini
[not found] <50B69AA0.2000102@verizon.net>
2012-11-29 0:31 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).