| @@ -1290,6 +1290,7 @@ static void put_extern_sym2(Sym *sym, Section *section, · 1289 unmodified lines |
| 1290 | 1290 | case TOK_memset: |
| 1291 | 1291 | case TOK_strlen: |
| 1292 | 1292 | case TOK_strcpy: |
| 1293 | + case TOK__alloca: |
| 1293 | 1294 | strcpy(buf, "__bound_"); |
| 1294 | 1295 | strcat(buf, name); |
| 1295 | 1296 | name = buf; |
| @@ -3123,6 +3124,8 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long · 1827 unmodified lines |
| 3123 | 3124 | c = n; |
| 3124 | 3125 | goto add_char_nonext; |
| 3125 | 3126 | case 'x': |
| 3127 | + case 'u': |
| 3128 | + case 'U': |
| 3126 | 3129 | p++; |
| 3127 | 3130 | n = 0; |
| 3128 | 3131 | for(;;) { |
| @@ -4360,7 +4363,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 1231 unmodified lines |
| 4360 | 4363 | ptr = (int *)macro_ptr; |
| 4361 | 4364 | macro_ptr = ml.p; |
| 4362 | 4365 | if (can_read_stream && *can_read_stream == &ml) |
| 4363 | | − *can_read_stream = ml.prev; |
| 4366 | + *can_read_stream = ml.prev; |
| 4364 | 4367 | if (ret != 0) |
| 4365 | 4368 | goto no_subst; |
| 4366 | 4369 | } else { |
| @@ -5298,8 +5301,8 @@ void gen_opl(int op) · 931 unmodified lines |
| 5298 | 5301 | #if defined(TCC_TARGET_I386) |
| 5299 | 5302 | b = psym(0x850f, 0); |
| 5300 | 5303 | #elif defined(TCC_TARGET_ARM) |
| 5301 | | − b = ind; |
| 5302 | | − o(0x1A000000 | encbranch(ind, 0, 1)); |
| 5304 | + b = ind; |
| 5305 | + o(0x1A000000 | encbranch(ind, 0, 1)); |
| 5303 | 5306 | #elif defined(TCC_TARGET_C67) |
| 5304 | 5307 | error("not implemented"); |
| 5305 | 5308 | #else |
| @@ -5329,23 +5332,29 @@ void gen_opl(int op) · 23 unmodified lines |
| 5329 | 5332 | independent opt */ |
| 5330 | 5333 | void gen_opic(int op) |
| 5331 | 5334 | { |
| 5332 | | − int fc, c1, c2, n; |
| 5335 | + int c1, c2, t1, t2, n, c; |
| 5333 | 5336 | SValue *v1, *v2; |
| 5337 | + long long l1, l2, l; |
| 5338 | + typedef unsigned long long U; |
| 5334 | 5339 | |
| 5335 | 5340 | v1 = vtop - 1; |
| 5336 | 5341 | v2 = vtop; |
| 5342 | + t1 = v1->type.t & VT_BTYPE; |
| 5343 | + t2 = v2->type.t & VT_BTYPE; |
| 5344 | + l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i; |
| 5345 | + l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i; |
| 5346 | + |
| 5337 | 5347 | /* currently, we cannot do computations with forward symbols */ |
| 5338 | 5348 | c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
| 5339 | 5349 | c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
| 5340 | 5350 | if (c1 && c2) { |
| 5341 | | − fc = v2->c.i; |
| 5342 | 5351 | switch(op) { |
| 5343 | | − case '+': v1->c.i += fc; break; |
| 5344 | | − case '-': v1->c.i -= fc; break; |
| 5345 | | − case '&': v1->c.i &= fc; break; |
| 5346 | | − case '^': v1->c.i ^= fc; break; |
| 5347 | | − case '|': v1->c.i |= fc; break; |
| 5348 | | − case '*': v1->c.i *= fc; break; |
| 5352 | + case '+': l1 += l2; break; |
| 5353 | + case '-': l1 -= l2; break; |
| 5354 | + case '&': l1 &= l2; break; |
| 5355 | + case '^': l1 ^= l2; break; |
| 5356 | + case '|': l1 |= l2; break; |
| 5357 | + case '*': l1 *= l2; break; |
| 5349 | 5358 | |
| 5350 | 5359 | case TOK_PDIV: |
| 5351 | 5360 | case '/': |
| @@ -5353,66 +5362,68 @@ void gen_opic(int op) · 1 unmodified line |
| 5353 | 5362 | case TOK_UDIV: |
| 5354 | 5363 | case TOK_UMOD: |
| 5355 | 5364 | /* if division by zero, generate explicit division */ |
| 5356 | | − if (fc == 0) { |
| 5365 | + if (l2 == 0) { |
| 5357 | 5366 | if (const_wanted) |
| 5358 | 5367 | error("division by zero in constant"); |
| 5359 | 5368 | goto general_case; |
| 5360 | 5369 | } |
| 5361 | 5370 | switch(op) { |
| 5362 | | − default: v1->c.i /= fc; break; |
| 5363 | | − case '%': v1->c.i %= fc; break; |
| 5364 | | − case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; |
| 5365 | | − case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; |
| 5371 | + default: l1 /= l2; break; |
| 5372 | + case '%': l1 %= l2; break; |
| 5373 | + case TOK_UDIV: l1 = (U)l1 / l2; break; |
| 5374 | + case TOK_UMOD: l1 = (U)l1 % l2; break; |
| 5366 | 5375 | } |
| 5367 | 5376 | break; |
| 5368 | | − case TOK_SHL: v1->c.i <<= fc; break; |
| 5369 | | − case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break; |
| 5370 | | − case TOK_SAR: v1->c.i >>= fc; break; |
| 5377 | + case TOK_SHL: l1 <<= l2; break; |
| 5378 | + case TOK_SHR: l1 = (U)l1 >> l2; break; |
| 5379 | + case TOK_SAR: l1 >>= l2; break; |
| 5371 | 5380 | /* tests */ |
| 5372 | | − case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break; |
| 5373 | | − case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break; |
| 5374 | | − case TOK_EQ: v1->c.i = v1->c.i == fc; break; |
| 5375 | | − case TOK_NE: v1->c.i = v1->c.i != fc; break; |
| 5376 | | − case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break; |
| 5377 | | − case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break; |
| 5378 | | − case TOK_LT: v1->c.i = v1->c.i < fc; break; |
| 5379 | | − case TOK_GE: v1->c.i = v1->c.i >= fc; break; |
| 5380 | | − case TOK_LE: v1->c.i = v1->c.i <= fc; break; |
| 5381 | | − case TOK_GT: v1->c.i = v1->c.i > fc; break; |
| 5381 | + case TOK_ULT: l1 = (U)l1 < (U)l2; break; |
| 5382 | + case TOK_UGE: l1 = (U)l1 >= (U)l2; break; |
| 5383 | + case TOK_EQ: l1 = l1 == l2; break; |
| 5384 | + case TOK_NE: l1 = l1 != l2; break; |
| 5385 | + case TOK_ULE: l1 = (U)l1 <= (U)l2; break; |
| 5386 | + case TOK_UGT: l1 = (U)l1 > (U)l2; break; |
| 5387 | + case TOK_LT: l1 = l1 < l2; break; |
| 5388 | + case TOK_GE: l1 = l1 >= l2; break; |
| 5389 | + case TOK_LE: l1 = l1 <= l2; break; |
| 5390 | + case TOK_GT: l1 = l1 > l2; break; |
| 5382 | 5391 | /* logical */ |
| 5383 | | − case TOK_LAND: v1->c.i = v1->c.i && fc; break; |
| 5384 | | − case TOK_LOR: v1->c.i = v1->c.i || fc; break; |
| 5392 | + case TOK_LAND: l1 = l1 && l2; break; |
| 5393 | + case TOK_LOR: l1 = l1 || l2; break; |
| 5385 | 5394 | default: |
| 5386 | 5395 | goto general_case; |
| 5387 | 5396 | } |
| 5397 | + v1->c.ll = l1; |
| 5388 | 5398 | vtop--; |
| 5389 | 5399 | } else { |
| 5390 | 5400 | /* if commutative ops, put c2 as constant */ |
| 5391 | 5401 | if (c1 && (op == '+' || op == '&' || op == '^' || |
| 5392 | 5402 | op == '|' || op == '*')) { |
| 5393 | 5403 | vswap(); |
| 5394 | | − swap(&c1, &c2); |
| 5404 | + c = c1, c1 = c2, c2 = c; |
| 5405 | + l = l1, l1 = l2, l2 = l; |
| 5395 | 5406 | } |
| 5396 | | − fc = vtop->c.i; |
| 5407 | + /* Filter out NOP operations like x*1, x-0, x&-1... */ |
| 5397 | 5408 | if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || |
| 5398 | 5409 | op == TOK_PDIV) && |
| 5399 | | − fc == 1) || |
| 5410 | + l2 == 1) || |
| 5400 | 5411 | ((op == '+' || op == '-' || op == '|' || op == '^' || |
| 5401 | 5412 | op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && |
| 5402 | | − fc == 0) || |
| 5413 | + l2 == 0) || |
| 5403 | 5414 | (op == '&' && |
| 5404 | | − fc == -1))) { |
| 5415 | + l2 == -1))) { |
| 5405 | 5416 | /* nothing to do */ |
| 5406 | 5417 | vtop--; |
| 5407 | 5418 | } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { |
| 5408 | 5419 | /* try to use shifts instead of muls or divs */ |
| 5409 | | − if (fc > 0 && (fc & (fc - 1)) == 0) { |
| 5420 | + if (l2 > 0 && (l2 & (l2 - 1)) == 0) { |
| 5410 | 5421 | n = -1; |
| 5411 | | − while (fc) { |
| 5412 | | − fc >>= 1; |
| 5422 | + while (l2) { |
| 5423 | + l2 >>= 1; |
| 5413 | 5424 | n++; |
| 5414 | 5425 | } |
| 5415 | | − vtop->c.i = n; |
| 5426 | + vtop->c.ll = n; |
| 5416 | 5427 | if (op == '*') |
| 5417 | 5428 | op = TOK_SHL; |
| 5418 | 5429 | else if (op == TOK_PDIV) |
| @@ -5426,14 +5437,17 @@ void gen_opic(int op) · 7 unmodified lines |
| 5426 | 5437 | (VT_CONST | VT_SYM)) { |
| 5427 | 5438 | /* symbol + constant case */ |
| 5428 | 5439 | if (op == '-') |
| 5429 | | − fc = -fc; |
| 5440 | + l2 = -l2; |
| 5430 | 5441 | vtop--; |
| 5431 | | − vtop->c.i += fc; |
| 5442 | + vtop->c.ll += l2; |
| 5432 | 5443 | } else { |
| 5433 | 5444 | general_case: |
| 5434 | 5445 | if (!nocode_wanted) { |
| 5435 | 5446 | /* call low level op generator */ |
| 5436 | | − gen_opi(op); |
| 5447 | + if (t1 == VT_LLONG || t2 == VT_LLONG) |
| 5448 | + gen_opl(op); |
| 5449 | + else |
| 5450 | + gen_opi(op); |
| 5437 | 5451 | } else { |
| 5438 | 5452 | vtop--; |
| 5439 | 5453 | } |
| @@ -5540,7 +5554,8 @@ static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) · 100 unmodified lines |
| 5540 | 5554 | bt2 = type2->t & VT_BTYPE; |
| 5541 | 5555 | /* accept comparison between pointer and integer with a warning */ |
| 5542 | 5556 | if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') { |
| 5543 | | − warning("comparison between pointer and integer"); |
| 5557 | + if (op != TOK_LOR && op != TOK_LAND ) |
| 5558 | + warning("comparison between pointer and integer"); |
| 5544 | 5559 | return; |
| 5545 | 5560 | } |
| 5546 | 5561 | |
| @@ -5586,7 +5601,7 @@ void gen_op(int op) · 39 unmodified lines |
| 5586 | 5601 | if (bt1 == VT_PTR || bt2 == VT_PTR) { |
| 5587 | 5602 | /* at least one operand is a pointer */ |
| 5588 | 5603 | /* relationnal op: must be both pointers */ |
| 5589 | | − if (op >= TOK_ULT && op <= TOK_GT) { |
| 5604 | + if (op >= TOK_ULT && op <= TOK_LOR) { |
| 5590 | 5605 | check_comparison_pointer_types(vtop - 1, vtop, op); |
| 5591 | 5606 | /* pointers are handled are unsigned */ |
| 5592 | 5607 | t = VT_INT | VT_UNSIGNED; |
| @@ -5696,8 +5711,6 @@ void gen_op(int op) · 103 unmodified lines |
| 5696 | 5711 | gen_cast(&type1); |
| 5697 | 5712 | if (is_float(t)) |
| 5698 | 5713 | gen_opif(op); |
| 5699 | | − else if ((t & VT_BTYPE) == VT_LLONG) |
| 5700 | | − gen_opl(op); |
| 5701 | 5714 | else |
| 5702 | 5715 | gen_opic(op); |
| 5703 | 5716 | if (op >= TOK_ULT && op <= TOK_GT) { |
| @@ -5947,6 +5960,11 @@ static void gen_cast(CType *type) · 243 unmodified lines |
| 5947 | 5960 | the lvalue already contains the real type size (see |
| 5948 | 5961 | VT_LVAL_xxx constants) */ |
| 5949 | 5962 | } |
| 5963 | + } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) { |
| 5964 | + /* if we are casting between pointer types, |
| 5965 | + we must update the VT_LVAL_xxx size */ |
| 5966 | + vtop->r = (vtop->r & ~VT_LVAL_TYPE) |
| 5967 | + | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE); |
| 5950 | 5968 | } |
| 5951 | 5969 | vtop->type = *type; |
| 5952 | 5970 | } |
| @@ -6502,12 +6520,15 @@ static void parse_attribute(AttributeDef *ad) · 549 unmodified lines |
| 6502 | 6520 | if (tcc_state->warn_unsupported) |
| 6503 | 6521 | warning("'%s' attribute ignored", get_tok_str(t, NULL)); |
| 6504 | 6522 | /* skip parameters */ |
| 6505 | | − /* XXX: skip parenthesis too */ |
| 6506 | 6523 | if (tok == '(') { |
| 6507 | | − next(); |
| 6508 | | − while (tok != ')' && tok != -1) |
| 6524 | + int parenthesis = 0; |
| 6525 | + do { |
| 6526 | + if (tok == '(') |
| 6527 | + parenthesis++; |
| 6528 | + else if (tok == ')') |
| 6529 | + parenthesis--; |
| 6509 | 6530 | next(); |
| 6510 | | − next(); |
| 6531 | + } while (parenthesis && tok != -1); |
| 6511 | 6532 | } |
| 6512 | 6533 | break; |
| 6513 | 6534 | } |
| @@ -6668,7 +6689,8 @@ static void struct_decl(CType *type, int u) · 154 unmodified lines |
| 6668 | 6689 | if (a == TOK_STRUCT) { |
| 6669 | 6690 | c = (c + align - 1) & -align; |
| 6670 | 6691 | offset = c; |
| 6671 | | − c += size; |
| 6692 | + if (size > 0) |
| 6693 | + c += size; |
| 6672 | 6694 | } else { |
| 6673 | 6695 | offset = 0; |
| 6674 | 6696 | if (size > c) |
| @@ -6719,13 +6741,14 @@ static void struct_decl(CType *type, int u) · 44 unmodified lines |
| 6719 | 6741 | */ |
| 6720 | 6742 | static int parse_btype(CType *type, AttributeDef *ad) |
| 6721 | 6743 | { |
| 6722 | | − int t, u, type_found, typespec_found; |
| 6744 | + int t, u, type_found, typespec_found, typedef_found; |
| 6723 | 6745 | Sym *s; |
| 6724 | 6746 | CType type1; |
| 6725 | 6747 | |
| 6726 | 6748 | memset(ad, 0, sizeof(AttributeDef)); |
| 6727 | 6749 | type_found = 0; |
| 6728 | 6750 | typespec_found = 0; |
| 6751 | + typedef_found = 0; |
| 6729 | 6752 | t = 0; |
| 6730 | 6753 | while(1) { |
| 6731 | 6754 | switch(tok) { |
| @@ -6809,9 +6832,9 @@ static int parse_btype(CType *type, AttributeDef *ad) · 77 unmodified lines |
| 6809 | 6832 | case TOK_SIGNED2: |
| 6810 | 6833 | case TOK_SIGNED3: |
| 6811 | 6834 | typespec_found = 1; |
| 6812 | | − t |= VT_SIGNED; |
| 6813 | | − next(); |
| 6814 | | − break; |
| 6835 | + t |= VT_SIGNED; |
| 6836 | + next(); |
| 6837 | + break; |
| 6815 | 6838 | case TOK_REGISTER: |
| 6816 | 6839 | case TOK_AUTO: |
| 6817 | 6840 | case TOK_RESTRICT1: |
| @@ -6858,11 +6881,12 @@ static int parse_btype(CType *type, AttributeDef *ad) · 40 unmodified lines |
| 6858 | 6881 | parse_expr_type(&type1); |
| 6859 | 6882 | goto basic_type2; |
| 6860 | 6883 | default: |
| 6861 | | − if (typespec_found) |
| 6884 | + if (typespec_found || typedef_found) |
| 6862 | 6885 | goto the_end; |
| 6863 | 6886 | s = sym_find(tok); |
| 6864 | 6887 | if (!s || !(s->type.t & VT_TYPEDEF)) |
| 6865 | 6888 | goto the_end; |
| 6889 | + typedef_found = 1; |
| 6866 | 6890 | t |= (s->type.t & ~VT_TYPEDEF); |
| 6867 | 6891 | type->ref = s->type.ref; |
| 6868 | 6892 | next(); |
| @@ -8164,6 +8188,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 1295 unmodified lines |
| 8164 | 8188 | int v1, v2; |
| 8165 | 8189 | if (!case_sym) |
| 8166 | 8190 | expect("switch"); |
| 8191 | + /* since a case is like a label, we must skip it with a jmp */ |
| 8192 | + b = gjmp(0); |
| 8193 | + next_case: |
| 8167 | 8194 | next(); |
| 8168 | 8195 | v1 = expr_const(); |
| 8169 | 8196 | v2 = v1; |
| @@ -8173,24 +8200,26 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 3 unmodified lines |
| 8173 | 8200 | if (v2 < v1) |
| 8174 | 8201 | warning("empty case range"); |
| 8175 | 8202 | } |
| 8176 | | − /* since a case is like a label, we must skip it with a jmp */ |
| 8177 | | − b = gjmp(0); |
| 8178 | 8203 | gsym(*case_sym); |
| 8179 | 8204 | vseti(case_reg, 0); |
| 8180 | 8205 | vpushi(v1); |
| 8181 | 8206 | if (v1 == v2) { |
| 8182 | 8207 | gen_op(TOK_EQ); |
| 8183 | | − *case_sym = gtst(1, 0); |
| 8208 | + *case_sym = 0; |
| 8184 | 8209 | } else { |
| 8185 | 8210 | gen_op(TOK_GE); |
| 8186 | 8211 | *case_sym = gtst(1, 0); |
| 8187 | 8212 | vseti(case_reg, 0); |
| 8188 | 8213 | vpushi(v2); |
| 8189 | 8214 | gen_op(TOK_LE); |
| 8190 | | − *case_sym = gtst(1, *case_sym); |
| 8191 | 8215 | } |
| 8192 | | − gsym(b); |
| 8193 | 8216 | skip(':'); |
| 8217 | + if (tok == TOK_CASE) { |
| 8218 | + b = gtst(0, b); |
| 8219 | + goto next_case; |
| 8220 | + } |
| 8221 | + *case_sym = gtst(1, *case_sym); |
| 8222 | + gsym(b); |
| 8194 | 8223 | is_expr = 0; |
| 8195 | 8224 | goto block_after_label; |
| 8196 | 8225 | } else |
| @@ -8873,11 +8902,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 676 unmodified lines |
| 8873 | 8902 | } |
| 8874 | 8903 | |
| 8875 | 8904 | if (v) { |
| 8876 | | − if (scope == VT_CONST) { |
| 8877 | | − if (!sym) |
| 8878 | | − goto do_def; |
| 8879 | | − } else { |
| 8880 | | − do_def: |
| 8905 | + if (scope != VT_CONST || !sym) { |
| 8881 | 8906 | sym = sym_push(v, type, r | VT_SYM, 0); |
| 8882 | 8907 | } |
| 8883 | 8908 | /* update symbol definition */ |