summaryrefslogtreecommitdiff
path: root/libcpp/lex.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-10-30 09:35:42 +0000
committer <>2015-01-09 11:51:27 +0000
commitc27a97d04853380f1e80525391b3f0d156ed4c84 (patch)
tree68ffaade7c605bc80cffa18360799c98a810976f /libcpp/lex.c
parent6af3fdec2262dd94954acc5e426ef71cbd4521d3 (diff)
downloadgcc-tarball-c27a97d04853380f1e80525391b3f0d156ed4c84.tar.gz
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-4.9.2.tar.bz2.gcc-4.9.2
Diffstat (limited to 'libcpp/lex.c')
-rw-r--r--libcpp/lex.c502
1 files changed, 403 insertions, 99 deletions
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 0ad9660a76..ec07c6e653 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -1,6 +1,5 @@
/* CPP Library - lexical analysis.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
- 2011 Free Software Foundation, Inc.
+ Copyright (C) 2000-2014 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -267,7 +266,6 @@ search_line_acc_char (const uchar *s, const uchar *end ATTRIBUTE_UNUSED)
/* Disable on Solaris 2/x86 until the following problems can be properly
autoconfed:
- The Solaris 8 assembler cannot assemble SSE2/SSE4.2 insns.
The Solaris 9 assembler cannot assemble SSE4.2 insns.
Before Solaris 9 Update 6, SSE insns cannot be executed.
The Solaris 10+ assembler tags objects with the instruction set
@@ -428,6 +426,8 @@ search_line_sse42 (const uchar *s, const uchar *end)
/* Check for unaligned input. */
if (si & 15)
{
+ v16qi sv;
+
if (__builtin_expect (end - s < 16, 0)
&& __builtin_expect ((si & 0xfff) > 0xff0, 0))
{
@@ -440,8 +440,9 @@ search_line_sse42 (const uchar *s, const uchar *end)
/* ??? The builtin doesn't understand that the PCMPESTRI read from
memory need not be aligned. */
- __asm ("%vpcmpestri $0, (%1), %2"
- : "=c"(index) : "r"(s), "x"(search), "a"(4), "d"(16));
+ sv = __builtin_ia32_loaddqu ((const char *) s);
+ index = __builtin_ia32_pcmpestri128 (search, 4, sv, 16, 0);
+
if (__builtin_expect (index < 16, 0))
goto found;
@@ -514,9 +515,111 @@ init_vectorized_lexer (void)
search_line_fast = impl;
}
-#elif (GCC_VERSION >= 4005) && defined(__ALTIVEC__)
+#elif defined(_ARCH_PWR8) && defined(__ALTIVEC__)
+
+/* A vection of the fast scanner using AltiVec vectorized byte compares
+ and VSX unaligned loads (when VSX is available). This is otherwise
+ the same as the pre-GCC 5 version. */
+
+static const uchar *
+search_line_fast (const uchar *s, const uchar *end ATTRIBUTE_UNUSED)
+{
+ typedef __attribute__((altivec(vector))) unsigned char vc;
+
+ const vc repl_nl = {
+ '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n',
+ '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'
+ };
+ const vc repl_cr = {
+ '\r', '\r', '\r', '\r', '\r', '\r', '\r', '\r',
+ '\r', '\r', '\r', '\r', '\r', '\r', '\r', '\r'
+ };
+ const vc repl_bs = {
+ '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\',
+ '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\'
+ };
+ const vc repl_qm = {
+ '?', '?', '?', '?', '?', '?', '?', '?',
+ '?', '?', '?', '?', '?', '?', '?', '?',
+ };
+ const vc zero = { 0 };
+
+ vc data, t;
+
+ /* Main loop processing 16 bytes at a time. */
+ do
+ {
+ vc m_nl, m_cr, m_bs, m_qm;
+
+ data = *((const vc *)s);
+ s += 16;
+
+ m_nl = (vc) __builtin_vec_cmpeq(data, repl_nl);
+ m_cr = (vc) __builtin_vec_cmpeq(data, repl_cr);
+ m_bs = (vc) __builtin_vec_cmpeq(data, repl_bs);
+ m_qm = (vc) __builtin_vec_cmpeq(data, repl_qm);
+ t = (m_nl | m_cr) | (m_bs | m_qm);
+
+ /* T now contains 0xff in bytes for which we matched one of the relevant
+ characters. We want to exit the loop if any byte in T is non-zero.
+ Below is the expansion of vec_any_ne(t, zero). */
+ }
+ while (!__builtin_vec_vcmpeq_p(/*__CR6_LT_REV*/3, t, zero));
+
+ /* Restore s to to point to the 16 bytes we just processed. */
+ s -= 16;
+
+ {
+#define N (sizeof(vc) / sizeof(long))
-/* A vection of the fast scanner using AltiVec vectorized byte compares. */
+ union {
+ vc v;
+ /* Statically assert that N is 2 or 4. */
+ unsigned long l[(N == 2 || N == 4) ? N : -1];
+ } u;
+ unsigned long l, i = 0;
+
+ u.v = t;
+
+ /* Find the first word of T that is non-zero. */
+ switch (N)
+ {
+ case 4:
+ l = u.l[i++];
+ if (l != 0)
+ break;
+ s += sizeof(unsigned long);
+ l = u.l[i++];
+ if (l != 0)
+ break;
+ s += sizeof(unsigned long);
+ case 2:
+ l = u.l[i++];
+ if (l != 0)
+ break;
+ s += sizeof(unsigned long);
+ l = u.l[i];
+ }
+
+ /* L now contains 0xff in bytes for which we matched one of the
+ relevant characters. We can find the byte index by finding
+ its bit index and dividing by 8. */
+#ifdef __BIG_ENDIAN__
+ l = __builtin_clzl(l) >> 3;
+#else
+ l = __builtin_ctzl(l) >> 3;
+#endif
+ return s + l;
+
+#undef N
+ }
+}
+
+#elif (GCC_VERSION >= 4005) && defined(__ALTIVEC__) && defined (__BIG_ENDIAN__)
+
+/* A vection of the fast scanner using AltiVec vectorized byte compares.
+ This cannot be used for little endian because vec_lvsl/lvsr are
+ deprecated for little endian and the code won't work properly. */
/* ??? Unfortunately, attribute(target("altivec")) is not yet supported,
so we can't compile this function without -maltivec on the command line
(or implied by some other switch). */
@@ -591,10 +694,10 @@ search_line_fast (const uchar *s, const uchar *end ATTRIBUTE_UNUSED)
{
#define N (sizeof(vc) / sizeof(long))
- typedef char check_count[(N == 2 || N == 4) * 2 - 1];
union {
vc v;
- unsigned long l[N];
+ /* Statically assert that N is 2 or 4. */
+ unsigned long l[(N == 2 || N == 4) ? N : -1];
} u;
unsigned long l, i = 0;
@@ -630,6 +733,69 @@ search_line_fast (const uchar *s, const uchar *end ATTRIBUTE_UNUSED)
}
}
+#elif defined (__ARM_NEON__)
+#include "arm_neon.h"
+
+static const uchar *
+search_line_fast (const uchar *s, const uchar *end ATTRIBUTE_UNUSED)
+{
+ const uint8x16_t repl_nl = vdupq_n_u8 ('\n');
+ const uint8x16_t repl_cr = vdupq_n_u8 ('\r');
+ const uint8x16_t repl_bs = vdupq_n_u8 ('\\');
+ const uint8x16_t repl_qm = vdupq_n_u8 ('?');
+ const uint8x16_t xmask = (uint8x16_t) vdupq_n_u64 (0x8040201008040201ULL);
+
+ unsigned int misalign, found, mask;
+ const uint8_t *p;
+ uint8x16_t data;
+
+ /* Align the source pointer. */
+ misalign = (uintptr_t)s & 15;
+ p = (const uint8_t *)((uintptr_t)s & -16);
+ data = vld1q_u8 (p);
+
+ /* Create a mask for the bytes that are valid within the first
+ 16-byte block. The Idea here is that the AND with the mask
+ within the loop is "free", since we need some AND or TEST
+ insn in order to set the flags for the branch anyway. */
+ mask = (-1u << misalign) & 0xffff;
+
+ /* Main loop, processing 16 bytes at a time. */
+ goto start;
+
+ do
+ {
+ uint8x8_t l;
+ uint16x4_t m;
+ uint32x2_t n;
+ uint8x16_t t, u, v, w;
+
+ p += 16;
+ data = vld1q_u8 (p);
+ mask = 0xffff;
+
+ start:
+ t = vceqq_u8 (data, repl_nl);
+ u = vceqq_u8 (data, repl_cr);
+ v = vorrq_u8 (t, vceqq_u8 (data, repl_bs));
+ w = vorrq_u8 (u, vceqq_u8 (data, repl_qm));
+ t = vandq_u8 (vorrq_u8 (v, w), xmask);
+ l = vpadd_u8 (vget_low_u8 (t), vget_high_u8 (t));
+ m = vpaddl_u8 (l);
+ n = vpaddl_u16 (m);
+
+ found = vget_lane_u32 ((uint32x2_t) vorr_u64 ((uint64x1_t) n,
+ vshr_n_u64 ((uint64x1_t) n, 24)), 0);
+ found &= mask;
+ }
+ while (!found);
+
+ /* FOUND contains 1 in bits for which we matched a relevant
+ character. Conversion to the byte index is trivial. */
+ found = __builtin_ctz (found);
+ return (const uchar *)p + found;
+}
+
#else
/* We only have one accellerated alternative. Use a direct call so that
@@ -1029,6 +1195,7 @@ warn_about_normalization (cpp_reader *pfile,
else
cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
"`%.*s' is not in NFC", (int) sz, buf);
+ free (buf);
}
}
@@ -1139,11 +1306,14 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
cur = pfile->buffer->cur;
if (! starts_ucn)
- while (ISIDNUM (*cur))
- {
- hash = HT_HASHSTEP (hash, *cur);
- cur++;
- }
+ {
+ while (ISIDNUM (*cur))
+ {
+ hash = HT_HASHSTEP (hash, *cur);
+ cur++;
+ }
+ NORMALIZE_STATE_UPDATE_IDNUM (nst, *(cur - 1));
+ }
pfile->buffer->cur = cur;
if (starts_ucn || forms_identifier_p (pfile, false, nst))
{
@@ -1151,8 +1321,8 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn,
do {
while (ISIDNUM (*pfile->buffer->cur))
{
+ NORMALIZE_STATE_UPDATE_IDNUM (nst, *pfile->buffer->cur);
pfile->buffer->cur++;
- NORMALIZE_STATE_UPDATE_IDNUM (nst);
}
} while (forms_identifier_p (pfile, false, nst));
result = _cpp_interpret_identifier (pfile, base,
@@ -1209,10 +1379,11 @@ 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]))
{
+ NORMALIZE_STATE_UPDATE_IDNUM (nst, *cur);
cur++;
- NORMALIZE_STATE_UPDATE_IDNUM (nst);
}
pfile->buffer->cur = cur;
@@ -1269,6 +1440,33 @@ bufring_append (cpp_reader *pfile, const uchar *base, size_t len,
*last_buff_p = last_buff;
}
+
+/* Returns true if a macro has been defined.
+ This might not work if compile with -save-temps,
+ or preprocess separately from compilation. */
+
+static bool
+is_macro(cpp_reader *pfile, const uchar *base)
+{
+ const uchar *cur = base;
+ if (! ISIDST (*cur))
+ return false;
+ unsigned int hash = HT_HASHSTEP (0, *cur);
+ ++cur;
+ while (ISIDNUM (*cur))
+ {
+ hash = HT_HASHSTEP (hash, *cur);
+ ++cur;
+ }
+ hash = HT_HASHFINISH (hash, cur - base);
+
+ cpp_hashnode *result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table,
+ base, cur - base, hash, HT_NO_INSERT));
+
+ return !result ? false : (result->type == NT_MACRO);
+}
+
+
/* Lexes a raw string. The stored string contains the spelling, including
double quotes, delimiter string, '(' and ')', any leading
'L', 'u', 'U' or 'u8' and 'R' modifier. It returns the type of the
@@ -1281,11 +1479,20 @@ static void
lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
const uchar *cur)
{
- const uchar *raw_prefix;
- unsigned int raw_prefix_len = 0;
+ uchar raw_prefix[17];
+ uchar temp_buffer[18];
+ const uchar *orig_base;
+ unsigned int raw_prefix_len = 0, raw_suffix_len = 0;
+ enum raw_str_phase { RAW_STR_PREFIX, RAW_STR, RAW_STR_SUFFIX };
+ raw_str_phase phase = RAW_STR_PREFIX;
enum cpp_ttype type;
size_t total_len = 0;
+ /* Index into temp_buffer during phases other than RAW_STR,
+ during RAW_STR phase 17 to tell BUF_APPEND that nothing should
+ be appended to temp_buffer. */
+ size_t temp_buffer_len = 0;
_cpp_buff *first_buff = NULL, *last_buff = NULL;
+ size_t raw_prefix_start;
_cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note];
type = (*base == 'L' ? CPP_WSTRING :
@@ -1293,68 +1500,31 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
*base == 'u' ? (base[1] == '8' ? CPP_UTF8STRING : CPP_STRING16)
: CPP_STRING);
- raw_prefix = cur + 1;
- while (raw_prefix_len < 16)
- {
- switch (raw_prefix[raw_prefix_len])
- {
- case ' ': case '(': case ')': case '\\': case '\t':
- case '\v': case '\f': case '\n': default:
- break;
- /* Basic source charset except the above chars. */
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
- case 's': case 't': case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
- case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
- case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- case '_': case '{': case '}': case '#': case '[': case ']':
- case '<': case '>': case '%': case ':': case ';': case '.':
- case '?': case '*': case '+': case '-': case '/': case '^':
- case '&': case '|': case '~': case '!': case '=': case ',':
- case '"': case '\'':
- raw_prefix_len++;
- continue;
- }
- break;
- }
-
- if (raw_prefix[raw_prefix_len] != '(')
- {
- int col = CPP_BUF_COLUMN (pfile->buffer, raw_prefix + raw_prefix_len)
- + 1;
- if (raw_prefix_len == 16)
- cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, col,
- "raw string delimiter longer than 16 characters");
- else
- cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, col,
- "invalid character '%c' in raw string delimiter",
- (int) raw_prefix[raw_prefix_len]);
- pfile->buffer->cur = raw_prefix - 1;
- create_literal (pfile, token, base, raw_prefix - 1 - base, CPP_OTHER);
- return;
- }
-
- cur = raw_prefix + raw_prefix_len + 1;
- for (;;)
- {
#define BUF_APPEND(STR,LEN) \
do { \
bufring_append (pfile, (const uchar *)(STR), (LEN), \
&first_buff, &last_buff); \
total_len += (LEN); \
+ if (__builtin_expect (temp_buffer_len < 17, 0) \
+ && (const uchar *)(STR) != base \
+ && (LEN) <= 2) \
+ { \
+ memcpy (temp_buffer + temp_buffer_len, \
+ (const uchar *)(STR), (LEN)); \
+ temp_buffer_len += (LEN); \
+ } \
} while (0);
+ orig_base = base;
+ ++cur;
+ raw_prefix_start = cur - base;
+ for (;;)
+ {
cppchar_t c;
/* If we previously performed any trigraph or line splicing
- transformations, undo them within the body of the raw string. */
+ transformations, undo them in between the opening and closing
+ double quote. */
while (note->pos < cur)
++note;
for (; note->pos == cur; ++note)
@@ -1414,23 +1584,13 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
++note;
goto after_backslash;
}
- /* The ) from ??) could be part of the suffix. */
- else if (type == ')'
- && strncmp ((const char *) cur+1,
- (const char *) raw_prefix,
- raw_prefix_len) == 0
- && cur[raw_prefix_len+1] == '"')
- {
- BUF_APPEND (")", 1);
- base++;
- cur += raw_prefix_len + 2;
- goto break_outer_loop;
- }
else
{
/* Skip the replacement character. */
base = ++cur;
BUF_APPEND (&type, 1);
+ c = type;
+ goto check_c;
}
}
else
@@ -1439,20 +1599,104 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
}
}
c = *cur++;
+ if (__builtin_expect (temp_buffer_len < 17, 0))
+ temp_buffer[temp_buffer_len++] = c;
- if (c == ')'
- && strncmp ((const char *) cur, (const char *) raw_prefix,
- raw_prefix_len) == 0
- && cur[raw_prefix_len] == '"')
+ check_c:
+ if (phase == RAW_STR_PREFIX)
{
- cur += raw_prefix_len + 1;
- break;
+ while (raw_prefix_len < temp_buffer_len)
+ {
+ raw_prefix[raw_prefix_len] = temp_buffer[raw_prefix_len];
+ switch (raw_prefix[raw_prefix_len])
+ {
+ case ' ': case '(': case ')': case '\\': case '\t':
+ case '\v': case '\f': case '\n': default:
+ break;
+ /* Basic source charset except the above chars. */
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+ case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+ case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z':
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ case '_': case '{': case '}': case '#': case '[': case ']':
+ case '<': case '>': case '%': case ':': case ';': case '.':
+ case '?': case '*': case '+': case '-': case '/': case '^':
+ case '&': case '|': case '~': case '!': case '=': case ',':
+ case '"': case '\'':
+ if (raw_prefix_len < 16)
+ {
+ raw_prefix_len++;
+ continue;
+ }
+ break;
+ }
+
+ if (raw_prefix[raw_prefix_len] != '(')
+ {
+ int col = CPP_BUF_COLUMN (pfile->buffer, cur) + 1;
+ if (raw_prefix_len == 16)
+ cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc,
+ col, "raw string delimiter longer "
+ "than 16 characters");
+ else if (raw_prefix[raw_prefix_len] == '\n')
+ cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc,
+ col, "invalid new-line in raw "
+ "string delimiter");
+ else
+ cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc,
+ col, "invalid character '%c' in "
+ "raw string delimiter",
+ (int) raw_prefix[raw_prefix_len]);
+ pfile->buffer->cur = orig_base + raw_prefix_start - 1;
+ create_literal (pfile, token, orig_base,
+ raw_prefix_start - 1, CPP_OTHER);
+ if (first_buff)
+ _cpp_release_buff (pfile, first_buff);
+ return;
+ }
+ raw_prefix[raw_prefix_len] = '"';
+ phase = RAW_STR;
+ /* Nothing should be appended to temp_buffer during
+ RAW_STR phase. */
+ temp_buffer_len = 17;
+ break;
+ }
+ continue;
+ }
+ else if (phase == RAW_STR_SUFFIX)
+ {
+ while (raw_suffix_len <= raw_prefix_len
+ && raw_suffix_len < temp_buffer_len
+ && temp_buffer[raw_suffix_len] == raw_prefix[raw_suffix_len])
+ raw_suffix_len++;
+ if (raw_suffix_len > raw_prefix_len)
+ break;
+ if (raw_suffix_len == temp_buffer_len)
+ continue;
+ phase = RAW_STR;
+ /* Nothing should be appended to temp_buffer during
+ RAW_STR phase. */
+ temp_buffer_len = 17;
+ }
+ if (c == ')')
+ {
+ phase = RAW_STR_SUFFIX;
+ raw_suffix_len = 0;
+ temp_buffer_len = 0;
}
else if (c == '\n')
{
if (pfile->state.in_directive
- || pfile->state.parsing_args
- || pfile->state.in_deferred_pragma)
+ || (pfile->state.parsing_args
+ && pfile->buffer->next_line >= pfile->buffer->rlimit))
{
cur--;
type = CPP_OTHER;
@@ -1487,18 +1731,31 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
note = &pfile->buffer->notes[pfile->buffer->cur_note];
}
}
- break_outer_loop:
if (CPP_OPTION (pfile, user_literals))
{
+ /* If a string format macro, say from inttypes.h, is placed touching
+ a string literal it could be parsed as a C++11 user-defined string
+ literal thus breaking the program.
+ Try to identify macros with is_macro. A warning is issued. */
+ if (is_macro (pfile, cur))
+ {
+ /* Raise a warning, but do not consume subsequent tokens. */
+ if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping)
+ cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
+ token->src_loc, 0,
+ "invalid suffix on literal; C++11 requires "
+ "a space between literal and string macro");
+ }
/* Grab user defined literal suffix. */
- if (ISIDST (*cur))
+ else if (ISIDST (*cur))
{
type = cpp_userdef_string_add_type (type);
++cur;
+
+ while (ISIDNUM (*cur))
+ ++cur;
}
- while (ISIDNUM (*cur))
- ++cur;
}
pfile->buffer->cur = cur;
@@ -1606,15 +1863,29 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
if (CPP_OPTION (pfile, user_literals))
{
+ /* If a string format macro, say from inttypes.h, is placed touching
+ a string literal it could be parsed as a C++11 user-defined string
+ literal thus breaking the program.
+ Try to identify macros with is_macro. A warning is issued. */
+ if (is_macro (pfile, cur))
+ {
+ /* Raise a warning, but do not consume subsequent tokens. */
+ if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping)
+ cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
+ token->src_loc, 0,
+ "invalid suffix on literal; C++11 requires "
+ "a space between literal and string macro");
+ }
/* Grab user defined literal suffix. */
- if (ISIDST (*cur))
+ else if (ISIDST (*cur))
{
type = cpp_userdef_char_add_type (type);
type = cpp_userdef_string_add_type (type);
++cur;
+
+ while (ISIDNUM (*cur))
+ ++cur;
}
- while (ISIDNUM (*cur))
- ++cur;
}
pfile->buffer->cur = cur;
@@ -2192,6 +2463,17 @@ _cpp_lex_direct (cpp_reader *pfile)
{
if (*buffer->cur == ':')
{
+ /* C++11 [2.5/3 lex.pptoken], "Otherwise, if the next
+ three characters are <:: and the subsequent character
+ is neither : nor >, the < is treated as a preprocessor
+ token by itself". */
+ if (CPP_OPTION (pfile, cplusplus)
+ && CPP_OPTION (pfile, lang) != CLK_CXX98
+ && CPP_OPTION (pfile, lang) != CLK_GNUCXX
+ && buffer->cur[1] == ':'
+ && buffer->cur[2] != ':' && buffer->cur[2] != '>')
+ break;
+
buffer->cur++;
result->flags |= DIGRAPH;
result->type = CPP_OPEN_SQUARE;
@@ -2636,6 +2918,15 @@ cpp_avoid_paste (cpp_reader *pfile, const cpp_token *token1,
|| (CPP_OPTION (pfile, objc)
&& token1->val.str.text[0] == '@'
&& (b == CPP_NAME || b == CPP_STRING)));
+ case CPP_STRING:
+ case CPP_WSTRING:
+ case CPP_UTF8STRING:
+ case CPP_STRING16:
+ case CPP_STRING32: return (CPP_OPTION (pfile, user_literals)
+ && (b == CPP_NAME
+ || (TOKEN_SPELL (token2) == SPELL_LITERAL
+ && ISIDST (token2->val.str.text[0]))));
+
default: break;
}
@@ -2734,8 +3025,17 @@ new_buff (size_t len)
len = MIN_BUFF_SIZE;
len = CPP_ALIGN (len);
+#ifdef ENABLE_VALGRIND_CHECKING
+ /* Valgrind warns about uses of interior pointers, so put _cpp_buff
+ struct first. */
+ size_t slen = CPP_ALIGN2 (sizeof (_cpp_buff), 2 * DEFAULT_ALIGNMENT);
+ base = XNEWVEC (unsigned char, len + slen);
+ result = (_cpp_buff *) base;
+ base += slen;
+#else
base = XNEWVEC (unsigned char, len + sizeof (_cpp_buff));
result = (_cpp_buff *) (base + len);
+#endif
result->base = base;
result->cur = base;
result->limit = base + len;
@@ -2822,7 +3122,11 @@ _cpp_free_buff (_cpp_buff *buff)
for (; buff; buff = next)
{
next = buff->next;
+#ifdef ENABLE_VALGRIND_CHECKING
+ free (buff);
+#else
free (buff->base);
+#endif
}
}
@@ -2876,7 +3180,7 @@ _cpp_aligned_alloc (cpp_reader *pfile, size_t len)
/* Say which field of TOK is in use. */
enum cpp_token_fld_kind
-cpp_token_val_index (cpp_token *tok)
+cpp_token_val_index (const cpp_token *tok)
{
switch (TOKEN_SPELL (tok))
{