diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-07-21 04:28:03 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-07-21 04:28:03 +0200 |
commit | 8cf887352b795b59e9666513f8c8ca0c0908a38c (patch) | |
tree | 6ed6396fa7b067df8a3ff310a4f33ede51228e59 /libcpp | |
parent | a1d6f2a23f5d336b13d7d1a2a5306ec785cdbd74 (diff) | |
download | gcc-8cf887352b795b59e9666513f8c8ca0c0908a38c.tar.gz |
re PR preprocessor/57620 (Phantom terminator confuses raw string literal parsing.)
PR preprocessor/57620
* lex.c (lex_raw_string): Undo phase1 and phase2 transformations
between R" and final " rather than only in between R"del( and )del".
* c-c++-common/raw-string-2.c (s12, u12, U12, L12): Remove.
(main): Don't test {s,u,U,L}12.
* c-c++-common/raw-string-13.c: New test.
* c-c++-common/raw-string-14.c: New test.
* c-c++-common/raw-string-15.c: New test.
* c-c++-common/raw-string-16.c: New test.
From-SVN: r201091
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/ChangeLog | 6 | ||||
-rw-r--r-- | libcpp/lex.c | 191 |
2 files changed, 124 insertions, 73 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 9213232aa98..dd107aec089 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2013-07-20 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/57620 + * lex.c (lex_raw_string): Undo phase1 and phase2 transformations + between R" and final " rather than only in between R"del( and )del". + 2013-07-10 Jakub Jelinek <jakub@redhat.com> PR preprocessor/57824 diff --git a/libcpp/lex.c b/libcpp/lex.c index fc89bafd81b..ed794d5b004 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1373,11 +1373,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 : @@ -1385,68 +1394,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) @@ -1506,23 +1478,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 @@ -1531,14 +1493,98 @@ 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') { @@ -1579,7 +1625,6 @@ 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)) { |