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
This commit is contained in:
Edward Smith-Rowland 2013-10-31 14:01:23 +00:00 committed by Edward Smith-Rowland
parent b63cb15373
commit 7057e6452b
14 changed files with 187 additions and 31 deletions

View 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.

View 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)

View 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.

View File

@ -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);
}

View File

@ -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" }
}

View File

@ -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);
}

View 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.

View 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;

View 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;

View 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. */

View 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)

View 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);

View 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.

View 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};