|
1 | 1 | %{ |
2 | | -/* $NetBSD: cgram.y,v 1.537 2026/03/16 20:09:15 rillig Exp $ */ |
| 2 | +/* $NetBSD: cgram.y,v 1.538 2026/03/18 06:17:55 rillig Exp $ */ |
3 | 3 |
|
4 | 4 | /* |
5 | 5 | * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. |
|
35 | 35 |
|
36 | 36 | #include <sys/cdefs.h> |
37 | 37 | #if defined(__RCSID) |
38 | | -__RCSID("$NetBSD: cgram.y,v 1.537 2026/03/16 20:09:15 rillig Exp $"); |
| 38 | +__RCSID("$NetBSD: cgram.y,v 1.538 2026/03/18 06:17:55 rillig Exp $"); |
39 | 39 | #endif |
40 | 40 |
|
41 | 41 | #include <limits.h> |
@@ -148,6 +148,15 @@ new_attribute(const sbuf_t *prefix, const sbuf_t *name, |
148 | 148 | return attr; |
149 | 149 | } |
150 | 150 |
|
| 151 | +static tnode_t * |
| 152 | +unconst_tnode(const tnode_t *p) |
| 153 | +{ |
| 154 | + void *r; |
| 155 | + |
| 156 | + memcpy(&r, &p, sizeof(r)); |
| 157 | + return r; |
| 158 | +} |
| 159 | + |
151 | 160 | #if YYDEBUG && YYBYACC |
152 | 161 | #define YYSTYPE_TOSTRING cgram_to_string |
153 | 162 | #endif |
@@ -175,7 +184,7 @@ new_attribute(const sbuf_t *prefix, const sbuf_t *name, |
175 | 184 | buffer *y_string; |
176 | 185 | qual_ptr *y_qual_ptr; |
177 | 186 | bool y_seen_statement; |
178 | | - struct generic_association *y_generic; |
| 187 | + struct generic_selection y_generic_selection; |
179 | 188 | array_size y_array_size; |
180 | 189 | bool y_in_system_header; |
181 | 190 | designation y_designation; |
@@ -238,7 +247,7 @@ new_attribute(const sbuf_t *prefix, const sbuf_t *name, |
238 | 247 | fprintf(yyo, "%s *", type_qualifiers_string($$->qualifiers)); |
239 | 248 | } <y_qual_ptr> |
240 | 249 | %printer { fprintf(yyo, "%s", $$ ? "yes" : "no"); } <y_seen_statement> |
241 | | -%printer { fprintf(yyo, "%s", type_name($$->ga_arg)); } <y_generic> |
| 250 | +%printer { fprintf(yyo, "%s", type_name($$.expr_type)); } <y_generic_selection> |
242 | 251 | %printer { fprintf(yyo, "%d", $$.dim); } <y_array_size> |
243 | 252 | %printer { fprintf(yyo, "%s", $$ ? "yes" : "no"); } <y_in_system_header> |
244 | 253 | %printer { |
@@ -354,8 +363,7 @@ new_attribute(const sbuf_t *prefix, const sbuf_t *name, |
354 | 363 | %type <y_tnode> primary_expression |
355 | 364 | %type <y_designation> member_designator |
356 | 365 | %type <y_tnode> generic_selection |
357 | | -%type <y_generic> generic_assoc_list |
358 | | -%type <y_generic> generic_association |
| 366 | +%type <y_generic_selection> generic_inner |
359 | 367 | %type <y_tnode> postfix_expression |
360 | 368 | %type <y_tnode> gcc_statement_expr_list |
361 | 369 | %type <y_tnode> gcc_statement_expr_item |
@@ -605,37 +613,46 @@ member_designator: |
605 | 613 |
|
606 | 614 | /* K&R ---, C90 ---, C99 ---, C11 6.5.1.1, C23 6.5.2.1 */ |
607 | 615 | generic_selection: |
608 | | - T_GENERIC T_LPAREN { |
609 | | - push_evaluation_mode(EM_TYPE); |
610 | | - } assignment_expression { |
611 | | - pop_evaluation_mode(); |
612 | | - } T_COMMA generic_assoc_list T_RPAREN { |
| 616 | + T_GENERIC { |
613 | 617 | /* generic selection requires C11 or later */ |
614 | 618 | c11ism(345); |
615 | | - $$ = build_generic_selection($4, $7); |
| 619 | + } T_LPAREN generic_inner T_RPAREN { |
| 620 | + $$ = $4.matched != NULL ? $4.matched : $4.fallback; |
616 | 621 | } |
617 | 622 | ; |
618 | 623 |
|
619 | | -/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1, C23 6.5.2.1 */ |
620 | | -generic_assoc_list: |
621 | | - generic_association |
622 | | -| generic_assoc_list T_COMMA generic_association { |
623 | | - $3->ga_prev = $1; |
624 | | - $$ = $3; |
625 | | - } |
626 | | -; |
| 624 | +/* The rule 'generic_assoc_list' is inlined into 'generic_inner'. */ |
| 625 | +/* The rule 'generic_association' is inlined into 'generic_inner'. */ |
627 | 626 |
|
628 | | -/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1, C23 6.5.2.1 */ |
629 | | -generic_association: |
630 | | - type_name T_COLON assignment_expression { |
631 | | - $$ = block_zero_alloc(sizeof(*$$), "generic"); |
632 | | - $$->ga_arg = $1; |
633 | | - $$->ga_result = $3; |
634 | | - } |
635 | | -| T_DEFAULT T_COLON assignment_expression { |
636 | | - $$ = block_zero_alloc(sizeof(*$$), "generic"); |
637 | | - $$->ga_arg = NULL; |
638 | | - $$->ga_result = $3; |
| 627 | +generic_inner: |
| 628 | + { |
| 629 | + push_evaluation_mode(EM_TYPE); |
| 630 | + } assignment_expression { |
| 631 | + pop_evaluation_mode(); |
| 632 | + } { |
| 633 | + $$ = (struct generic_selection){ |
| 634 | + /* C23 6.5.2.1p2 */ |
| 635 | + .expr_type = $2 != NULL |
| 636 | + ? cconv(unconst_tnode($2))->tn_type |
| 637 | + : NULL |
| 638 | + }; |
| 639 | + } |
| 640 | +| generic_inner T_COMMA type_name T_COLON { |
| 641 | + $1.assoc_matched = $1.expr_type != NULL && $3 != NULL |
| 642 | + && types_compatible($1.expr_type, $3, true, false, NULL); |
| 643 | + push_evaluation_mode($1.assoc_matched ? EM_EVAL : EM_PARSE); |
| 644 | + } assignment_expression { |
| 645 | + pop_evaluation_mode(); |
| 646 | + $$ = $1; |
| 647 | + if ($$.assoc_matched) |
| 648 | + $$.matched = $6; |
| 649 | + } |
| 650 | +| generic_inner T_COMMA T_DEFAULT T_COLON { |
| 651 | + push_evaluation_mode($1.matched != NULL ? EM_PARSE : EM_EVAL); |
| 652 | + } assignment_expression { |
| 653 | + pop_evaluation_mode(); |
| 654 | + $$ = $1; |
| 655 | + $$.fallback = $6; |
639 | 656 | } |
640 | 657 | ; |
641 | 658 |
|
|
0 commit comments