libcpp:
authoremsr <emsr@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 31 Oct 2013 14:01:23 +0000 (14:01 +0000)
committeremsr <emsr@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 31 Oct 2013 14:01:23 +0000 (14:01 +0000)
2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>

        Implement C++14 digit separators.
* include/cpplib.h (cpp_options): Add digit_separators flag.
* internal.h (DIGIT_SEP(c)): New macro.
* expr.c (cpp_classify_number): Check improper placement of digit sep;
(cpp_interpret_integer): Skip over digit separators.
* init.c (lang_flags): Add digit_separators flag; (lang_defaults): Add
digit separator flags per language; (cpp_set_lang): Set
digit_separators
* lex.c (lex_number): Add digits separator to allowable characters for
C++14.

gcc/c-family:

2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>

        Implement C++14 digit separators.
* c-lex.c (interpret_float): Remove digit separators from scratch string
before building real literal.

gcc/testsuite:

2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>

        Implement C++14 digit separators.
* g++.dg/cpp1y/digit-sep.C: New.
* g++.dg/cpp1y/digit-sep-neg.C: New.
* g++.dg/cpp1y/digit-sep-cxx11-neg.C: New.

libstdc++-v3:

2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>

        Implement C++14 digit separators.
* include/include/bits/parse_numbers.h: Change struct _Digit<_Base, '`'>
to struct _Digit<_Base, '\''>.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204260 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-lex.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/digit-sep.C [new file with mode: 0644]
libcpp/ChangeLog
libcpp/expr.c
libcpp/include/cpplib.h
libcpp/init.c
libcpp/internal.h
libcpp/lex.c
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/parse_numbers.h

index ff1ce5b..3fa9d13 100644 (file)
@@ -1,3 +1,9 @@
+2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+        Implement C++14 digit separators.
+       * c-lex.c (interpret_float): Remove digit separators from scratch string
+       before building real literal.
+
 2013-10-30  Jakub Jelinek  <jakub@redhat.com>
 
        * cilk.c (create_cilk_helper_decl): Use HOST_WIDE_INT_PRINT_DEC.
index 4dfd5d9..6484352 100644 (file)
@@ -774,8 +774,19 @@ interpret_float (const cpp_token *token, unsigned int flags,
     }
 
   copy = (char *) alloca (copylen + 1);
-  memcpy (copy, token->val.str.text, copylen);
-  copy[copylen] = '\0';
+  if (cxx_dialect > cxx11)
+    {
+      size_t maxlen = 0;
+      for (size_t i = 0; i < copylen; ++i)
+        if (token->val.str.text[i] != '\'')
+          copy[maxlen++] = token->val.str.text[i];
+      copy[maxlen] = '\0';
+    }
+  else
+    {
+      memcpy (copy, token->val.str.text, copylen);
+      copy[copylen] = '\0';
+    }
 
   real_from_string3 (&real, copy, TYPE_MODE (const_type));
   if (const_type != type)
index 261e2e2..7283dbe 100644 (file)
@@ -1,3 +1,10 @@
+2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+        Implement C++14 digit separators.
+       * g++.dg/cpp1y/digit-sep.C: New.
+       * g++.dg/cpp1y/digit-sep-neg.C: New.
+       * g++.dg/cpp1y/digit-sep-cxx11-neg.C: New.
+
 2013-10-31  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/vect/vect-align-3.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C
