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:
parent
b63cb15373
commit
7057e6452b
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
12
gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C
Normal file
12
gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C
Normal 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);
|
||||
}
|
26
gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
Normal file
26
gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
Normal 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" }
|
||||
}
|
22
gcc/testsuite/g++.dg/cpp1y/digit-sep.C
Normal file
22
gcc/testsuite/g++.dg/cpp1y/digit-sep.C
Normal 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);
|
||||
}
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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};
|
||||
|
Loading…
Reference in New Issue
Block a user