177564a48SMasahiro Yamada /* SPDX-License-Identifier: GPL-2.0-or-later */
277564a48SMasahiro Yamada /*
377564a48SMasahiro Yamada * C global declaration parser for genksyms.
477564a48SMasahiro Yamada * Copyright 1996, 1997 Linux International.
577564a48SMasahiro Yamada *
677564a48SMasahiro Yamada * New implementation contributed by Richard Henderson <rth@tamu.edu>
777564a48SMasahiro Yamada * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
877564a48SMasahiro Yamada *
977564a48SMasahiro Yamada * This file is part of the Linux modutils.
1077564a48SMasahiro Yamada */
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds %{
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include <assert.h>
1501660dfcSArnaud Lacombe #include <stdlib.h>
16e37ddb82SMichal Marek #include <string.h>
171da177e4SLinus Torvalds #include "genksyms.h"
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds static int is_typedef;
201da177e4SLinus Torvalds static int is_extern;
211da177e4SLinus Torvalds static char *current_name;
221da177e4SLinus Torvalds static struct string_list *decl_spec;
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds static void yyerror(const char *);
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds static inline void
remove_node(struct string_list ** p)271da177e4SLinus Torvalds remove_node(struct string_list **p)
281da177e4SLinus Torvalds {
291da177e4SLinus Torvalds struct string_list *node = *p;
301da177e4SLinus Torvalds *p = node->next;
311da177e4SLinus Torvalds free_node(node);
321da177e4SLinus Torvalds }
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds static inline void
remove_list(struct string_list ** pb,struct string_list ** pe)351da177e4SLinus Torvalds remove_list(struct string_list **pb, struct string_list **pe)
361da177e4SLinus Torvalds {
371da177e4SLinus Torvalds struct string_list *b = *pb, *e = *pe;
381da177e4SLinus Torvalds *pb = e;
391da177e4SLinus Torvalds free_list(b, e);
401da177e4SLinus Torvalds }
411da177e4SLinus Torvalds
42b06fcd6cSMichal Marek /* Record definition of a struct/union/enum */
record_compound(struct string_list ** keyw,struct string_list ** ident,struct string_list ** body,enum symbol_type type)43b06fcd6cSMichal Marek static void record_compound(struct string_list **keyw,
44b06fcd6cSMichal Marek struct string_list **ident,
45b06fcd6cSMichal Marek struct string_list **body,
46b06fcd6cSMichal Marek enum symbol_type type)
47b06fcd6cSMichal Marek {
48b06fcd6cSMichal Marek struct string_list *b = *body, *i = *ident, *r;
492c5925d6SMichal Marek
502c5925d6SMichal Marek if (i->in_source_file) {
512c5925d6SMichal Marek remove_node(keyw);
522c5925d6SMichal Marek (*ident)->tag = type;
532c5925d6SMichal Marek remove_list(body, ident);
542c5925d6SMichal Marek return;
552c5925d6SMichal Marek }
56b06fcd6cSMichal Marek r = copy_node(i); r->tag = type;
57b06fcd6cSMichal Marek r->next = (*keyw)->next; *body = r; (*keyw)->next = NULL;
58b06fcd6cSMichal Marek add_symbol(i->string, type, b, is_extern);
59b06fcd6cSMichal Marek }
60b06fcd6cSMichal Marek
611da177e4SLinus Torvalds %}
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds %token ASM_KEYW
641da177e4SLinus Torvalds %token ATTRIBUTE_KEYW
651da177e4SLinus Torvalds %token AUTO_KEYW
661da177e4SLinus Torvalds %token BOOL_KEYW
67a222061bSWill Deacon %token BUILTIN_INT_KEYW
681da177e4SLinus Torvalds %token CHAR_KEYW
691da177e4SLinus Torvalds %token CONST_KEYW
701da177e4SLinus Torvalds %token DOUBLE_KEYW
711da177e4SLinus Torvalds %token ENUM_KEYW
721da177e4SLinus Torvalds %token EXTERN_KEYW
733550a516SSam Ravnborg %token EXTENSION_KEYW
741da177e4SLinus Torvalds %token FLOAT_KEYW
751da177e4SLinus Torvalds %token INLINE_KEYW
761da177e4SLinus Torvalds %token INT_KEYW
771da177e4SLinus Torvalds %token LONG_KEYW
781da177e4SLinus Torvalds %token REGISTER_KEYW
791da177e4SLinus Torvalds %token RESTRICT_KEYW
801da177e4SLinus Torvalds %token SHORT_KEYW
811da177e4SLinus Torvalds %token SIGNED_KEYW
821da177e4SLinus Torvalds %token STATIC_KEYW
83*9ab55d7fSMarco Elver %token STATIC_ASSERT_KEYW
841da177e4SLinus Torvalds %token STRUCT_KEYW
851da177e4SLinus Torvalds %token TYPEDEF_KEYW
861da177e4SLinus Torvalds %token UNION_KEYW
871da177e4SLinus Torvalds %token UNSIGNED_KEYW
881da177e4SLinus Torvalds %token VOID_KEYW
891da177e4SLinus Torvalds %token VOLATILE_KEYW
901da177e4SLinus Torvalds %token TYPEOF_KEYW
910efdb228SNicholas Piggin %token VA_LIST_KEYW
921da177e4SLinus Torvalds
931da177e4SLinus Torvalds %token EXPORT_SYMBOL_KEYW
941da177e4SLinus Torvalds
951da177e4SLinus Torvalds %token ASM_PHRASE
961da177e4SLinus Torvalds %token ATTRIBUTE_PHRASE
97dc533240SJan Beulich %token TYPEOF_PHRASE
981da177e4SLinus Torvalds %token BRACE_PHRASE
991da177e4SLinus Torvalds %token BRACKET_PHRASE
1001da177e4SLinus Torvalds %token EXPRESSION_PHRASE
101*9ab55d7fSMarco Elver %token STATIC_ASSERT_PHRASE
1021da177e4SLinus Torvalds
1031da177e4SLinus Torvalds %token CHAR
1041da177e4SLinus Torvalds %token DOTS
1051da177e4SLinus Torvalds %token IDENT
1061da177e4SLinus Torvalds %token INT
1071da177e4SLinus Torvalds %token REAL
1081da177e4SLinus Torvalds %token STRING
1091da177e4SLinus Torvalds %token TYPE
1101da177e4SLinus Torvalds %token OTHER
1111da177e4SLinus Torvalds %token FILENAME
1121da177e4SLinus Torvalds
1131da177e4SLinus Torvalds %%
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds declaration_seq:
1161da177e4SLinus Torvalds declaration
1171da177e4SLinus Torvalds | declaration_seq declaration
1181da177e4SLinus Torvalds ;
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvalds declaration:
1211da177e4SLinus Torvalds { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; }
1221da177e4SLinus Torvalds declaration1
1231da177e4SLinus Torvalds { free_list(*$2, NULL); *$2 = NULL; }
1241da177e4SLinus Torvalds ;
1251da177e4SLinus Torvalds
1261da177e4SLinus Torvalds declaration1:
1273550a516SSam Ravnborg EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
1283550a516SSam Ravnborg { $$ = $4; }
1293550a516SSam Ravnborg | TYPEDEF_KEYW { is_typedef = 1; } simple_declaration
1301da177e4SLinus Torvalds { $$ = $3; }
1311da177e4SLinus Torvalds | simple_declaration
1321da177e4SLinus Torvalds | function_definition
1331da177e4SLinus Torvalds | asm_definition
1341da177e4SLinus Torvalds | export_definition
135*9ab55d7fSMarco Elver | static_assert
1361da177e4SLinus Torvalds | error ';' { $$ = $2; }
1371da177e4SLinus Torvalds | error '}' { $$ = $2; }
1381da177e4SLinus Torvalds ;
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds simple_declaration:
1411da177e4SLinus Torvalds decl_specifier_seq_opt init_declarator_list_opt ';'
1421da177e4SLinus Torvalds { if (current_name) {
1431da177e4SLinus Torvalds struct string_list *decl = (*$3)->next;
1441da177e4SLinus Torvalds (*$3)->next = NULL;
1451da177e4SLinus Torvalds add_symbol(current_name,
1461da177e4SLinus Torvalds is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
1471da177e4SLinus Torvalds decl, is_extern);
1481da177e4SLinus Torvalds current_name = NULL;
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds $$ = $3;
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds ;
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds init_declarator_list_opt:
1551da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
1561da177e4SLinus Torvalds | init_declarator_list
1571da177e4SLinus Torvalds ;
1581da177e4SLinus Torvalds
1591da177e4SLinus Torvalds init_declarator_list:
1601da177e4SLinus Torvalds init_declarator
1611da177e4SLinus Torvalds { struct string_list *decl = *$1;
1621da177e4SLinus Torvalds *$1 = NULL;
1631da177e4SLinus Torvalds add_symbol(current_name,
1641da177e4SLinus Torvalds is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
1651da177e4SLinus Torvalds current_name = NULL;
1661da177e4SLinus Torvalds $$ = $1;
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds | init_declarator_list ',' init_declarator
1691da177e4SLinus Torvalds { struct string_list *decl = *$3;
1701da177e4SLinus Torvalds *$3 = NULL;
1711da177e4SLinus Torvalds free_list(*$2, NULL);
1721da177e4SLinus Torvalds *$2 = decl_spec;
1731da177e4SLinus Torvalds add_symbol(current_name,
1741da177e4SLinus Torvalds is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
1751da177e4SLinus Torvalds current_name = NULL;
1761da177e4SLinus Torvalds $$ = $3;
1771da177e4SLinus Torvalds }
1781da177e4SLinus Torvalds ;
1791da177e4SLinus Torvalds
1801da177e4SLinus Torvalds init_declarator:
1811da177e4SLinus Torvalds declarator asm_phrase_opt attribute_opt initializer_opt
1821da177e4SLinus Torvalds { $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; }
1831da177e4SLinus Torvalds ;
1841da177e4SLinus Torvalds
1851da177e4SLinus Torvalds /* Hang on to the specifiers so that we can reuse them. */
1861da177e4SLinus Torvalds decl_specifier_seq_opt:
1871da177e4SLinus Torvalds /* empty */ { decl_spec = NULL; }
1881da177e4SLinus Torvalds | decl_specifier_seq
1891da177e4SLinus Torvalds ;
1901da177e4SLinus Torvalds
1911da177e4SLinus Torvalds decl_specifier_seq:
1921da177e4SLinus Torvalds decl_specifier { decl_spec = *$1; }
1931da177e4SLinus Torvalds | decl_specifier_seq decl_specifier { decl_spec = *$2; }
1941da177e4SLinus Torvalds ;
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds decl_specifier:
1971da177e4SLinus Torvalds storage_class_specifier
1981da177e4SLinus Torvalds { /* Version 2 checksumming ignores storage class, as that
1991da177e4SLinus Torvalds is really irrelevant to the linkage. */
2001da177e4SLinus Torvalds remove_node($1);
2011da177e4SLinus Torvalds $$ = $1;
2021da177e4SLinus Torvalds }
2031da177e4SLinus Torvalds | type_specifier
2041da177e4SLinus Torvalds ;
2051da177e4SLinus Torvalds
2061da177e4SLinus Torvalds storage_class_specifier:
2071da177e4SLinus Torvalds AUTO_KEYW
2081da177e4SLinus Torvalds | REGISTER_KEYW
2091da177e4SLinus Torvalds | STATIC_KEYW
2101da177e4SLinus Torvalds | EXTERN_KEYW { is_extern = 1; $$ = $1; }
2111da177e4SLinus Torvalds | INLINE_KEYW { is_extern = 0; $$ = $1; }
2121da177e4SLinus Torvalds ;
2131da177e4SLinus Torvalds
2141da177e4SLinus Torvalds type_specifier:
2151da177e4SLinus Torvalds simple_type_specifier
2161da177e4SLinus Torvalds | cvar_qualifier
217dc533240SJan Beulich | TYPEOF_KEYW '(' parameter_declaration ')'
218dc533240SJan Beulich | TYPEOF_PHRASE
2191da177e4SLinus Torvalds
2201da177e4SLinus Torvalds /* References to s/u/e's defined elsewhere. Rearrange things
2211da177e4SLinus Torvalds so that it is easier to expand the definition fully later. */
2221da177e4SLinus Torvalds | STRUCT_KEYW IDENT
2231da177e4SLinus Torvalds { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; }
2241da177e4SLinus Torvalds | UNION_KEYW IDENT
2251da177e4SLinus Torvalds { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; }
2261da177e4SLinus Torvalds | ENUM_KEYW IDENT
2271da177e4SLinus Torvalds { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; }
2281da177e4SLinus Torvalds
2291da177e4SLinus Torvalds /* Full definitions of an s/u/e. Record it. */
2301da177e4SLinus Torvalds | STRUCT_KEYW IDENT class_body
231b06fcd6cSMichal Marek { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; }
2321da177e4SLinus Torvalds | UNION_KEYW IDENT class_body
233b06fcd6cSMichal Marek { record_compound($1, $2, $3, SYM_UNION); $$ = $3; }
234e37ddb82SMichal Marek | ENUM_KEYW IDENT enum_body
235b06fcd6cSMichal Marek { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; }
236e37ddb82SMichal Marek /*
237e37ddb82SMichal Marek * Anonymous enum definition. Tell add_symbol() to restart its counter.
238e37ddb82SMichal Marek */
239e37ddb82SMichal Marek | ENUM_KEYW enum_body
240e37ddb82SMichal Marek { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
241e37ddb82SMichal Marek /* Anonymous s/u definitions. Nothing needs doing. */
2421da177e4SLinus Torvalds | STRUCT_KEYW class_body { $$ = $2; }
2431da177e4SLinus Torvalds | UNION_KEYW class_body { $$ = $2; }
2441da177e4SLinus Torvalds ;
2451da177e4SLinus Torvalds
2461da177e4SLinus Torvalds simple_type_specifier:
2471da177e4SLinus Torvalds CHAR_KEYW
2481da177e4SLinus Torvalds | SHORT_KEYW
2491da177e4SLinus Torvalds | INT_KEYW
2501da177e4SLinus Torvalds | LONG_KEYW
2511da177e4SLinus Torvalds | SIGNED_KEYW
2521da177e4SLinus Torvalds | UNSIGNED_KEYW
2531da177e4SLinus Torvalds | FLOAT_KEYW
2541da177e4SLinus Torvalds | DOUBLE_KEYW
2551da177e4SLinus Torvalds | VOID_KEYW
2561da177e4SLinus Torvalds | BOOL_KEYW
2570efdb228SNicholas Piggin | VA_LIST_KEYW
258a222061bSWill Deacon | BUILTIN_INT_KEYW
2591da177e4SLinus Torvalds | TYPE { (*$1)->tag = SYM_TYPEDEF; $$ = $1; }
2601da177e4SLinus Torvalds ;
2611da177e4SLinus Torvalds
2621da177e4SLinus Torvalds ptr_operator:
2631da177e4SLinus Torvalds '*' cvar_qualifier_seq_opt
2641da177e4SLinus Torvalds { $$ = $2 ? $2 : $1; }
2651da177e4SLinus Torvalds ;
2661da177e4SLinus Torvalds
2671da177e4SLinus Torvalds cvar_qualifier_seq_opt:
2681da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
2691da177e4SLinus Torvalds | cvar_qualifier_seq
2701da177e4SLinus Torvalds ;
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvalds cvar_qualifier_seq:
2731da177e4SLinus Torvalds cvar_qualifier
2741da177e4SLinus Torvalds | cvar_qualifier_seq cvar_qualifier { $$ = $2; }
2751da177e4SLinus Torvalds ;
2761da177e4SLinus Torvalds
2771da177e4SLinus Torvalds cvar_qualifier:
2781da177e4SLinus Torvalds CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE
2791da177e4SLinus Torvalds | RESTRICT_KEYW
2801da177e4SLinus Torvalds { /* restrict has no effect in prototypes so ignore it */
2811da177e4SLinus Torvalds remove_node($1);
2821da177e4SLinus Torvalds $$ = $1;
2831da177e4SLinus Torvalds }
2841da177e4SLinus Torvalds ;
2851da177e4SLinus Torvalds
2861da177e4SLinus Torvalds declarator:
2871da177e4SLinus Torvalds ptr_operator declarator { $$ = $2; }
2881da177e4SLinus Torvalds | direct_declarator
2891da177e4SLinus Torvalds ;
2901da177e4SLinus Torvalds
2911da177e4SLinus Torvalds direct_declarator:
2921da177e4SLinus Torvalds IDENT
2931da177e4SLinus Torvalds { if (current_name != NULL) {
2941da177e4SLinus Torvalds error_with_pos("unexpected second declaration name");
2951da177e4SLinus Torvalds YYERROR;
2961da177e4SLinus Torvalds } else {
2971da177e4SLinus Torvalds current_name = (*$1)->string;
2981da177e4SLinus Torvalds $$ = $1;
2991da177e4SLinus Torvalds }
3001da177e4SLinus Torvalds }
3011c722503SRichard Yao | TYPE
3021c722503SRichard Yao { if (current_name != NULL) {
3031c722503SRichard Yao error_with_pos("unexpected second declaration name");
3041c722503SRichard Yao YYERROR;
3051c722503SRichard Yao } else {
3061c722503SRichard Yao current_name = (*$1)->string;
3071c722503SRichard Yao $$ = $1;
3081c722503SRichard Yao }
3091c722503SRichard Yao }
3101da177e4SLinus Torvalds | direct_declarator '(' parameter_declaration_clause ')'
3111da177e4SLinus Torvalds { $$ = $4; }
3121da177e4SLinus Torvalds | direct_declarator '(' error ')'
3131da177e4SLinus Torvalds { $$ = $4; }
3141da177e4SLinus Torvalds | direct_declarator BRACKET_PHRASE
3151da177e4SLinus Torvalds { $$ = $2; }
3161da177e4SLinus Torvalds | '(' declarator ')'
3171da177e4SLinus Torvalds { $$ = $3; }
3181da177e4SLinus Torvalds ;
3191da177e4SLinus Torvalds
3201da177e4SLinus Torvalds /* Nested declarators differ from regular declarators in that they do
3211da177e4SLinus Torvalds not record the symbols they find in the global symbol table. */
3221da177e4SLinus Torvalds nested_declarator:
3231da177e4SLinus Torvalds ptr_operator nested_declarator { $$ = $2; }
3241da177e4SLinus Torvalds | direct_nested_declarator
3251da177e4SLinus Torvalds ;
3261da177e4SLinus Torvalds
3271da177e4SLinus Torvalds direct_nested_declarator:
3281da177e4SLinus Torvalds IDENT
3291da177e4SLinus Torvalds | TYPE
3301da177e4SLinus Torvalds | direct_nested_declarator '(' parameter_declaration_clause ')'
3311da177e4SLinus Torvalds { $$ = $4; }
3321da177e4SLinus Torvalds | direct_nested_declarator '(' error ')'
3331da177e4SLinus Torvalds { $$ = $4; }
3341da177e4SLinus Torvalds | direct_nested_declarator BRACKET_PHRASE
3351da177e4SLinus Torvalds { $$ = $2; }
3361da177e4SLinus Torvalds | '(' nested_declarator ')'
3371da177e4SLinus Torvalds { $$ = $3; }
3381da177e4SLinus Torvalds | '(' error ')'
3391da177e4SLinus Torvalds { $$ = $3; }
3401da177e4SLinus Torvalds ;
3411da177e4SLinus Torvalds
3421da177e4SLinus Torvalds parameter_declaration_clause:
3431da177e4SLinus Torvalds parameter_declaration_list_opt DOTS { $$ = $2; }
3441da177e4SLinus Torvalds | parameter_declaration_list_opt
3451da177e4SLinus Torvalds | parameter_declaration_list ',' DOTS { $$ = $3; }
3461da177e4SLinus Torvalds ;
3471da177e4SLinus Torvalds
3481da177e4SLinus Torvalds parameter_declaration_list_opt:
3491da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
3501da177e4SLinus Torvalds | parameter_declaration_list
3511da177e4SLinus Torvalds ;
3521da177e4SLinus Torvalds
3531da177e4SLinus Torvalds parameter_declaration_list:
3541da177e4SLinus Torvalds parameter_declaration
3551da177e4SLinus Torvalds | parameter_declaration_list ',' parameter_declaration
3561da177e4SLinus Torvalds { $$ = $3; }
3571da177e4SLinus Torvalds ;
3581da177e4SLinus Torvalds
3591da177e4SLinus Torvalds parameter_declaration:
3601da177e4SLinus Torvalds decl_specifier_seq m_abstract_declarator
3611da177e4SLinus Torvalds { $$ = $2 ? $2 : $1; }
3621da177e4SLinus Torvalds ;
3631da177e4SLinus Torvalds
3641da177e4SLinus Torvalds m_abstract_declarator:
3651da177e4SLinus Torvalds ptr_operator m_abstract_declarator
3661da177e4SLinus Torvalds { $$ = $2 ? $2 : $1; }
3671da177e4SLinus Torvalds | direct_m_abstract_declarator
3681da177e4SLinus Torvalds ;
3691da177e4SLinus Torvalds
3701da177e4SLinus Torvalds direct_m_abstract_declarator:
3711da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
3721da177e4SLinus Torvalds | IDENT
3731da177e4SLinus Torvalds { /* For version 2 checksums, we don't want to remember
3741da177e4SLinus Torvalds private parameter names. */
3751da177e4SLinus Torvalds remove_node($1);
3761da177e4SLinus Torvalds $$ = $1;
3771da177e4SLinus Torvalds }
3781da177e4SLinus Torvalds /* This wasn't really a typedef name but an identifier that
3791da177e4SLinus Torvalds shadows one. */
3801da177e4SLinus Torvalds | TYPE
3811da177e4SLinus Torvalds { remove_node($1);
3821da177e4SLinus Torvalds $$ = $1;
3831da177e4SLinus Torvalds }
3841da177e4SLinus Torvalds | direct_m_abstract_declarator '(' parameter_declaration_clause ')'
3851da177e4SLinus Torvalds { $$ = $4; }
3861da177e4SLinus Torvalds | direct_m_abstract_declarator '(' error ')'
3871da177e4SLinus Torvalds { $$ = $4; }
3881da177e4SLinus Torvalds | direct_m_abstract_declarator BRACKET_PHRASE
3891da177e4SLinus Torvalds { $$ = $2; }
3901da177e4SLinus Torvalds | '(' m_abstract_declarator ')'
3911da177e4SLinus Torvalds { $$ = $3; }
3921da177e4SLinus Torvalds | '(' error ')'
3931da177e4SLinus Torvalds { $$ = $3; }
3941da177e4SLinus Torvalds ;
3951da177e4SLinus Torvalds
3961da177e4SLinus Torvalds function_definition:
3971da177e4SLinus Torvalds decl_specifier_seq_opt declarator BRACE_PHRASE
3981da177e4SLinus Torvalds { struct string_list *decl = *$2;
3991da177e4SLinus Torvalds *$2 = NULL;
4001da177e4SLinus Torvalds add_symbol(current_name, SYM_NORMAL, decl, is_extern);
4011da177e4SLinus Torvalds $$ = $3;
4021da177e4SLinus Torvalds }
4031da177e4SLinus Torvalds ;
4041da177e4SLinus Torvalds
4051da177e4SLinus Torvalds initializer_opt:
4061da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
4071da177e4SLinus Torvalds | initializer
4081da177e4SLinus Torvalds ;
4091da177e4SLinus Torvalds
4101da177e4SLinus Torvalds /* We never care about the contents of an initializer. */
4111da177e4SLinus Torvalds initializer:
4121da177e4SLinus Torvalds '=' EXPRESSION_PHRASE
4131da177e4SLinus Torvalds { remove_list($2, &(*$1)->next); $$ = $2; }
4141da177e4SLinus Torvalds ;
4151da177e4SLinus Torvalds
4161da177e4SLinus Torvalds class_body:
4171da177e4SLinus Torvalds '{' member_specification_opt '}' { $$ = $3; }
4181da177e4SLinus Torvalds | '{' error '}' { $$ = $3; }
4191da177e4SLinus Torvalds ;
4201da177e4SLinus Torvalds
4211da177e4SLinus Torvalds member_specification_opt:
4221da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
4231da177e4SLinus Torvalds | member_specification
4241da177e4SLinus Torvalds ;
4251da177e4SLinus Torvalds
4261da177e4SLinus Torvalds member_specification:
4271da177e4SLinus Torvalds member_declaration
4281da177e4SLinus Torvalds | member_specification member_declaration { $$ = $2; }
4291da177e4SLinus Torvalds ;
4301da177e4SLinus Torvalds
4311da177e4SLinus Torvalds member_declaration:
4321da177e4SLinus Torvalds decl_specifier_seq_opt member_declarator_list_opt ';'
4331da177e4SLinus Torvalds { $$ = $3; }
4341da177e4SLinus Torvalds | error ';'
4351da177e4SLinus Torvalds { $$ = $2; }
4361da177e4SLinus Torvalds ;
4371da177e4SLinus Torvalds
4381da177e4SLinus Torvalds member_declarator_list_opt:
4391da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
4401da177e4SLinus Torvalds | member_declarator_list
4411da177e4SLinus Torvalds ;
4421da177e4SLinus Torvalds
4431da177e4SLinus Torvalds member_declarator_list:
4441da177e4SLinus Torvalds member_declarator
4451da177e4SLinus Torvalds | member_declarator_list ',' member_declarator { $$ = $3; }
4461da177e4SLinus Torvalds ;
4471da177e4SLinus Torvalds
4481da177e4SLinus Torvalds member_declarator:
4491da177e4SLinus Torvalds nested_declarator attribute_opt { $$ = $2 ? $2 : $1; }
4501da177e4SLinus Torvalds | IDENT member_bitfield_declarator { $$ = $2; }
4511da177e4SLinus Torvalds | member_bitfield_declarator
4521da177e4SLinus Torvalds ;
4531da177e4SLinus Torvalds
4541da177e4SLinus Torvalds member_bitfield_declarator:
4551da177e4SLinus Torvalds ':' EXPRESSION_PHRASE { $$ = $2; }
4561da177e4SLinus Torvalds ;
4571da177e4SLinus Torvalds
4581da177e4SLinus Torvalds attribute_opt:
4591da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
46094aa3d71SAndreas Gruenbacher | attribute_opt ATTRIBUTE_PHRASE
4611da177e4SLinus Torvalds ;
4621da177e4SLinus Torvalds
463e37ddb82SMichal Marek enum_body:
464e37ddb82SMichal Marek '{' enumerator_list '}' { $$ = $3; }
465e37ddb82SMichal Marek | '{' enumerator_list ',' '}' { $$ = $4; }
466e37ddb82SMichal Marek ;
467e37ddb82SMichal Marek
468e37ddb82SMichal Marek enumerator_list:
469e37ddb82SMichal Marek enumerator
470e37ddb82SMichal Marek | enumerator_list ',' enumerator
471e37ddb82SMichal Marek
472e37ddb82SMichal Marek enumerator:
473e37ddb82SMichal Marek IDENT
474e37ddb82SMichal Marek {
475e37ddb82SMichal Marek const char *name = strdup((*$1)->string);
476e37ddb82SMichal Marek add_symbol(name, SYM_ENUM_CONST, NULL, 0);
477e37ddb82SMichal Marek }
478e37ddb82SMichal Marek | IDENT '=' EXPRESSION_PHRASE
479e37ddb82SMichal Marek {
480e37ddb82SMichal Marek const char *name = strdup((*$1)->string);
481e37ddb82SMichal Marek struct string_list *expr = copy_list_range(*$3, *$2);
482e37ddb82SMichal Marek add_symbol(name, SYM_ENUM_CONST, expr, 0);
483e37ddb82SMichal Marek }
484e37ddb82SMichal Marek
4851da177e4SLinus Torvalds asm_definition:
4861da177e4SLinus Torvalds ASM_PHRASE ';' { $$ = $2; }
4871da177e4SLinus Torvalds ;
4881da177e4SLinus Torvalds
4891da177e4SLinus Torvalds asm_phrase_opt:
4901da177e4SLinus Torvalds /* empty */ { $$ = NULL; }
4911da177e4SLinus Torvalds | ASM_PHRASE
4921da177e4SLinus Torvalds ;
4931da177e4SLinus Torvalds
4941da177e4SLinus Torvalds export_definition:
4951da177e4SLinus Torvalds EXPORT_SYMBOL_KEYW '(' IDENT ')' ';'
4961da177e4SLinus Torvalds { export_symbol((*$3)->string); $$ = $5; }
4971da177e4SLinus Torvalds ;
4981da177e4SLinus Torvalds
499*9ab55d7fSMarco Elver /* Ignore any module scoped _Static_assert(...) */
500*9ab55d7fSMarco Elver static_assert:
501*9ab55d7fSMarco Elver STATIC_ASSERT_PHRASE ';' { $$ = $2; }
502*9ab55d7fSMarco Elver ;
5031da177e4SLinus Torvalds
5041da177e4SLinus Torvalds %%
5051da177e4SLinus Torvalds
5061da177e4SLinus Torvalds static void
5071da177e4SLinus Torvalds yyerror(const char *e)
5081da177e4SLinus Torvalds {
5091da177e4SLinus Torvalds error_with_pos("%s", e);
5101da177e4SLinus Torvalds }
511