gcc/c-family/
authoremsr <emsr@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 29 Nov 2012 02:30:44 +0000 (02:30 +0000)
committeremsr <emsr@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 29 Nov 2012 02:30:44 +0000 (02:30 +0000)
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
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-lex.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C [new file with mode: 0644]

index ab68f3a..fb39e9d 100644 (file)
@@ -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
index 0c9cccd..5927edf 100644 (file)
@@ -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;
 }
index afd8f07..609be73 100644 (file)
@@ -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);
 
index de9fa69..95ec2df 100644 (file)
@@ -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.  */
index 8c30eaa..c202bdf 100644 (file)
@@ -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
index a2d8062..1fe6246 100644 (file)
@@ -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;
        }
index 79faf38..cea4e76 100644 (file)
@@ -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
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 (file)
index 0000000..ed2de22
--- /dev/null
@@ -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 (file)
index 0000000..85c1572
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options -std=c++0x }\r
+// PR c++/52654\r
+\r
+int\r
+operator"" _w(const char*)\r
+{ return 0; }\r
+\r
+template<char...>\r
+  int\r
+  operator"" _tw()\r
+  { return 0; }\r
+\r
+int i = 12345678901234567890123456789012345678901234567890_w;\r
+int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w;\r
+int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w;\r
+\r
+int ti = 12345678901234567890123456789012345678901234567890_tw;\r
+int tj = 12345678901234567890123456789.012345678901234567890e+1234567890_tw;\r
+int tk = 12345678901234567890123456789.012345678901234567890e-1234567890_tw;\r