aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorEdward Smith-Rowland <3dw4rd@verizon.net>2013-10-31 14:01:23 +0000
committerEdward Smith-Rowland <emsr@gcc.gnu.org>2013-10-31 14:01:23 +0000
commit7057e6452ba6b205085eede49eddf37c2feab29a (patch)
tree28dc58242b9d84a0f1723c9f24e40c623e194ef1 /libcpp
parentb63cb15373bf384f1d644c4cfae0c60422cc3909 (diff)
downloadgcc-7057e6452ba6b205085eede49eddf37c2feab29a.zip
gcc-7057e6452ba6b205085eede49eddf37c2feab29a.tar.gz
gcc-7057e6452ba6b205085eede49eddf37c2feab29a.tar.bz2
Implement C++14 digit separators.
libcpp: 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, '\''>. From-SVN: r204260
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog13
-rw-r--r--libcpp/expr.c67
-rw-r--r--libcpp/include/cpplib.h3
-rw-r--r--libcpp/init.c32
-rw-r--r--libcpp/internal.h2
-rw-r--r--libcpp/lex.c3
6 files changed, 93 insertions, 27 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index b4de4f5..2e98e34 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -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.
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 0eb6c13..c009807 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -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;
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 6c4225c..34ad6c3 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -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;
diff --git a/libcpp/init.c b/libcpp/init.c
index 9751000..97aa6cd 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -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. */
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 1226dbd..6de44ed 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -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)
diff --git a/libcpp/lex.c b/libcpp/lex.c
index ed794d5..95995ed 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -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);