new file mode 100644 (file)
index 0000000..a078fa2
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options -std=c++11 }
+
+#define assert(E) if(!(E))__builtin_abort();
+
+#define m(x) 0
+
+int
+main()
+{
+  int i = m(1'2)+(3'4);
+  assert(i == 0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
new file mode 100644 (file)
index 0000000..371e675
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-options -std=c++1y }
+
+int
+main()
+{
+  int i = 0;
+  i = 1048''576; // { dg-error "adjacent digit separators" }
+  i = 0X'100000; // { dg-error "digit separator after base indicator" }
+  i = 0x'100000; // { dg-error "digit separator after base indicator" }
+  i = 0004''000'000); // { dg-error "adjacent digit separators" }
+  i = 0B1'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0; // OK
+  i = 0b'0001'0000'0000'0000'0000'0000; // { dg-error "digit separator after base indicator" }
+  i = 0b0001'0000'0000'0000'0000'0000'; // { dg-error "digit separator outside digit sequence" }
+  unsigned u = 0b0001'0000'0000'0000'0000'0000'U; // { dg-error "digit separator outside digit sequence" }
+
+  double d = 0.0;
+  d = 1'.602'176'565e-19; // { dg-error "digit separator adjacent to decimal point" }
+  d = 1.'602'176'565e-19; // { dg-error "digit separator adjacent to decimal point" }
+  d = 1.602''176'565e-19; // { dg-error "adjacent digit separators" }
+  d = 1.602'176'565'e-19; // { dg-error "digit separator adjacent to exponent" }
+  d = 1.602'176'565e'-19; // { dg-error "digit separator adjacent to exponent" }
+  d = 1.602'176'565e-'19; // { dg-error "digit separator adjacent to exponent" }
+  d = 1.602'176'565e-1'9; // OK
+  d = 1.602'176'565e-19'; // { dg-error "digit separator outside digit sequence" }
+  float f = 1.602'176'565e-19'F; // { dg-error "digit separator outside digit sequence" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep.C
new file mode 100644 (file)
index 0000000..69b1c69
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-options -std=c++1y }
+
+#define assert(E) if(!(E))__builtin_abort();
+
+#define m(x) 0
+
+int
+main()
+{
+  assert(1048576 == 1'048'576);
+  assert(1048576 == 0X100000);
+  assert(1048576 == 0x10'0000);
+  assert(1048576 == 0'004'000'000);
+  assert(1048576 == 0B100000000000000000000);
+  assert(1048576 == 0b0001'0000'0000'0000'0000'0000);
+
+  assert(1.602'176'565e-19 == 1.602176565e-19);
+  assert(1.602'176'565e-1'9 == 1.602176565e-19);
+
+  int i = m(1'2)+(3'4);
+  assert(i == 34);
+}
index b4de4f5..2e98e34 100644 (file)
@@ -1,3 +1,16 @@
+2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+        Implement C++14 digit separators.
+       * include/cpplib.h (cpp_options): Add digit_separators flag.
+       * internal.h (DIGIT_SEP(c)): New macro.
+       * expr.c (cpp_classify_number): Check improper placement of digit sep;
+       (cpp_interpret_integer): Skip over digit separators.
+       * init.c (lang_flags): Add digit_separators flag; (lang_defaults): Add
+       digit separator flags per language; (cpp_set_lang): Set
+       digit_separators
+       * lex.c (lex_number): Add digits separator to allowable characters for
+       C++14.
+
 2013-10-15  David Malcolm  <dmalcolm@redhat.com>
 
        * Makefile.in (PICFLAG): New.
index 0eb6c13..c009807 100644 (file)
@@ -394,6 +394,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   unsigned int max_digit, result, radix;
   enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
   bool seen_digit;
+  bool seen_digit_sep;
 
   if (ud_suffix)
     *ud_suffix = NULL;
@@ -408,6 +409,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   max_digit = 0;
   radix = 10;
   seen_digit = false;
+  seen_digit_sep = false;
 
   /* First, interpret the radix.  */
   if (*str == '0')
@@ -416,16 +418,27 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
       str++;
 
       /* Require at least one hex digit to classify it as hex.  */
-      if ((*str == 'x' || *str == 'X')
-         && (str[1] == '.' || ISXDIGIT (str[1])))
+      if (*str == 'x' || *str == 'X')
        {
-         radix = 16;
-         str++;
+         if (str[1] == '.' || ISXDIGIT (str[1]))
+           {
+             radix = 16;
+             str++;
+           }
+         else if (DIGIT_SEP (str[1]))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator after base indicator");
        }
-      else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1'))
+      else if (*str == 'b' || *str == 'B')
        {
-         radix = 2;
-         str++;
+         if (str[1] == '0' || str[1] == '1')
+           {
+             radix = 2;
+             str++;
+           }
+         else if (DIGIT_SEP (str[1]))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator after base indicator");
        }
     }
 
@@ -436,13 +449,24 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 
       if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
        {
+         seen_digit_sep = false;
          seen_digit = true;
          c = hex_value (c);
          if (c > max_digit)
            max_digit = c;
        }
+      else if (DIGIT_SEP (c))
+       {
+         if (seen_digit_sep)
+           SYNTAX_ERROR_AT (virtual_location, "adjacent digit separators");
+         seen_digit_sep = true;
+       }
       else if (c == '.')
        {
+         if (seen_digit_sep || DIGIT_SEP (*str))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator adjacent to decimal point");
+         seen_digit_sep = false;
          if (float_flag == NOT_FLOAT)
            float_flag = AFTER_POINT;
          else
@@ -452,6 +476,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
       else if ((radix <= 10 && (c == 'e' || c == 'E'))
               || (radix == 16 && (c == 'p' || c == 'P')))
        {
+         if (seen_digit_sep || DIGIT_SEP (*str))
+           SYNTAX_ERROR_AT (virtual_location,
+                            "digit separator adjacent to exponent");
          float_flag = AFTER_EXPON;
          break;
        }
@@ -463,6 +490,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
        }
     }
 
+  if (seen_digit_sep && float_flag != AFTER_EXPON)
+    SYNTAX_ERROR_AT (virtual_location,
+                    "digit separator outside digit sequence");
+
   /* The suffix may be for decimal fixed-point constants without exponent.  */
   if (radix != 16 && float_flag == NOT_FLOAT)
     {
@@ -520,16 +551,28 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 
          /* Exponent is decimal, even if string is a hex float.  */
          if (!ISDIGIT (*str))
-           SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
-
+           {
+             if (DIGIT_SEP (*str))
+               SYNTAX_ERROR_AT (virtual_location,
+                                "digit separator adjacent to exponent");
+             else
+               SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
+           }
          do
-           str++;
-         while (ISDIGIT (*str));
+           {
+             seen_digit_sep = DIGIT_SEP (*str);
+             str++;
+           }
+         while (ISDIGIT (*str) || DIGIT_SEP (*str));
        }
       else if (radix == 16)
        SYNTAX_ERROR_AT (virtual_location,
                         "hexadecimal floating constants require an exponent");
 
+      if (seen_digit_sep)
+       SYNTAX_ERROR_AT (virtual_location,
+                        "digit separator outside digit sequence");
+
       result = interpret_float_suffix (pfile, str, limit - str);
       if (result == 0)
        {
@@ -723,6 +766,8 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
 
          if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
            c = hex_value (c);
+         else if (DIGIT_SEP (c))
+           continue;
          else
            break;
 
index 6c4225c..34ad6c3 100644 (file)
@@ -437,6 +437,9 @@ struct cpp_options
   /* Nonzero for C++ 2014 Standard binary constants.  */
   unsigned char binary_constants;
 
+  /* Nonzero for C++ 2014 Standard digit separators.  */
+  unsigned char digit_separators;
+
   /* Holds the name of the target (execution) character set.  */
   const char *narrow_charset;
 
index 9751000..97aa6cd 100644 (file)
@@ -84,24 +84,25 @@ struct lang_flags
   char rliterals;
   char user_literals;
   char binary_constants;
+  char digit_separators;
 };
 
 static const struct lang_flags lang_defaults[] =
-{ /*              c99 c++ xnum xid std  //   digr ulit rlit udlit bin_cst */
-  /* GNUC89   */  { 0,  0,  1,   0,  0,   1,   1,   0,   0,   0,    0 },
-  /* GNUC99   */  { 1,  0,  1,   0,  0,   1,   1,   1,   1,   0,    0 },
-  /* GNUC11   */  { 1,  0,  1,   0,  0,   1,   1,   1,   1,   0,    0 },
-  /* STDC89   */  { 0,  0,  0,   0,  1,   0,   0,   0,   0,   0,    0 },
-  /* STDC94   */  { 0,  0,  0,   0,  1,   0,   1,   0,   0,   0,    0 },
-  /* STDC99   */  { 1,  0,  1,   0,  1,   1,   1,   0,   0,   0,    0 },
-  /* STDC11   */  { 1,  0,  1,   0,  1,   1,   1,   1,   0,   0,    0 },
-  /* GNUCXX   */  { 0,  1,  1,   0,  0,   1,   1,   0,   0,   0,    0 },
-  /* CXX98    */  { 0,  1,  1,   0,  1,   1,   1,   0,   0,   0,    0 },
-  /* GNUCXX11 */  { 1,  1,  1,   0,  0,   1,   1,   1,   1,   1,    0 },
-  /* CXX11    */  { 1,  1,  1,   0,  1,   1,   1,   1,   1,   1,    0 },
-  /* GNUCXX1Y */  { 1,  1,  1,   0,  0,   1,   1,   1,   1,   1,    1 },
-  /* CXX1Y    */  { 1,  1,  1,   0,  1,   1,   1,   1,   1,   1,    1 },
-  /* ASM      */  { 0,  0,  1,   0,  0,   1,   0,   0,   0,   0,    0 }
+{ /*              c99 c++ xnum xid std  //   digr ulit rlit udlit bin_cst dig_sep */
+  /* GNUC89   */  { 0,  0,  1,   0,  0,   1,   1,   0,   0,   0,    0,      0 },
+  /* GNUC99   */  { 1,  0,  1,   0,  0,   1,   1,   1,   1,   0,    0,      0 },
+  /* GNUC11   */  { 1,  0,  1,   0,  0,   1,   1,   1,   1,   0,    0,      0 },
+  /* STDC89   */  { 0,  0,  0,   0,  1,   0,   0,   0,   0,   0,    0,      0 },
+  /* STDC94   */  { 0,  0,  0,   0,  1,   0,   1,   0,   0,   0,    0,      0 },
+  /* STDC99   */  { 1,  0,  1,   0,  1,   1,   1,   0,   0,   0,    0,      0 },
+  /* STDC11   */  { 1,  0,  1,   0,  1,   1,   1,   1,   0,   0,    0,      0 },
+  /* GNUCXX   */  { 0,  1,  1,   0,  0,   1,   1,   0,   0,   0,    0,      0 },
+  /* CXX98    */  { 0,  1,  1,   0,  1,   1,   1,   0,   0,   0,    0,      0 },
+  /* GNUCXX11 */  { 1,  1,  1,   0,  0,   1,   1,   1,   1,   1,    0,      0 },
+  /* CXX11    */  { 1,  1,  1,   0,  1,   1,   1,   1,   1,   1,    0,      0 },
+  /* GNUCXX1Y */  { 1,  1,  1,   0,  0,   1,   1,   1,   1,   1,    1,      1 },
+  /* CXX1Y    */  { 1,  1,  1,   0,  1,   1,   1,   1,   1,   1,    1,      1 },
+  /* ASM      */  { 0,  0,  1,   0,  0,   1,   0,   0,   0,   0,    0,      0 }
   /* xid should be 1 for GNUC99, STDC99, GNUCXX, CXX98, GNUCXX11, CXX11,
      GNUCXX1Y, and CXX1Y when no longer experimental (when all uses of
      identifiers in the compiler have been audited for correct handling
@@ -128,6 +129,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
   CPP_OPTION (pfile, rliterals)                         = l->rliterals;
   CPP_OPTION (pfile, user_literals)             = l->user_literals;
   CPP_OPTION (pfile, binary_constants)          = l->binary_constants;
+  CPP_OPTION (pfile, digit_separators)          = l->digit_separators;
 }
 
 /* Initialize library global state.  */
index 1226dbd..6de44ed 100644 (file)
@@ -59,6 +59,8 @@ struct cset_converter
     || (((prevc) == 'p' || (prevc) == 'P') \
         && CPP_OPTION (pfile, extended_numbers))))
 
+#define DIGIT_SEP(c) ((c) == '\'' && CPP_OPTION (pfile, digit_separators))
+
 #define CPP_OPTION(PFILE, OPTION) ((PFILE)->opts.OPTION)
 #define CPP_BUFFER(PFILE) ((PFILE)->buffer)
 #define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base)
index ed794d5..95995ed 100644 (file)
@@ -1274,7 +1274,8 @@ lex_number (cpp_reader *pfile, cpp_string *number,
       cur = pfile->buffer->cur;
 
       /* N.B. ISIDNUM does not include $.  */
-      while (ISIDNUM (*cur) || *cur == '.' || VALID_SIGN (*cur, cur[-1]))
+      while (ISIDNUM (*cur) || *cur == '.' || DIGIT_SEP (*cur)
+            || VALID_SIGN (*cur, cur[-1]))
        {
          cur++;
          NORMALIZE_STATE_UPDATE_IDNUM (nst);
index 87fa986..0b51888 100644 (file)
@@ -1,3 +1,9 @@
+2013-10-31  Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+        Implement C++14 digit separators.
+       * include/include/bits/parse_numbers.h: Change struct _Digit<_Base, '`'>
+       to struct _Digit<_Base, '\''>.
+
 2013-10-31  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * testsuite/20_util/default_delete/48631_neg.cc: Tweak dg-prune.
index eaa3d27..537b772 100644 (file)
@@ -32,7 +32,7 @@
 
 #pragma GCC system_header
 
-// From n3642.pdf except I added binary literals and digit separator '`'.
+// From n3642.pdf except I added binary literals and digit separator '\''.
 
 #if __cplusplus > 201103L
 
@@ -221,7 +221,7 @@ namespace __parse_int {
 
   //  Digit separator
   template<unsigned _Base>
-    struct _Digit<_Base, '`'>
+    struct _Digit<_Base, '\''>
     {
       static constexpr bool valid{false};
       static constexpr unsigned value{0};