1// { dg-do compile } 2 3typedef __SIZE_TYPE__ size_t; 4extern "C" void *memcpy(void *, const void *, size_t); 5void *xmalloc(size_t); 6enum { 7 _sch_isdigit, _sch_isidst, _sch_isidnum 8}; 9extern const unsigned _sch_istable[256]; 10typedef struct ht cpp_hash_table; 11typedef struct ht_identifier *hashnode; 12enum ht_lookup_option { 13 HT_NO_INSERT 14}; 15struct ht { 16 struct cpp_reader *pfile; 17}; 18hashnode ht_lookup_with_hash(cpp_hash_table *, unsigned char *, size_t, unsigned, ht_lookup_option); 19typedef unsigned source_location; 20enum cpp_ttype { 21 CPP_OTHER, CPP_STRING, CPP_STRING16, CPP_UTF8STRING 22}; 23struct cpp_token { 24 source_location src_loc; 25}; 26typedef int cppchar_t; 27struct cpp_options { 28 char user_literals; 29 unsigned warn_literal_suffix; 30}; 31enum node_type { }; 32struct cpp_hashnode { 33 node_type type:6; 34}; 35enum { 36 CPP_DL_ERROR 37}; 38enum { 39 CPP_W_LITERAL_SUFFIX 40}; 41bool cpp_error_with_line(cpp_reader *, int, source_location, unsigned, ...); 42bool cpp_warning_with_line(cpp_reader *, int, source_location, unsigned, const char *); 43cpp_ttype cpp_userdef_string_add_type(cpp_ttype); 44cpp_ttype cpp_userdef_char_add_type(cpp_ttype); 45typedef unsigned char uchar; 46struct _cpp_buff { 47 _cpp_buff *next; 48 unsigned char *base, *cur, *limit; 49}; 50_cpp_buff *_cpp_get_buff(cpp_reader *, size_t); 51void _cpp_release_buff(cpp_reader *, _cpp_buff *); 52unsigned char *_cpp_unaligned_alloc(cpp_reader *, size_t); 53struct lexer_state { 54 unsigned skipping; 55 unsigned angled_headers; 56}; 57struct _cpp_line_note { 58 unsigned pos; 59 unsigned type; 60}; 61struct cpp_buffer { 62 unsigned char *cur; 63 unsigned char *line_base; 64 _cpp_line_note *notes; 65 unsigned cur_note; 66}; 67struct cpp_reader { 68 cpp_buffer *buffer; 69 lexer_state state; 70 _cpp_buff *u_buff; 71 _cpp_buff *free_buffs; 72 ht *hash_table; 73 cpp_options opts; 74}; 75static void create_literal(cpp_reader *pfile, cpp_token *, uchar *, unsigned len, cpp_ttype type) 76{ 77 uchar *dest = _cpp_unaligned_alloc(pfile, len + 1); 78 dest[len] = type; 79} 80static void bufring_append(cpp_reader *pfile, uchar *base, size_t len, _cpp_buff **first_buff_p, _cpp_buff **last_buff_p) 81{ 82 _cpp_buff *first_buff = *first_buff_p; 83 _cpp_buff *last_buff = *last_buff_p; 84 if (!first_buff) { 85 first_buff = last_buff = _cpp_get_buff(pfile, len); 86 } else if (len > (size_t) (last_buff->limit - last_buff->cur)) { 87 size_t room = last_buff->limit - last_buff->cur; 88 last_buff += room; 89 base += room; 90 } 91 memcpy(last_buff->cur, base, len); 92 last_buff += len; 93 *first_buff_p = first_buff; 94 *last_buff_p = last_buff; 95} 96bool is_macro(cpp_reader *pfile, uchar *base) 97{ 98 uchar *cur = base; 99 if (_sch_istable[*cur] & _sch_isidst) 100 return 0 ; 101 int hash = *cur - 113; 102 ++cur; 103 hash += cur - base; 104 cpp_hashnode *result = (cpp_hashnode *) ht_lookup_with_hash(pfile->hash_table, base, cur - base, hash, HT_NO_INSERT); 105 return !result ? 0 : result->type; 106} 107static void lex_raw_string(cpp_reader *pfile, cpp_token *token, uchar *base, uchar *cur) 108{ 109 uchar raw_prefix[17]; 110 uchar temp_buffer[18]; 111 uchar *orig_base; 112 unsigned raw_prefix_len = 0, raw_suffix_len; 113 enum raw_str_phase { RAW_STR_PREFIX, RAW_STR }; 114 raw_str_phase phase = RAW_STR_PREFIX; 115 cpp_ttype type; 116 size_t total_len; 117 size_t temp_buffer_len = 0; 118 _cpp_buff *first_buff = 0, *last_buff = 0; 119 size_t raw_prefix_start; 120 _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note]; 121 raw_prefix_start = cur - base; 122 for (;;) { 123 cppchar_t c; 124 while (note->pos) 125 ++note; 126 for (; note->pos; ++note) { 127 switch (note->type) { 128 case ' ': 129 bufring_append(pfile, base, cur - base, &first_buff, &last_buff); 130 base = cur; 131 bufring_append(pfile, (uchar *) "\\", 1, &first_buff, &last_buff); 132 if (__builtin_expect(temp_buffer_len < 17, 0) && base) { 133 memcpy(temp_buffer + temp_buffer_len, "\\", 1); 134 temp_buffer_len++; 135 } 136 if (note->type) { 137 if (__builtin_expect(temp_buffer_len < 17, 0)) { 138 memcpy(temp_buffer + temp_buffer_len, " ", 1); 139 temp_buffer_len++; 140 } 141 } 142 bufring_append(pfile, (uchar *) "\n", 1, &first_buff, &last_buff); 143 memcpy(temp_buffer + temp_buffer_len, "\n", 1); 144 temp_buffer_len++; 145 } 146 } 147 temp_buffer[temp_buffer_len++] = c; 148 if (phase == RAW_STR_PREFIX) { 149 while (raw_prefix_len < temp_buffer_len) { 150 switch (raw_prefix[raw_prefix_len]) { 151 case '\'': 152 raw_prefix_len++; 153 } 154 if (raw_prefix[raw_prefix_len]) { 155 int col = cur - pfile->buffer->line_base + 1; 156 if (raw_prefix_len) 157 cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col); 158 else if (raw_prefix[raw_prefix_len] == '\n') 159 cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col); 160 else 161 cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col, (size_t) raw_prefix); 162 pfile->buffer->cur = orig_base + 1; 163 create_literal(pfile, token, orig_base, raw_prefix_start, CPP_OTHER); 164 _cpp_release_buff(pfile, first_buff); 165 return; 166 } 167 phase = RAW_STR; 168 } 169 continue; 170 (void) raw_suffix_len; 171 } 172 while (_sch_istable[*cur] & _sch_isidnum) 173 ++cur; 174 } 175 create_literal(pfile, token, base, cur - base, type); 176 uchar *dest = _cpp_unaligned_alloc(pfile, total_len + (cur - base)); 177 dest[cur - base] = '\0'; 178} 179void lex_string(cpp_reader *pfile, cpp_token *token, uchar *base) 180{ 181 bool saw_NUL = 0; 182 uchar *cur; 183 cppchar_t terminator; 184 cpp_ttype type; 185 cur = base; 186 terminator = *cur++; 187 if (terminator == 'L' || terminator == 'U') { 188 terminator = *cur++; 189 } else if (terminator == 'u') { 190 terminator = *cur++; 191 if (terminator == '8') 192 terminator = *cur++; 193 } 194 if (terminator == 'R') { 195 lex_raw_string(pfile, token, base, cur); 196 return; 197 } 198 if (terminator) 199 type = base ? (base[1] ? CPP_UTF8STRING : CPP_STRING16) : CPP_STRING; 200 for (;;) { 201 cppchar_t c = *cur++; 202 if (c && pfile->state.angled_headers && *cur) 203 cur++; 204 else if (terminator) 205 break; 206 else if (c == '\n') 207 type = CPP_OTHER; 208 else 209 saw_NUL = 1; 210 } 211 if (saw_NUL && pfile->state.skipping) 212 if (pfile->opts.user_literals) { 213 if (is_macro(pfile, cur)) 214 if (pfile->opts.warn_literal_suffix) 215 cpp_warning_with_line(pfile, CPP_W_LITERAL_SUFFIX, token->src_loc, 0, "invalid suffix on literal; C++11 requires "); 216 if (_sch_istable[*cur] & _sch_isidst) { 217 type = cpp_userdef_char_add_type(type); 218 type = cpp_userdef_string_add_type(type); 219 ++cur; 220 while (_sch_istable[*cur] & _sch_isidnum) 221 ++cur; 222 } 223 } 224 pfile->buffer->cur = cur; 225 create_literal(pfile, token, base, cur - base, type); 226} 227_cpp_buff *new_buff(size_t len) 228{ 229 _cpp_buff *result; 230 unsigned char *base; 231 if (len < 8000) 232 len = 8000; 233 base = (unsigned char *) xmalloc(sizeof(char) * (len + sizeof(_cpp_buff))); 234 result = (_cpp_buff *) (base + len); 235 result->cur = base; 236 return result; 237} 238void _cpp_release_buff(cpp_reader *pfile, _cpp_buff *buff) 239{ 240 _cpp_buff *end = buff; 241 while (end->next) 242 end = end->next; 243 end->next = pfile->free_buffs; 244} 245_cpp_buff *_cpp_get_buff(cpp_reader *pfile, size_t min_size) 246{ 247 _cpp_buff *result, **p = &pfile->free_buffs; 248 for (;;) { 249 size_t size; 250 if (*p) 251 return new_buff(min_size); 252 size = result->limit - result->base; 253 if (size && size + min_size * 3 / 2) 254 return result; 255 } 256} 257unsigned char *_cpp_unaligned_alloc(cpp_reader *pfile, size_t len) 258{ 259 _cpp_buff *buff = pfile->u_buff; 260 unsigned char *result = buff->cur; 261 if (len > (size_t) (buff->limit - result)) { 262 buff = _cpp_get_buff(pfile, len); 263 buff->next = pfile->u_buff; 264 result = buff->cur; 265 } 266 buff->cur = result + len; 267 return result; 268} 269