Module Name: src Committed By: rillig Date: Thu May 9 20:15:05 UTC 2024
Modified Files: src/usr.bin/xlint/lint1: cgram.y Log Message: lint: sort grammar rules according to the order they appear in C23 To generate a diff of this commit: cvs rdiff -u -r1.496 -r1.497 src/usr.bin/xlint/lint1/cgram.y Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/xlint/lint1/cgram.y diff -u src/usr.bin/xlint/lint1/cgram.y:1.496 src/usr.bin/xlint/lint1/cgram.y:1.497 --- src/usr.bin/xlint/lint1/cgram.y:1.496 Thu May 9 11:08:07 2024 +++ src/usr.bin/xlint/lint1/cgram.y Thu May 9 20:15:05 2024 @@ -1,5 +1,5 @@ %{ -/* $NetBSD: cgram.y,v 1.496 2024/05/09 11:08:07 rillig Exp $ */ +/* $NetBSD: cgram.y,v 1.497 2024/05/09 20:15:05 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: cgram.y,v 1.496 2024/05/09 11:08:07 rillig Exp $"); +__RCSID("$NetBSD: cgram.y,v 1.497 2024/05/09 20:15:05 rillig Exp $"); #endif #include <limits.h> @@ -328,9 +328,12 @@ is_either(const char *s, const char *a, /* No type for type_attribute. */ /* No type for begin_type. */ /* No type for end_type. */ +/* No type for notype_init_declarators. */ +/* No type for type_init_declarators. */ +/* No type for notype_init_declarator. */ +/* No type for type_init_declarator. */ %type <y_type> type_specifier %type <y_type> notype_type_specifier -%type <y_type> atomic_type_specifier %type <y_type> struct_or_union_specifier %type <y_tspec> struct_or_union %type <y_sym> braced_member_declaration_list @@ -347,19 +350,17 @@ is_either(const char *s, const char *a, %type <y_sym> enums_with_opt_comma %type <y_sym> enumerator_list %type <y_sym> enumerator -%type <y_type_qualifiers> type_qualifier +%type <y_type> atomic_type_specifier /* No type for atomic. */ -%type <y_qual_ptr> pointer -%type <y_type_qualifiers> type_qualifier_list_opt -%type <y_type_qualifiers> type_qualifier_list -/* No type for notype_init_declarators. */ -/* No type for type_init_declarators. */ -/* No type for notype_init_declarator. */ -/* No type for type_init_declarator. */ +%type <y_type_qualifiers> type_qualifier %type <y_sym> notype_declarator %type <y_sym> type_declarator %type <y_sym> notype_direct_declarator %type <y_sym> type_direct_declarator +%type <y_qual_ptr> pointer +%type <y_type_qualifiers> type_qualifier_list_opt +%type <y_type_qualifiers> type_qualifier_list +%type <y_sym> parameter_declaration %type <y_sym> type_param_declarator %type <y_sym> notype_param_declarator %type <y_sym> direct_param_declarator @@ -369,13 +370,12 @@ is_either(const char *s, const char *a, %type <y_sym> identifier_list %type <y_type> type_name %type <y_sym> abstract_declaration -%type <y_sym> abstract_declarator -%type <y_sym> direct_abstract_declarator %type <y_parameter_list> abstract_decl_param_list /* No type for abstract_decl_lparen. */ %type <y_parameter_list> vararg_parameter_type_list %type <y_parameter_list> parameter_type_list -%type <y_sym> parameter_declaration +%type <y_sym> abstract_declarator +%type <y_sym> direct_abstract_declarator /* No type for braced_initializer. */ /* No type for initializer. */ /* No type for initializer_list. */ @@ -391,8 +391,8 @@ is_either(const char *s, const char *a, /* No type for no_attr_statement. */ /* No type for non_expr_statement. */ /* No type for no_attr_non_expr_statement. */ -/* No type for labeled_statement. */ /* No type for label. */ +/* No type for labeled_statement. */ /* No type for compound_statement. */ /* No type for compound_statement_lbrace. */ /* No type for compound_statement_rbrace. */ @@ -472,7 +472,7 @@ string: } ; -/* K&R 7.1, C90 ???, C99 6.5.1, C11 6.5.1 */ +/* K&R 7.1, C90 ???, C99 6.5.1, C11 6.5.1, C23 6.5.2 */ primary_expression: T_NAME { bool sys_name, sys_next; @@ -541,7 +541,7 @@ member_designator: } ; -/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1 */ +/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1, C23 6.5.2.1 */ generic_selection: T_GENERIC T_LPAREN assignment_expression T_COMMA generic_assoc_list T_RPAREN { @@ -551,7 +551,7 @@ generic_selection: } ; -/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1 */ +/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1, C23 6.5.2.1 */ generic_assoc_list: generic_association | generic_assoc_list T_COMMA generic_association { @@ -560,7 +560,7 @@ generic_assoc_list: } ; -/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1 */ +/* K&R ---, C90 ---, C99 ---, C11 6.5.1.1, C23 6.5.2.1 */ generic_association: type_name T_COLON assignment_expression { $$ = block_zero_alloc(sizeof(*$$), "generic"); @@ -574,7 +574,7 @@ generic_association: } ; -/* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2, C23 6.5.2 */ +/* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2, C23 6.5.3.1 */ postfix_expression: primary_expression | postfix_expression T_LBRACK sys expression T_RBRACK { @@ -594,7 +594,8 @@ postfix_expression: | postfix_expression T_INCDEC sys { $$ = build_unary($2 ? INCAFT : DECAFT, $3, $1); } -| T_LPAREN type_name T_RPAREN { /* C99 6.5.2.5 "Compound literals" */ + /* Rule 'compound_literal' from C99 6.5.2.5. */ +| T_LPAREN type_name T_RPAREN { sym_t *tmp = mktempsym($2); begin_initialization(tmp); cgram_declare(tmp, true, NULL); @@ -665,7 +666,7 @@ point_or_arrow: /* helper for 'postfix } ; -/* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2 */ +/* K&R 7.1, C90 ???, C99 6.5.2, C11 6.5.2, C23 6.5.3.1 */ argument_expression_list: assignment_expression { $$ = expr_zero_alloc(sizeof(*$$), "function_call"); @@ -677,7 +678,13 @@ argument_expression_list: } ; -/* K&R 7.2, C90 ???, C99 6.5.3, C11 6.5.3 */ + +/* C23 6.5.3.6 */ +/* The rule 'compound_literal' is inlined into 'postfix_expression'. */ + +/* TODO: Implement 'storage_class_specifiers' from C23 6.5.3.6. */ + +/* K&R 7.2, C90 ???, C99 6.5.3, C11 6.5.3, C23 6.5.4 */ unary_expression: postfix_expression | T_INCDEC sys unary_expression { @@ -725,16 +732,17 @@ unary_expression: lint_assert($2 != NULL); $$ = build_alignof($2->tn_type); } - /* K&R ---, C90 ---, C99 ---, C11 6.5.3 */ + /* K&R ---, C90 ---, C99 ---, C11 6.5.3, C23 6.5.4.4 */ | T_ALIGNOF T_LPAREN type_name T_RPAREN { /* TODO: c11ism */ $$ = build_alignof($3); } ; +/* C23 6.5.4 */ /* The rule 'unary_operator' is inlined into unary_expression. */ -/* K&R 7.2, C90 ???, C99 6.5.4, C11 6.5.4 */ +/* K&R 7.2, C90 ???, C99 6.5.4, C11 6.5.4, C23 6.5.5 */ cast_expression: unary_expression | T_LPAREN type_name T_RPAREN sys cast_expression { @@ -759,7 +767,7 @@ expression_opt: /* 'conditional_expression' also implements 'inclusive_OR_expression'. */ /* 'conditional_expression' also implements 'logical_AND_expression'. */ /* 'conditional_expression' also implements 'logical_OR_expression'. */ -/* K&R ???, C90 ???, C99 6.5.5 to 6.5.15, C11 6.5.5 to 6.5.15 */ +/* K&R ???, C90 ???, C99 6.5.5 to 6.5.15, C11 6.5.5 to 6.5.15, C23 6.5.6 to 6.5.16 */ conditional_expression: cast_expression | conditional_expression T_ASTERISK sys conditional_expression { @@ -802,7 +810,7 @@ conditional_expression: } ; -/* K&R ???, C90 ???, C99 6.5.16, C11 6.5.16 */ +/* K&R ???, C90 ???, C99 6.5.16, C11 6.5.16, C23 6.5.17.1 */ assignment_expression: conditional_expression | unary_expression T_ASSIGN sys assignment_expression { @@ -813,7 +821,10 @@ assignment_expression: } ; -/* K&R ???, C90 ???, C99 6.5.17, C11 6.5.17 */ +/* C23 6.5.17.1 */ +/* The rule 'assignment_operator' is inlined into 'assignment_expression'. */ + +/* K&R ???, C90 ???, C99 6.5.17, C11 6.5.17, C23 6.5.18 */ expression: assignment_expression | expression T_COMMA sys assignment_expression { @@ -831,7 +842,7 @@ declaration_or_error: | error T_SEMI ; -/* K&R ???, C90 ???, C99 6.7, C11 ???, C23 6.7 */ +/* K&R ???, C90 ???, C99 6.7, C11 ???, C23 6.7.1 */ declaration: begin_type_declmods end_type T_SEMI { if (dcs->d_scl == TYPEDEF) @@ -862,7 +873,9 @@ declaration: | static_assert_declaration ; -begin_type_declaration_specifiers: /* see C99 6.7 */ +/* TODO: Implement 'declaration_specifiers' from C23 6.7.1. */ + +begin_type_declaration_specifiers: /* see C99 6.7, C23 6.7.1 */ begin_type_typespec { dcs_add_type($1); } @@ -981,7 +994,64 @@ end_type: } ; -type_specifier: /* C99 6.7.2 */ +/* TODO: Implement 'declaration_specifier' from C23 6.7.1. */ + +/* + * For an explanation of 'type' and 'notype' prefixes in the following rules, + * see https://www.gnu.org/software/bison/manual/bison.html#Semantic-Tokens. + */ + +/* C23 6.7.1 */ +/* The rule 'init_declarator_list' is split into the 'notype' and 'type' variants. */ + +notype_init_declarators: + notype_init_declarator +| notype_init_declarators T_COMMA type_init_declarator +; + +type_init_declarators: + type_init_declarator +| type_init_declarators T_COMMA type_init_declarator +; + +/* C23 6.7.1 */ +/* The rule 'init_declarator' is split into the 'notype' and 'type' variants. */ + +notype_init_declarator: + notype_declarator asm_or_symbolrename_opt { + cgram_declare($1, false, $2); + check_size($1); + } +| notype_declarator asm_or_symbolrename_opt { + begin_initialization($1); + cgram_declare($1, true, $2); + } T_ASSIGN initializer { + check_size($1); + end_initialization(); + } +; + +type_init_declarator: + type_declarator asm_or_symbolrename_opt { + cgram_declare($1, false, $2); + check_size($1); + } +| type_declarator asm_or_symbolrename_opt { + begin_initialization($1); + cgram_declare($1, true, $2); + } T_ASSIGN initializer { + check_size($1); + end_initialization(); + } +; + + +/* TODO: Implement 'attribute_declaration' from C23 6.7.1. */ + +/* TODO: Implement 'storage_class_specifier' from C23 6.7.2. */ + +/* C99 6.7.2, C23 6.7.3.1 */ +type_specifier: notype_type_specifier | T_TYPENAME { $$ = getsym($1)->s_type; @@ -1007,14 +1077,7 @@ notype_type_specifier: /* see C99 6.7.2 } ; -/* K&R ---, C90 ---, C99 ---, C11 6.7.2.4 */ -atomic_type_specifier: - atomic T_LPAREN type_name T_RPAREN { - $$ = $3; - } -; - -/* K&R ---, C90 ---, C99 6.7.2.1, C11 ???, C23 6.7.2.1 */ +/* K&R ---, C90 ---, C99 6.7.2.1, C11 ???, C23 6.7.3.2 */ struct_or_union_specifier: struct_or_union identifier_sym { /* @@ -1042,7 +1105,7 @@ struct_or_union_specifier: } ; -/* K&R ---, C90 ---, C99 6.7.2.1, C11 ???, C23 6.7.2.1 */ +/* K&R ---, C90 ---, C99 6.7.2.1, C11 ???, C23 6.7.3.2 */ struct_or_union: T_STRUCT_OR_UNION { set_sym_kind(SK_TAG); @@ -1070,7 +1133,7 @@ member_declaration_list_with_rbrace: /* } ; -/* K&R ???, C90 ???, C99 6.7.2.1, C11 6.7.2.1, C23 6.7.2.1 */ +/* K&R ???, C90 ???, C99 6.7.2.1, C11 6.7.2.1, C23 6.7.3.2 */ /* Was named struct_declaration_list until C11. */ member_declaration_list: member_declaration @@ -1080,7 +1143,7 @@ member_declaration_list: ; /* Was named struct_declaration until C11. */ -/* K&R ???, C90 ???, C99 6.7.2.1, C11 6.7.2.1, C23 6.7.2.1 */ +/* K&R ???, C90 ???, C99 6.7.2.1, C11 6.7.2.1, C23 6.7.3.2 */ member_declaration: begin_type_qualifier_list end_type { /* ^^ There is no check for the missing type-specifier. */ @@ -1124,6 +1187,13 @@ member_declaration: } ; +/* TODO: Implement 'specifier_qualifier_list' from C23 6.7.3.2. */ + +/* TODO: Implement 'type_specifier_qualifier' from C23 6.7.3.2. */ + +/* C23 6.7.3.2 */ +/* The rule 'member_declarator_list' is split into the 'type' and 'notype' variants. */ + /* Was named struct_declarators until C11. */ notype_member_declarators: notype_member_declarator { @@ -1148,6 +1218,9 @@ type_member_declarators: } ; +/* C23 6.7.3.2 */ +/* The rule 'member_declarator' is split into the 'type' and 'notype' variants. */ + /* Was named struct_declarator until C11. */ notype_member_declarator: notype_declarator @@ -1176,7 +1249,7 @@ type_member_declarator: } ; -/* K&R ---, C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2 */ +/* K&R ---, C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2, C23 6.7.3.5 */ enum_specifier: enum gcc_attribute_specifier_list_opt identifier_sym { $$ = make_tag_type($3, ENUM, false, false); @@ -1226,7 +1299,8 @@ enums_with_opt_comma: /* helper for C99 } ; -enumerator_list: /* C99 6.7.2.2 */ +/* C99 6.7.2.2, C23 6.7.3.3 */ +enumerator_list: enumerator | enumerator_list T_COMMA enumerator { $$ = concat_symbols($1, $3); @@ -1236,7 +1310,8 @@ enumerator_list: /* C99 6.7.2.2 */ } ; -enumerator: /* C99 6.7.2.2 */ +/* C99 6.7.2.2, C23 6.7.3.3 */ +enumerator: identifier_sym gcc_attribute_specifier_list_opt { $$ = enumeration_constant($1, enumval, true); } @@ -1247,10 +1322,12 @@ enumerator: /* C99 6.7.2.2 */ } ; -type_qualifier: /* C99 6.7.3 */ - T_QUAL -| atomic { - $$ = (type_qualifiers){ .tq_atomic = true }; +/* TODO: Implement 'enum_type_specifier' from C23 6.7.3.3. */ + +/* K&R ---, C90 ---, C99 ---, C11 6.7.2.4, C23 6.7.3.5 */ +atomic_type_specifier: + atomic T_LPAREN type_name T_RPAREN { + $$ = $3; } ; @@ -1263,75 +1340,24 @@ atomic: /* helper */ } ; -pointer: /* C99 6.7.5 */ - T_ASTERISK type_qualifier_list_opt { - $$ = xcalloc(1, sizeof(*$$)); - add_type_qualifiers(&$$->qualifiers, $2); - } -| T_ASTERISK type_qualifier_list_opt pointer { - $$ = xcalloc(1, sizeof(*$$)); - add_type_qualifiers(&$$->qualifiers, $2); - $$ = append_qualified_pointer($$, $3); - } -; +/* TODO: Implement 'typeof_specifier' from C23 6.7.3.6. */ -type_qualifier_list_opt: /* see C99 6.7.5 */ - /* empty */ { - $$ = (type_qualifiers){ .tq_const = false }; - } -| type_qualifier_list -; +/* TODO: Implement 'typeof_specifier_argument' from C23 6.7.3.6. */ -type_qualifier_list: /* C99 6.7.5 */ - type_qualifier -| type_qualifier_list type_qualifier { - $$ = $1; - add_type_qualifiers(&$$, $2); +/* C99 6.7.3, C23 6.7.4.1 */ +type_qualifier: + T_QUAL +| atomic { + $$ = (type_qualifiers){ .tq_atomic = true }; } ; -/* - * For an explanation of 'notype' in the following rules, see - * https://www.gnu.org/software/bison/manual/bison.html#Semantic-Tokens. - */ +/* TODO: Implement 'function_specifier' from C23 6.7.5. */ -notype_init_declarators: - notype_init_declarator -| notype_init_declarators T_COMMA type_init_declarator -; +/* TODO: Implement 'alignment_specifier' from C23 6.7.6. */ -type_init_declarators: - type_init_declarator -| type_init_declarators T_COMMA type_init_declarator -; - -notype_init_declarator: - notype_declarator asm_or_symbolrename_opt { - cgram_declare($1, false, $2); - check_size($1); - } -| notype_declarator asm_or_symbolrename_opt { - begin_initialization($1); - cgram_declare($1, true, $2); - } T_ASSIGN initializer { - check_size($1); - end_initialization(); - } -; - -type_init_declarator: - type_declarator asm_or_symbolrename_opt { - cgram_declare($1, false, $2); - check_size($1); - } -| type_declarator asm_or_symbolrename_opt { - begin_initialization($1); - cgram_declare($1, true, $2); - } T_ASSIGN initializer { - check_size($1); - end_initialization(); - } -; +/* C23 6.7.7.1 */ +/* The rule 'declarator' is split into the 'notype' and 'type' variants. */ notype_declarator: notype_direct_declarator @@ -1347,6 +1373,9 @@ type_declarator: } ; +/* C23 6.7.7.1 */ +/* The rule 'direct_declarator' is split into the 'notype' and 'type' variants. */ + notype_direct_declarator: type_attribute_list_opt T_NAME { $$ = declarator_name(getsym($2)); @@ -1383,6 +1412,78 @@ type_direct_declarator: | type_direct_declarator type_attribute ; + +/* TODO: Implement 'array_declarator' from C23 6.7.7.1. */ + +/* TODO: Implement 'function_declarator' from C23 6.7.7.1. */ + +/* C99 6.7.5, C23 6.7.7.1 */ +pointer: + T_ASTERISK type_qualifier_list_opt { + $$ = xcalloc(1, sizeof(*$$)); + add_type_qualifiers(&$$->qualifiers, $2); + } +| T_ASTERISK type_qualifier_list_opt pointer { + $$ = xcalloc(1, sizeof(*$$)); + add_type_qualifiers(&$$->qualifiers, $2); + $$ = append_qualified_pointer($$, $3); + } +; + +/* see C99 6.7.5, C23 6.7.7.1 */ +type_qualifier_list_opt: + /* empty */ { + $$ = (type_qualifiers){ .tq_const = false }; + } +| type_qualifier_list +; + +/* C99 6.7.5 */ +type_qualifier_list: + type_qualifier +| type_qualifier_list type_qualifier { + $$ = $1; + add_type_qualifiers(&$$, $2); + } +; + +/* TODO: Implement 'parameter_type_list' from C23 6.7.7.1. */ + +/* TODO: Implement 'parameter_list' from C23 6.7.7.1. */ + +/* C23 6.7.7.1 */ +/* XXX: C99 6.7.5 defines the same name, but it looks completely different. */ +parameter_declaration: + begin_type_declmods end_type { + /* ^^ There is no check for the missing type-specifier. */ + $$ = declare_parameter(abstract_name(), false); + } +| begin_type_declaration_specifiers end_type { + $$ = declare_parameter(abstract_name(), false); + } +| begin_type_declmods end_type notype_param_declarator { + /* ^^ There is no check for the missing type-specifier. */ + $$ = declare_parameter($3, false); + } + /* + * type_param_declarator is needed because of following conflict: + * "typedef int a; f(int (a));" could be parsed as + * "function with argument a of type int", or + * "function with an unnamed (abstract) argument of type function". + * This grammar realizes the second case. + */ +| begin_type_declaration_specifiers end_type type_param_declarator { + $$ = declare_parameter($3, false); + } +| begin_type_declmods end_type abstract_declarator { + /* ^^ There is no check for the missing type-specifier. */ + $$ = declare_parameter($3, false); + } +| begin_type_declaration_specifiers end_type abstract_declarator { + $$ = declare_parameter($3, false); + } +; + /* * The two distinct rules type_param_declarator and notype_param_declarator * avoid a conflict in parameter lists. A typename enclosed in parentheses is @@ -1495,8 +1596,9 @@ identifier_list: /* C99 6.7.5 */ | identifier_list error ; +/* C99 6.7.6, C23 6.7.8 */ /* XXX: C99 requires an additional specifier-qualifier-list. */ -type_name: /* C99 6.7.6 */ +type_name: { begin_declaration_level(DLK_ABSTRACT); } abstract_declaration { @@ -1520,51 +1622,6 @@ abstract_declaration: /* specific to li } ; -/* K&R 8.7, C90 ???, C99 6.7.6, C11 6.7.7 */ -/* In K&R, abstract-declarator could be empty and was still simpler. */ -abstract_declarator: - pointer { - $$ = add_pointer(abstract_name(), $1); - } -| direct_abstract_declarator -| pointer direct_abstract_declarator { - $$ = add_pointer($2, $1); - } -| type_attribute_list direct_abstract_declarator { - $$ = $2; - } -| pointer type_attribute_list direct_abstract_declarator { - $$ = add_pointer($3, $1); - } -; - -/* K&R ---, C90 ???, C99 6.7.6, C11 6.7.7 */ -direct_abstract_declarator: - /* TODO: sort rules according to C99 */ - T_LPAREN abstract_declarator T_RPAREN { - $$ = $2; - } -| T_LBRACK array_size_opt T_RBRACK { - $$ = add_array(abstract_name(), $2.has_dim, $2.dim); - } -| direct_abstract_declarator T_LBRACK array_size_opt T_RBRACK { - $$ = add_array($1, $3.has_dim, $3.dim); - } -| abstract_decl_param_list asm_or_symbolrename_opt { - sym_t *name = abstract_enclosing_name(); - $$ = add_function(symbolrename(name, $2), $1); - end_declaration_level(); - block_level--; - } -| direct_abstract_declarator abstract_decl_param_list - asm_or_symbolrename_opt { - $$ = add_function(symbolrename($1, $3), $2); - end_declaration_level(); - block_level--; - } -| direct_abstract_declarator type_attribute_list -; - abstract_decl_param_list: /* specific to lint */ abstract_decl_lparen T_RPAREN type_attribute_opt { $$ = (parameter_list){ .first = NULL }; @@ -1615,50 +1672,70 @@ parameter_type_list: } ; -/* XXX: C99 6.7.5 defines the same name, but it looks completely different. */ -parameter_declaration: - begin_type_declmods end_type { - /* ^^ There is no check for the missing type-specifier. */ - $$ = declare_parameter(abstract_name(), false); +/* K&R 8.7, C90 ???, C99 6.7.6, C11 6.7.7, C23 6.7.8 */ +/* In K&R, abstract-declarator could be empty and was still simpler. */ +abstract_declarator: + pointer { + $$ = add_pointer(abstract_name(), $1); } -| begin_type_declaration_specifiers end_type { - $$ = declare_parameter(abstract_name(), false); +| direct_abstract_declarator +| pointer direct_abstract_declarator { + $$ = add_pointer($2, $1); } -| begin_type_declmods end_type notype_param_declarator { - /* ^^ There is no check for the missing type-specifier. */ - $$ = declare_parameter($3, false); +| type_attribute_list direct_abstract_declarator { + $$ = $2; } - /* - * type_param_declarator is needed because of following conflict: - * "typedef int a; f(int (a));" could be parsed as - * "function with argument a of type int", or - * "function with an unnamed (abstract) argument of type function". - * This grammar realizes the second case. - */ -| begin_type_declaration_specifiers end_type type_param_declarator { - $$ = declare_parameter($3, false); +| pointer type_attribute_list direct_abstract_declarator { + $$ = add_pointer($3, $1); } -| begin_type_declmods end_type abstract_declarator { - /* ^^ There is no check for the missing type-specifier. */ - $$ = declare_parameter($3, false); +; + +/* K&R ---, C90 ???, C99 6.7.6, C11 6.7.7, C23 6.7.8 */ +direct_abstract_declarator: + /* TODO: sort rules according to C99 */ + T_LPAREN abstract_declarator T_RPAREN { + $$ = $2; } -| begin_type_declaration_specifiers end_type abstract_declarator { - $$ = declare_parameter($3, false); +| T_LBRACK array_size_opt T_RBRACK { + $$ = add_array(abstract_name(), $2.has_dim, $2.dim); } +| direct_abstract_declarator T_LBRACK array_size_opt T_RBRACK { + $$ = add_array($1, $3.has_dim, $3.dim); + } +| abstract_decl_param_list asm_or_symbolrename_opt { + sym_t *name = abstract_enclosing_name(); + $$ = add_function(symbolrename(name, $2), $1); + end_declaration_level(); + block_level--; + } +| direct_abstract_declarator abstract_decl_param_list + asm_or_symbolrename_opt { + $$ = add_function(symbolrename($1, $3), $2); + end_declaration_level(); + block_level--; + } +| direct_abstract_declarator type_attribute_list ; +/* TODO: Implement 'array_abstract_declarator' from C23 6.7.8. */ + +/* TODO: Implement 'function_abstract_declarator' from C23 6.7.8. */ + +/* TODO: Implement 'typedef_name' from C23 6.7.9. */ + +/* C23 6.7.11 */ +/* K&R ---, C90 ---, C99 6.7.8, C11 6.7.9, C23 6.7.10 */ braced_initializer: - /* K&R ---, C90 ---, C99 ---, C11 ---, C23 6.7.10 */ init_lbrace init_rbrace { /* empty initializer braces require C23 or later */ c23ism(353); } - /* K&R ---, C90 ---, C99 6.7.8, C11 6.7.9, C23 6.7.10 */ | init_lbrace initializer_list init_rbrace | init_lbrace initializer_list T_COMMA init_rbrace ; -initializer: /* C99 6.7.8 "Initialization" */ +/* C99 6.7.8, C23 6.7.11 */ +initializer: assignment_expression { init_expr($1); } @@ -1671,14 +1748,16 @@ initializer: /* C99 6.7.8 "Initializat | error ; -initializer_list: /* C99 6.7.8 "Initialization" */ +/* C99 6.7.8, C23 6.7.11 */ +initializer_list: initializer | designation initializer | initializer_list T_COMMA initializer | initializer_list T_COMMA designation initializer ; -designation: /* C99 6.7.8 "Initialization" */ +/* C99 6.7.8, C23 6.7.11 */ +designation: { begin_designation(); } designator_list T_ASSIGN @@ -1690,12 +1769,14 @@ designation: /* C99 6.7.8 "Initializat } ; -designator_list: /* C99 6.7.8 "Initialization" */ +/* C99 6.7.8, C23 6.7.11 */ +designator_list: designator | designator_list designator ; -designator: /* C99 6.7.8 "Initialization" */ +/* C99 6.7.8, C23 6.7.11 */ +designator: T_LBRACK range T_RBRACK { if (!allow_c99) /* array initializer with designators is a C99 ... */ @@ -1710,6 +1791,7 @@ designator: /* C99 6.7.8 "Initializati } ; +/* C23 6.7.12 */ static_assert_declaration: T_STATIC_ASSERT T_LPAREN constant_expression T_COMMA T_STRING T_RPAREN T_SEMI { @@ -1747,6 +1829,28 @@ init_rbrace: /* helper */ } ; +/* TODO: Implement 'attribute_specifier_sequence' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute_specifier' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute_list' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute_token' from C23 6.7.13.2. */ + +/* TODO: Implement 'standard_attribute' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute_prefixed_token' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute_prefix' from C23 6.7.13.2. */ + +/* TODO: Implement 'attribute_argument_clause' from C23 6.7.13.2. */ + +/* TODO: Implement 'balanced_token_sequence' from C23 6.7.13.2. */ + +/* TODO: Implement 'balanced_token' from C23 6.7.13.2. */ + asm_or_symbolrename_opt: /* GCC extensions */ /* empty */ { $$ = NULL; @@ -1761,7 +1865,7 @@ asm_or_symbolrename_opt: /* GCC extensio } ; -/* K&R ???, C90 ???, C99 6.8, C11 ???, C23 6.8 */ +/* K&R ???, C90 ???, C99 6.8, C11 ???, C23 6.8.1 */ statement: expression_statement | non_expr_statement @@ -1790,10 +1894,13 @@ no_attr_non_expr_statement: | asm_statement ; -labeled_statement: /* C99 6.8.1 */ - label gcc_attribute_specifier_list_opt no_attr_statement -; +/* TODO: Implement 'unlabeled_statement' from C23 6.8.1. */ + +/* TODO: Implement 'primary_block' from C23 6.8.1. */ +/* TODO: Implement 'secondary_block' from C23 6.8.1. */ + +/* C23 6.8.2 */ label: T_NAME T_COLON { set_sym_kind(SK_LABEL); @@ -1814,7 +1921,13 @@ label: } ; -compound_statement: /* C99 6.8.2 */ +/* C99 6.8.1, C23 6.8.2 */ +labeled_statement: + label gcc_attribute_specifier_list_opt no_attr_statement +; + +/* C99 6.8.2, C23 6.8.3 */ +compound_statement: compound_statement_lbrace compound_statement_rbrace | compound_statement_lbrace block_item_list compound_statement_rbrace ; @@ -1842,7 +1955,8 @@ compound_statement_rbrace: } ; -block_item_list: /* C99 6.8.2 */ +/* C99 6.8.2, C23 6.8.3 */ +block_item_list: block_item | block_item_list block_item { if ($1 && !$2) @@ -1852,7 +1966,8 @@ block_item_list: /* C99 6.8.2 */ } ; -block_item: /* C99 6.8.2 */ +/* C99 6.8.2, C23 6.8.3 */ +block_item: declaration_or_error { $$ = false; restore_warning_flags(); @@ -1863,7 +1978,8 @@ block_item: /* C99 6.8.2 */ } ; -expression_statement: /* C99 6.8.3 */ +/* C99 6.8.3, C23 6.8.4 */ +expression_statement: expression T_SEMI { expr($1, false, false, false, false); suppress_fallthrough = false; @@ -1874,7 +1990,8 @@ expression_statement: /* C99 6.8.3 */ } ; -selection_statement: /* C99 6.8.4 */ +/* C99 6.8.4, C23 6.8.5.1 */ +selection_statement: if_without_else %prec T_THEN { save_warning_flags(); stmt_if_then_stmt(); @@ -1920,7 +2037,8 @@ switch_expr: /* see C99 6.8.4 */ } ; -iteration_statement: /* C99 6.8.5 */ +/* C99 6.8.5, C23 6.8.6.1 */ +iteration_statement: while_expr statement { clear_warning_flags(); stmt_while_expr_stmt(); @@ -1997,7 +2115,8 @@ for_exprs: /* see C99 6.8.5 */ } ; -jump_statement: /* C99 6.8.6 */ +/* C99 6.8.6, C23 6.8.7.1 */ +jump_statement: goto identifier T_SEMI { stmt_goto(getsym($2)); } @@ -2040,12 +2159,14 @@ read_until_rparen: /* helper for 'asm_s } ; -translation_unit: /* C99 6.9 */ +/* C99 6.9, C23 6.9.1 */ +translation_unit: external_declaration | translation_unit external_declaration ; -external_declaration: /* C99 6.9 */ +/* C99 6.9, C23 6.9.1 */ +external_declaration: function_definition { global_clean_up_decl(false); clear_warning_flags(); @@ -2097,7 +2218,8 @@ top_level_declaration: /* C99 6.9 calls } ; -function_definition: /* C99 6.9.1 */ +/* C99 6.9.1, C23 6.9.2 */ +function_definition: func_declarator { if ($1->s_type->t_tspec != FUNC) { /* syntax error '%s' */ @@ -2234,6 +2356,8 @@ gcc_attribute: } ; +/* The rule 'function_body' from C23 6.9.2 is inlined into 'function_definition'. */ + sys: /* empty */ { $$ = in_system_header;