xref: /openbmc/linux/scripts/genksyms/parse.y (revision 9ab55d7f)
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