1 /*-----------------------------------------------------------------------
3 SDCC.y - parser definition file for sdcc
5 Written By : Sandeep Dutta . sandeep.dutta@usa.net (1997)
6 Revised by : Philipp Klaus Krause krauspeh@informatik.uni-freiburg.de (2022)
7 Using inspiration from the grammar by Jutta Degener as extended by Jens Gustedt (under Expat license)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
31 #include "SDCCglobl.h"
34 #include "SDCChasht.h"
42 #include "SDCCbtree.h"
44 #include "dbuf_string.h"
46 extern
int yyerror (char *);
48 long NestLevel
= 0; /* current NestLevel */
49 int stackPtr
= 1; /* stack pointer */
50 int xstackPtr
= 0; /* xstack pointer */
52 int blockNo
= 0; /* sequential block number */
54 int inCriticalFunction
= 0;
55 int inCriticalBlock
= 0;
56 int seqPointNo
= 1; /* sequence point number */
57 int ignoreTypedefType
=0;
61 char lbuff
[1024]; /* local buffer */
62 char function_name
[256] = {0};
64 /* break & continue stacks */
65 STACK_DCL
(continueStack
,symbol
*,MAX_NEST_LEVEL
)
66 STACK_DCL
(breakStack
,symbol
*,MAX_NEST_LEVEL
)
67 STACK_DCL
(forStack
,symbol
*,MAX_NEST_LEVEL
)
68 STACK_DCL
(swStk
,ast
*,MAX_NEST_LEVEL
)
69 STACK_DCL
(blockNum
,int,MAX_NEST_LEVEL
*3)
71 value
*cenum
= NULL
; /* current enumeration type chain*/
72 bool uselessDecl
= true
;
80 attribute
*attr
; /* attribute */
81 symbol
*sym
; /* symbol table pointer */
82 structdef
*sdef
; /* structure definition */
83 char yychar[SDCC_NAME_MAX
+1];
84 sym_link
*lnk
; /* declarator or specifier */
85 int yyint
; /* integer value returned */
86 value
*val
; /* for integer constant */
87 initList
*ilist
; /* initial list */
88 designation
*dsgn
; /* designator */
89 const char *yystr
; /* pointer to dynamicaly allocated string */
90 ast
*asts
; /* expression tree */
93 %token
<yychar> IDENTIFIER TYPE_NAME ADDRSPACE_NAME
95 %token SIZEOF OFFSETOF
96 %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
98 %token ATTR_START TOK_SEP
99 %token
<yyint
> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
100 %token
<yyint
> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
101 %token
<yyint
> XOR_ASSIGN OR_ASSIGN
102 %token TYPEDEF EXTERN STATIC AUTO REGISTER CONSTEXPR CODE EEPROM INTERRUPT SFR SFR16 SFR32 ADDRESSMOD
103 %token AT SBIT REENTRANT USING XDATA DATA IDATA PDATA ELLIPSIS CRITICAL
104 %token NONBANKED BANKED SHADOWREGS SD_WPARAM
105 %token SD_BOOL SD_CHAR SD_SHORT SD_INT SD_LONG SIGNED UNSIGNED SD_FLOAT DOUBLE FIXED16X16 SD_CONST VOLATILE SD_VOID BIT
106 %token COMPLEX IMAGINARY
107 %token STRUCT UNION ENUM RANGE SD_FAR
108 %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
109 %token NAKED JAVANATIVE OVERLAY TRAP
110 %token
<yystr
> STRING_LITERAL INLINEASM FUNC
111 %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SET_VALUE_AT_ADDRESS SPIL UNSPIL GETABIT GETBYTE GETWORD
112 %token BITWISEAND UNARYMINUS IPUSH IPUSH_VALUE_AT_ADDRESS IPOP PCALL ENDFUNCTION JUMPTABLE
114 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
115 %token DUMMY_READ_VOLATILE ENDCRITICAL INLINE RESTRICT SMALLC RAISONANCE IAR COSMIC SDCCCALL PRESERVES_REGS Z88DK_FASTCALL Z88DK_CALLEE Z88DK_SHORTCALL Z88DK_PARAMS_OFFSET
118 %token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATIC_ASSERT THREAD_LOCAL
120 /* C23 problem: too many legacy FALSE and TRUE still in SDCC, workaround: prefix by TOKEN_*/
121 %token TOKEN_FALSE TOKEN_TRUE NULLPTR TYPEOF TYPEOF_UNQUAL SD_BITINT
122 %token DECIMAL32 DECIMAL64 DECIMAL128
124 /* SDCC extensions */
127 /* For internal use (in further stages of SDCC) */
128 %token GENERIC_ASSOC_LIST GENERIC_ASSOCIATION
130 /* If an enum type specifier is another enum (invalid but syntactically possible), make sure that the next '{' is part of the inner enum.
131 * If an enum specifier is in a struct, the next ':' belongs to its enum type specifier.
132 * Reason from C23: "If an enum type specifier is present, then the longest possible sequence of tokens that can be
133 * interpreted as a specifier qualifier list is interpreted as part of the enum type specifier." */
136 %type
<yyint
> Interrupt_storage
137 %type
<attr
> attribute_specifier_sequence attribute_specifier_sequence_opt attribute_specifier attribute_list attribute attribute_opt
138 %type
<sym
> identifier attribute_token declarator declarator2 direct_declarator array_declarator enumerator_list enumerator
139 %type
<sym
> member_declarator function_declarator
140 %type
<sym
> member_declarator_list member_declaration member_declaration_list
141 %type
<sym
> declaration init_declarator_list init_declarator
142 %type
<sym
> declaration_list identifier_list
143 %type
<sym
> kr_declaration kr_declaration_list
144 %type
<sym
> declaration_after_statement
145 %type
<sym
> declarator2_function_attributes while do for critical
146 %type
<sym
> addressmod
147 %type
<lnk
> pointer specifier_qualifier_list type_specifier_list_ type_specifier_qualifier type_specifier typeof_specifier type_qualifier_list type_qualifier_list_opt type_qualifier type_name
148 %type
<lnk
> type_specifier_list_without_struct_or_union type_specifier_qualifier_without_struct_or_union type_specifier_without_struct_or_union
149 %type
<lnk
> storage_class_specifier struct_or_union_specifier function_specifier alignment_specifier
150 %type
<lnk
> declaration_specifiers declaration_specifiers_ sfr_reg_bit sfr_attributes
151 %type
<lnk
> function_attribute function_attributes enum_specifier enum_comma_opt enum_type_specifier simple_typed_enum_decl
152 %type
<lnk
> abstract_declarator direct_abstract_declarator direct_abstract_declarator_opt array_abstract_declarator function_abstract_declarator
153 %type
<lnk
> unqualified_pointer
154 %type
<val
> parameter_type_list parameter_list parameter_declaration opt_assign_expr
155 %type
<sdef
> stag opt_stag
156 %type
<asts
> primary_expression
157 %type
<asts
> postfix_expression unary_expression offsetof_member_designator cast_expression multiplicative_expression
158 %type
<asts
> additive_expression shift_expression relational_expression equality_expression
159 %type
<asts
> and_expression exclusive_or_expression inclusive_or_expression logical_or_expr
160 %type
<asts
> logical_and_expr conditional_expr assignment_expr constant_expr constant_range_expr
161 %type
<asts
> expression argument_expr_list function_definition expression_opt predefined_constant
162 %type
<asts
> statement_list statement labeled_statement unlabeled_statement compound_statement
163 %type
<asts
> primary_block secondary_block
164 %type
<asts
> expression_statement selection_statement iteration_statement
165 %type
<asts
> jump_statement else_statement function_body string_literal_val
166 %type
<asts
> critical_statement asm_statement label
167 %type
<asts
> generic_selection generic_assoc_list generic_association generic_controlling_operand
168 %type
<asts
> implicit_block statements_and_implicit block_item_list
169 %type
<dsgn
> designator designator_list designation designation_opt
170 %type
<ilist
> initializer initializer_list
171 %type
<yyint
> unary_operator assignment_operator struct_or_union
172 %type
<yystr
> asm_string_literal
178 /* C23 A.2.1 Expressions */
181 : identifier
{ $$
= newAst_VALUE
(symbolVal
($1)); }
182 | CONSTANT
{ $$
= newAst_VALUE
($1); }
184 |
'(' expression
')' { $$
= $2; }
186 | predefined_constant
190 : TOKEN_FALSE
{ $$
= newAst_VALUE
(constBoolVal
(false
, true
)); }
191 | TOKEN_TRUE
{ $$
= newAst_VALUE
(constBoolVal
(true
, true
)); }
192 | NULLPTR
{ $$
= newAst_VALUE
(constNullptrVal
()); }
196 : GENERIC
'(' generic_controlling_operand
',' generic_assoc_list
')' { $$
= newNode
(GENERIC
, $3, $5); }
199 generic_controlling_operand
201 | type_name
{ $$
= newAst_LINK
($1); }
205 : generic_association
{ $$
= newNode
(GENERIC_ASSOC_LIST
, NULL
, $1); }
206 | generic_assoc_list
',' generic_association
{ $$
= newNode
(GENERIC_ASSOC_LIST
, $1, $3); }
210 : type_name
':' assignment_expr
{ $$
= newNode
(GENERIC_ASSOCIATION
, newAst_LINK
($1), $3); }
211 | DEFAULT
':' assignment_expr
{ $$
= newNode
(GENERIC_ASSOCIATION
,NULL
,$3); }
216 | postfix_expression
'[' expression
']' { $$
= newNode
('[', $1, $3); }
217 | postfix_expression
'(' ')' { $$
= newNode
(CALL
,$1,NULL
);
218 $$
->left
->funcName
= 1;}
219 | postfix_expression
'(' argument_expr_list
')'
221 $$
= newNode
(CALL
,$1,$3); $$
->left
->funcName
= 1;
223 | postfix_expression
'.' { ignoreTypedefType
= 1; } identifier
225 ignoreTypedefType
= 0;
226 $4 = newSymbol
($4->name
,NestLevel
);
228 $$
= newNode
(PTR_OP
,newNode
('&',$1,NULL
),newAst_VALUE
(symbolVal
($4)));
230 | postfix_expression PTR_OP
{ ignoreTypedefType
= 1; } identifier
232 ignoreTypedefType
= 0;
233 $4 = newSymbol
($4->name
,NestLevel
);
235 $$
= newNode
(PTR_OP
,$1,newAst_VALUE
(symbolVal
($4)));
237 | postfix_expression INC_OP
238 { $$
= newNode
(INC_OP
,$1,NULL
);}
239 | postfix_expression DEC_OP
240 { $$
= newNode
(DEC_OP
,$1,NULL
); }
241 |
'(' type_name
')' '{' initializer_list
'}'
243 /* if (!options.std_c99) */
244 werror
(E_COMPOUND_LITERALS_C99
);
246 /* TODO: implement compound literals (C99) */
247 $$
= newAst_VALUE
(valueFromLit
(0));
249 |
'(' type_name
')' '{' initializer_list
',' '}'
251 // if (!options.std_c99)
252 werror
(E_COMPOUND_LITERALS_C99
);
254 // TODO: implement compound literals (C99)
255 $$
= newAst_VALUE
(valueFromLit
(0));
257 |
'(' type_name
')' '{' '}'
259 if
(!options.std_c23
)
260 werror
(W_EMPTY_INIT_C23
);
261 // if (!options.std_c99)
262 werror
(E_COMPOUND_LITERALS_C99
);
264 // TODO: implement compound literals (C99)
265 $$
= newAst_VALUE
(valueFromLit
(0));
271 | assignment_expr
',' argument_expr_list
{ $$
= newNode
(PARAM
,$1,$3); }
276 | INC_OP unary_expression
{ $$
= newNode
(INC_OP
, NULL
, $2); }
277 | DEC_OP unary_expression
{ $$
= newNode
(DEC_OP
, NULL
, $2); }
278 | unary_operator cast_expression
280 if
($1 == '&' && IS_AST_OP
($2) && $2->opval.op
== '*' && $2->right
== NULL
)
282 else if
($1 == '*' && IS_AST_OP
($2) && $2->opval.op
== '&' && $2->right
== NULL
)
285 $$
= newNode
($1, $2, NULL
);
287 | SIZEOF unary_expression
{ $$
= newNode
(SIZEOF
, NULL
, $2); }
288 | SIZEOF
'(' type_name
')' { $$
= newAst_VALUE
(sizeofOp
($3)); }
289 | ALIGNOF
'(' type_name
')' { $$
= newAst_VALUE
(alignofOp
($3)); }
290 | OFFSETOF
'(' type_name
',' offsetof_member_designator
')' { $$
= offsetofOp
($3, $5); }
291 | ROT
'(' unary_expression
',' unary_expression
')' { $$
= newNode
(ROT
, $3, $5); }
305 |
'(' type_name
')' cast_expression
{ $$
= newNode
(CAST
,newAst_LINK
($2),$4); }
308 multiplicative_expression
310 | multiplicative_expression
'*' cast_expression
{ $$
= newNode
('*',$1,$3);}
311 | multiplicative_expression
'/' cast_expression
{ $$
= newNode
('/',$1,$3);}
312 | multiplicative_expression
'%' cast_expression
{ $$
= newNode
('%',$1,$3);}
316 : multiplicative_expression
317 | additive_expression
'+' multiplicative_expression
{ $$
=newNode
('+',$1,$3);}
318 | additive_expression
'-' multiplicative_expression
{ $$
=newNode
('-',$1,$3);}
322 : additive_expression
323 | shift_expression LEFT_OP additive_expression
{ $$
= newNode
(LEFT_OP
,$1,$3); }
324 | shift_expression RIGHT_OP additive_expression
{ $$
= newNode
(RIGHT_OP
,$1,$3); }
327 relational_expression
329 | relational_expression
'<' shift_expression
{ $$
= newNode
('<', $1,$3);}
330 | relational_expression
'>' shift_expression
{ $$
= newNode
('>', $1,$3);}
331 | relational_expression LE_OP shift_expression
{ $$
= newNode
(LE_OP
,$1,$3);}
332 | relational_expression GE_OP shift_expression
{ $$
= newNode
(GE_OP
,$1,$3);}
336 : relational_expression
337 | equality_expression EQ_OP relational_expression
{ $$
= newNode
(EQ_OP
,$1,$3);}
338 | equality_expression NE_OP relational_expression
{ $$
= newNode
(NE_OP
,$1,$3);}
342 : equality_expression
343 | and_expression
'&' equality_expression
{ $$
= newNode
('&',$1,$3);}
346 exclusive_or_expression
348 | exclusive_or_expression
'^' and_expression
{ $$
= newNode
('^',$1,$3);}
351 inclusive_or_expression
352 : exclusive_or_expression
353 | inclusive_or_expression
'|' exclusive_or_expression
{ $$
= newNode
('|',$1,$3);}
357 : inclusive_or_expression
358 | logical_and_expr AND_OP
{ seqPointNo
++;} inclusive_or_expression
359 { $$
= newNode
(AND_OP
,$1,$4);}
364 | logical_or_expr OR_OP
{ seqPointNo
++;} logical_and_expr
365 { $$
= newNode
(OR_OP
,$1,$4); }
370 | logical_or_expr
'?' { seqPointNo
++;} expression
':' conditional_expr
372 $$
= newNode
(':',$4,$6);
373 $$
= newNode
('?',$1,$$
);
379 | unary_expression assignment_operator assignment_expr
384 $$
= newNode
($2,$1,$3);
387 $$
= createRMW
($1, '*', $3);
390 $$
= createRMW
($1, '/', $3);
393 $$
= createRMW
($1, '%', $3);
396 $$
= createRMW
($1, '+', $3);
399 $$
= createRMW
($1, '-', $3);
402 $$
= createRMW
($1, LEFT_OP
, $3);
405 $$
= createRMW
($1, RIGHT_OP
, $3);
408 $$
= createRMW
($1, '&', $3);
411 $$
= createRMW
($1, '^', $3);
414 $$
= createRMW
($1, '|', $3);
439 | expression
',' { seqPointNo
++;} assignment_expr
{ $$
= newNode
(',',$1,$4);}
443 : { $$
= NULL
; seqPointNo
++; }
444 | expression
{ $$
= $1; seqPointNo
++; }
452 : constant_expr ELLIPSIS constant_expr
{ $$
= newNode
(ELLIPSIS
,$1,$3); }
455 /* C23 A.2.2 Declarations */
458 : simple_typed_enum_decl
463 | declaration_specifiers
';'
465 /* Special case: if incomplete struct/union declared without name, */
466 /* make sure an incomplete type for it exists in the current scope */
469 structdef
*sdef
= SPEC_STRUCT
($1);
471 osdef
= findSymWithBlock
(StructTab
, sdef
->tagsym
, currBlockno
, NestLevel
);
472 if
(osdef
&& osdef
->block
!= currBlockno
)
474 sdef
= newStruct
(osdef
->tagsym
->name
);
475 sdef
->level
= NestLevel
;
476 sdef
->block
= currBlockno
;
477 sdef
->tagsym
= newSymbol
(osdef
->tagsym
->name
, NestLevel
);
478 addSym
(StructTab
, sdef
, sdef
->tag
, sdef
->level
, currBlockno
, 0);
483 werror
(W_USELESS_DECL
);
487 | declaration_specifiers init_declarator_list
';'
489 /* add the specifier list to the id */
492 bool autocandidate
= options.std_c23
&& IS_SPEC
($1) && SPEC_SCLS
($1) == S_AUTO
;
494 for
(sym1
= sym
= reverseSyms
($2);sym
!= NULL
;sym
= sym
->next
) {
495 sym_link
*lnk
= copyLinkChain
($1);
496 sym_link
*l0
= NULL
, *l1
= NULL
, *l2
= NULL
;
497 /* check illegal declaration */
498 for
(l0
= sym
->type
; l0
!= NULL
; l0
= l0
->next
)
501 /* check if creating instances of structs with flexible arrays */
502 for
(l1
= lnk
; l1
!= NULL
; l1
= l1
->next
)
503 if
(IS_STRUCT
(l1
) && SPEC_STRUCT
(l1
)->b_flexArrayMember
)
505 if
(!options.std_c99
&& l0
== NULL
&& l1
!= NULL
&& SPEC_EXTR
($1) != 1)
506 werror
(W_FLEXARRAY_INSTRUCT
, sym
->name
);
507 /* check if creating instances of function type */
508 for
(l1
= lnk
; l1
!= NULL
; l1
= l1
->next
)
511 for
(l2
= lnk
; l2
!= NULL
; l2
= l2
->next
)
514 if
(l0
== NULL
&& l2
== NULL
&& l1
!= NULL
)
515 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_TYPE_IS_FUNCTION
, sym
->name
);
516 if
(autocandidate
&& !sym
->type
&& sym
->ival
&& sym
->ival
->type
== INIT_NODE
) // C23 auto type inference
518 sym
->type
= sym
->etype
= typeofOp
(sym
->ival
->init.node
);
521 /* do the pointer stuff */
522 pointerTypes
(sym
->type
,lnk
);
529 | static_assert_declaration
533 | attribute_declaration
539 declaration_specifiers
: declaration_specifiers_
{ $$
= finalizeSpec
($1); };
541 declaration_specifiers_
542 : storage_class_specifier
{ $$
= $1; }
543 | storage_class_specifier declaration_specifiers_
{
544 /* if the decl $2 is not a specifier */
545 /* find the spec and replace it */
546 $$
= mergeDeclSpec
($1, $2, "storage_class_specifier declaration_specifiers - skipped");
548 | type_specifier_qualifier
{ $$
= $1; }
549 | type_specifier_qualifier declaration_specifiers_
{
550 /* if the decl $2 is not a specifier */
551 /* find the spec and replace it */
552 $$
= mergeDeclSpec
($1, $2, "type_specifier_qualifier declaration_specifiers - skipped");
554 | function_specifier
{ $$
= $1; }
555 | function_specifier declaration_specifiers_
{
556 /* if the decl $2 is not a specifier */
557 /* find the spec and replace it */
558 $$
= mergeDeclSpec
($1, $2, "function_specifier declaration_specifiers - skipped");
564 | init_declarator_list
',' init_declarator
{ $3->next
= $1; $$
= $3;}
568 : declarator
{ $1->ival
= NULL
; }
569 | declarator
'=' initializer
{ $1->ival
= $3; seqPointNo
++; }
572 attribute_declaration
573 : attribute_specifier_sequence
';'
576 storage_class_specifier
578 $$
= newLink
(SPECIFIER
);
579 SPEC_TYPEDEF
($$
) = 1;
582 $$
= newLink
(SPECIFIER
);
586 $$
= newLink
(SPECIFIER
);
592 werror
(E_THREAD_LOCAL
);
595 $$
= newLink
(SPECIFIER
);
596 SPEC_SCLS
($$
) = S_AUTO
;
599 $$
= newLink
(SPECIFIER
);
600 SPEC_SCLS
($$
) = S_REGISTER
;
603 $$
= newLink
(SPECIFIER
);
604 werror
(E_CONSTEXPR
);
609 * Structs and unions have been factored out to avoid parsing conflicts with
610 * enum-type-specifier, which semantically cannot be a struct or union, anyway.
614 : type_specifier_without_struct_or_union
{ $$
= $1; }
615 | struct_or_union_specifier
{
618 ignoreTypedefType
= 1;
622 type_specifier_without_struct_or_union
624 $$
=newLink
(SPECIFIER
);
625 SPEC_NOUN
($$
) = V_VOID
;
626 ignoreTypedefType
= 1;
629 $$
=newLink
(SPECIFIER
);
630 SPEC_NOUN
($$
) = V_CHAR
;
631 ignoreTypedefType
= 1;
634 $$
=newLink
(SPECIFIER
);
636 ignoreTypedefType
= 1;
639 $$
=newLink
(SPECIFIER
);
640 SPEC_NOUN
($$
) = V_INT
;
641 ignoreTypedefType
= 1;
644 $$
=newLink
(SPECIFIER
);
646 ignoreTypedefType
= 1;
649 $$
=newLink
(SPECIFIER
);
650 SPEC_NOUN
($$
) = V_FLOAT
;
651 ignoreTypedefType
= 1;
654 $$
=newLink
(SPECIFIER
);
655 SPEC_NOUN
($$
) = V_DOUBLE
;
656 ignoreTypedefType
= 1;
659 $$
=newLink
(SPECIFIER
);
660 $$
->select.s.b_signed
= 1;
661 ignoreTypedefType
= 1;
664 $$
=newLink
(SPECIFIER
);
666 ignoreTypedefType
= 1;
668 | SD_BITINT
'(' constant_expr
')' {
669 $$
=newLink
(SPECIFIER
);
670 SPEC_NOUN
($$
) = V_BITINT
;
671 SPEC_BITINTWIDTH
($$
) = (unsigned int) ulFromVal
(constExprValue
($3, true
));
672 ignoreTypedefType
= 1;
675 $$
=newLink
(SPECIFIER
);
676 SPEC_NOUN
($$
) = V_BOOL
;
677 ignoreTypedefType
= 1;
680 $$
=newLink
(SPECIFIER
);
681 werror
(E_COMPLEX_UNSUPPORTED
);
684 $$
=newLink
(SPECIFIER
);
685 werror
(E_COMPLEX_UNSUPPORTED
);
688 $$
=newLink
(SPECIFIER
);
689 werror
(E_DECIMAL_FLOAT_UNSUPPORTED
);
692 $$
=newLink
(SPECIFIER
);
693 werror
(E_DECIMAL_FLOAT_UNSUPPORTED
);
696 $$
=newLink
(SPECIFIER
);
697 werror
(E_DECIMAL_FLOAT_UNSUPPORTED
);
702 ignoreTypedefType
= 1;
709 sym
= findSym
(TypedefTab
,NULL
,$1);
710 $$
= p
= copyLinkChain
(sym ? sym
->type
: NULL
);
711 SPEC_TYPEDEF
(getSpec
(p
)) = 0;
712 ignoreTypedefType
= 1;
719 $$
=newLink
(SPECIFIER
);
720 SPEC_NOUN
($$
) = V_FIXED16X16
;
721 ignoreTypedefType
= 1;
724 $$
=newLink
(SPECIFIER
);
725 SPEC_NOUN
($$
) = V_BIT
;
726 SPEC_SCLS
($$
) = S_BIT
;
729 ignoreTypedefType
= 1;
732 $$
=newLink
(SPECIFIER
);
733 /* add this to the storage class specifier */
734 SPEC_ABSA
($$
) = 1; /* set the absolute addr flag */
735 /* now get the abs addr from value */
736 SPEC_ADDR
($$
) = (unsigned int) ulFromVal
(constExprValue
(newAst_VALUE
($2), true
));
738 | AT
'(' constant_expr
')' {
739 $$
=newLink
(SPECIFIER
);
740 /* add this to the storage class specifier */
741 SPEC_ABSA
($$
) = 1; /* set the absolute addr flag */
742 /* now get the abs addr from value */
743 SPEC_ADDR
($$
) = (unsigned int) ulFromVal
(constExprValue
($3, true
));
750 : TYPEOF
'(' expression
')'
755 | TYPEOF
'(' type_name
')'
757 checkTypeSanity
($3, "(typeof)");
760 | TYPEOF_UNQUAL
'(' expression
')'
764 wassert
(IS_SPEC
($$
));
766 SPEC_RESTRICT
($$
) = 0;
767 SPEC_VOLATILE
($$
) = 0;
768 SPEC_ATOMIC
($$
) = 0;
769 SPEC_ADDRSPACE
($$
) = 0;
771 | TYPEOF_UNQUAL
'(' type_name
')'
773 checkTypeSanity
($3, "(typeof_unqual)");
775 wassert
(IS_SPEC
($$
));
777 SPEC_RESTRICT
($$
) = 0;
778 SPEC_VOLATILE
($$
) = 0;
779 SPEC_ATOMIC
($$
) = 0;
780 SPEC_ADDRSPACE
($$
) = 0;
783 struct_or_union_specifier
784 : struct_or_union attribute_specifier_sequence_opt opt_stag
790 /* no tag given, so new struct def for current scope */
791 addSym
(StructTab
, $3, $3->tag
, $3->level
, currBlockno
, 0);
795 sdef
= findSymWithBlock
(StructTab
, $3->tagsym
, currBlockno
, NestLevel
);
798 /* Error if a complete type already defined in this scope */
799 if
(sdef
->block
== currBlockno
)
802 $3->redefinition
= true
;
803 else
// We are completing an incomplete type
808 /* There is an existing struct def in an outer scope. */
809 /* Create new struct def for current scope */
810 addSym
(StructTab
, $3, $3->tag
, $3->level
, currBlockno
, 0);
815 /* There is no existing struct def at all. */
816 /* Create new struct def for current scope */
817 addSym
(StructTab
, $3, $3->tag
, $3->level
, currBlockno
, 0);
828 werror
(E_BAD_TAG
, $3->tag
, $1==STRUCT ?
"struct" : "union");
831 '{' member_declaration_list
'}'
836 // check for errors in structure members
837 for
(sym
=$6; sym
; sym
=sym
->next
)
839 if
(IS_ABSOLUTE
(sym
->etype
))
841 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_NOT_ALLOWED
, "'at'");
842 SPEC_ABSA
(sym
->etype
) = 0;
844 if
(IS_SPEC
(sym
->etype
) && SPEC_SCLS
(sym
->etype
))
846 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_NOT_ALLOWED
, "storage class");
847 printTypeChainRaw
(sym
->type
, NULL
);
848 SPEC_SCLS
(sym
->etype
) = 0;
850 for
(dsym
=sym
->next
; dsym
; dsym
=dsym
->next
)
852 if
(*dsym
->name
&& strcmp
(sym
->name
, dsym
->name
)==0)
854 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_DUPLICATE_MEMBER
,
855 $1==STRUCT ?
"struct" : "union", sym
->name
);
856 werrorfl
(dsym
->fileDef
, dsym
->lineDef
, E_PREVIOUS_DEF
);
861 /* Create a structdef */
862 $3->fields
= reverseSyms
($6); /* link the fields */
863 $3->size
= compStructSize
($1, $3); /* update size of */
864 promoteAnonStructs
($1, $3);
866 if
($3->redefinition
) // Since C23, multiple definitions for struct / union are allowed, if they are compatible and have the same tags. The current standard draft N3047 allows redeclarations of unions to have a different order of the members. We don't. The rule in N3047 is now considered a mistake by many, and will hopefully be changed to the SDCC behaviour via a national body comment for the final version of the standard.
868 sdef
= findSymWithBlock
(StructTab
, $3->tagsym
, currBlockno
, NestLevel
);
869 bool compatible
= options.std_c23
&& sdef
->tagsym
&& $3->tagsym
&& !strcmp
(sdef
->tagsym
->name
, $3->tagsym
->name
);
870 for
(symbol
*fieldsym1
= sdef
->fields
, *fieldsym2
= $3->fields
; compatible
; fieldsym1
= fieldsym1
->next
, fieldsym2
= fieldsym2
->next
)
872 if
(!fieldsym1
&& !fieldsym2
)
874 if
(!fieldsym1 ||
!fieldsym2
)
876 else if
(strcmp
(fieldsym1
->name
, fieldsym2
->name
))
878 else if
(compareType
(fieldsym1
->type
, fieldsym2
->type
, true
) <= 0)
883 werror
(E_STRUCT_REDEF_INCOMPATIBLE
, $3->tag
);
884 werrorfl
(sdef
->tagsym
->fileDef
, sdef
->tagsym
->lineDef
, E_PREVIOUS_DEF
);
890 /* Create the specifier */
891 $$
= newLink
(SPECIFIER
);
892 SPEC_NOUN
($$
) = V_STRUCT
;
893 SPEC_STRUCT
($$
)= sdef
;
895 | struct_or_union attribute_specifier_sequence_opt stag
899 sdef
= findSymWithBlock
(StructTab
, $3->tagsym
, currBlockno
, NestLevel
);
905 /* new struct def for current scope */
906 addSym
(StructTab
, $3, $3->tag
, $3->level
, currBlockno
, 0);
908 $$
= newLink
(SPECIFIER
);
909 SPEC_NOUN
($$
) = V_STRUCT
;
910 SPEC_STRUCT
($$
) = $3;
919 werror
(E_BAD_TAG
, $3->tag
, $1==STRUCT ?
"struct" : "union");
925 : STRUCT
{ $$
= STRUCT
; ignoreTypedefType
= 1; }
926 | UNION
{ $$
= UNION
; ignoreTypedefType
= 1; }
929 member_declaration_list
931 | member_declaration_list member_declaration
935 /* go to the end of the chain */
936 while
(sym
->next
) sym
= sym
->next
;
944 : attribute_specifier_sequence_opt specifier_qualifier_list member_declarator_list
';'
946 /* add this type to all the symbols */
948 for
( sym
= $3; sym
!= NULL
; sym
= sym
->next
)
950 sym_link
*btype
= copyLinkChain
($2);
952 pointerTypes
(sym
->type
, btype
);
956 sym
->etype
= getSpec
(sym
->type
);
959 addDecl
(sym
, 0, btype
);
960 /* make sure the type is complete and sane */
961 checkTypeSanity
(sym
->etype
, sym
->name
);
963 ignoreTypedefType
= 0;
968 type_specifier_qualifier
969 : type_specifier
{ $$
= $1; }
970 | type_qualifier
{ $$
= $1; }
971 | alignment_specifier
{ $$
= $1; }
974 type_specifier_qualifier_without_struct_or_union
975 : type_specifier_without_struct_or_union
{ $$
= $1; }
976 | struct_or_union
{ fatal
(1, E_ENUM_UNDERLYING_TYPE
); }
977 | type_qualifier
{ $$
= $1; }
978 | alignment_specifier
{ $$
= $1; }
981 member_declarator_list
983 | member_declarator_list
',' member_declarator
994 unsigned int bitsize
;
995 $$
= newSymbol
(genSymName
(NestLevel
), NestLevel
);
996 bitsize
= (unsigned int) ulFromVal
(constExprValue
($2, true
));
998 bitsize
= BITVAR_PAD
;
999 $$
->bitVar
= bitsize
;
1002 | declarator
':' constant_expr
1004 unsigned int bitsize
;
1005 bitsize
= (unsigned int) ulFromVal
(constExprValue
($3, true
));
1009 $$
= newSymbol
(genSymName
(NestLevel
), NestLevel
);
1010 $$
->bitVar
= BITVAR_PAD
;
1011 werror
(W_BITFLD_NAMED
);
1014 $1->bitVar
= bitsize
;
1016 |
{ $$
= newSymbol
("", NestLevel
); }
1020 : ENUM
'{' enumerator_list enum_comma_opt
'}'
1022 $$
= newEnumType
($3, NULL
);
1023 SPEC_SCLS
(getSpec
($$
)) = 0;
1025 | ENUM enum_type_specifier
'{' enumerator_list enum_comma_opt
'}'
1027 $$
= newEnumType
($4, $2);
1028 SPEC_SCLS
(getSpec
($$
)) = 0;
1030 | ENUM identifier
'{' enumerator_list enum_comma_opt
'}'
1035 enumtype
= newEnumType
($4, NULL
);
1036 SPEC_SCLS
(getSpec
(enumtype
)) = 0;
1037 $2->type
= enumtype
;
1039 csym
= findSymWithLevel
(enumTab
, $2);
1040 if
((csym
&& csym
->level
== $2->level
))
1042 if
(!options.std_c23 || compareType
(csym
->type
, $2->type
, true
) <= 0)
1044 werrorfl
($2->fileDef
, $2->lineDef
, E_DUPLICATE_TYPEDEF
, csym
->name
);
1045 werrorfl
(csym
->fileDef
, csym
->lineDef
, E_PREVIOUS_DEF
);
1049 /* add this to the enumerator table */
1051 addSym
(enumTab
, $2, $2->name
, $2->level
, $2->block
, 0);
1052 $$
= copyLinkChain
(enumtype
);
1054 | ENUM identifier enum_type_specifier
'{' enumerator_list enum_comma_opt
'}'
1059 enumtype
= newEnumType
($5, $3);
1060 SPEC_SCLS
(getSpec
(enumtype
)) = 0;
1061 $2->type
= enumtype
;
1063 csym
= findSymWithLevel
(enumTab
, $2);
1064 if
((csym
&& csym
->level
== $2->level
))
1066 if
(!options.std_c23 || compareType
(csym
->type
, $2->type
, true
) <= 0)
1068 werrorfl
($2->fileDef
, $2->lineDef
, E_DUPLICATE_TYPEDEF
, csym
->name
);
1069 werrorfl
(csym
->fileDef
, csym
->lineDef
, E_PREVIOUS_DEF
);
1073 /* add this to the enumerator table */
1075 addSym
(enumTab
, $2, $2->name
, $2->level
, $2->block
, 0);
1076 $$
= copyLinkChain
(enumtype
);
1082 /* check the enumerator table */
1083 if
((csym
= findSymWithLevel
(enumTab
, $2)))
1084 $$
= copyLinkChain
(csym
->type
);
1087 $$
= newLink
(SPECIFIER
);
1088 SPEC_NOUN
($$
) = V_INT
;
1094 * An enum specifier of the form "enum identifier enum-type-specifier"
1095 * may not appear except in a declaration of the form "enum identifier enum-type-specifier ;"
1097 simple_typed_enum_decl
1098 : ENUM identifier enum_type_specifier
';'
1102 /* let newEnumType check the enum-type-specifier and discard the returned type */
1103 newEnumType
(NULL
, $3);
1105 /* check the enumerator table */
1106 if
((csym
= findSymWithLevel
(enumTab
, $2)))
1107 $$
= copyLinkChain
(csym
->type
);
1110 $$
= newLink
(SPECIFIER
);
1111 SPEC_NOUN
($$
) = V_INT
;
1123 if
(!options.std_c99
)
1124 werror
(E_ENUM_COMMA_C99
);
1130 | enumerator_list
',' enumerator
1138 : identifier attribute_specifier_sequence_opt opt_assign_expr
1142 $1->type
= copyLinkChain
($3->type
);
1143 $1->etype
= getSpec
($1->type
);
1144 SPEC_ENUM
($1->etype
) = 1;
1147 // check if the symbol at the same level already exists
1148 if
((sym
= findSymWithLevel
(SymbolTab
, $1)) && sym
->level
== $1->level
)
1150 // C23 allows redefinitions of enumeration constants with the same value as part of a redeclaration of the same enumerated type.
1151 if
(!options.std_c23 || ullFromVal
(valFromType
(sym
->type
)) != ullFromVal
(valFromType
($1->type
)))
1153 werrorfl
($1->fileDef
, $1->lineDef
, E_DUPLICATE_MEMBER
, "enum", $1->name
);
1154 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_PREVIOUS_DEF
);
1159 // do this now, so we can use it for the next enums in the list
1166 : ':' type_specifier_list_without_struct_or_union
1168 if
(!options.std_c23
)
1169 werror
(E_ENUM_TYPE_SPECIFIER_C23
);
1170 $$
= finalizeSpec
($2);
1176 $$
=newLink
(SPECIFIER
);
1180 $$
=newLink
(SPECIFIER
);
1181 SPEC_RESTRICT
($$
) = 1;
1184 $$
=newLink
(SPECIFIER
);
1185 SPEC_VOLATILE
($$
) = 1;
1188 $$
=newLink
(SPECIFIER
);
1189 werror
(E_ATOMIC_UNSUPPORTED
);
1192 $$
=newLink
(SPECIFIER
);
1193 SPEC_ADDRSPACE
($$
) = findSym
(AddrspaceTab
, 0, $1);
1196 $$
= newLink
(SPECIFIER
);
1197 SPEC_SCLS
($$
) = S_XDATA
;
1200 $$
= newLink
(SPECIFIER
);
1201 SPEC_SCLS
($$
) = S_CODE
;
1204 $$
= newLink
(SPECIFIER
);
1205 SPEC_SCLS
($$
) = S_EEPROM
;
1208 $$
= newLink
(SPECIFIER
);
1209 SPEC_SCLS
($$
) = S_DATA
;
1212 $$
= newLink
(SPECIFIER
);
1213 SPEC_SCLS
($$
) = S_IDATA
;
1216 $$
= newLink
(SPECIFIER
);
1217 SPEC_SCLS
($$
) = S_PDATA
;
1223 $$
= newLink
(SPECIFIER
);
1224 SPEC_INLINE
($$
) = 1;
1227 $$
= newLink
(SPECIFIER
);
1228 SPEC_NORETURN
($$
) = 1;
1233 : ALIGNAS
'(' type_name
')'
1235 checkTypeSanity
($3, "(_Alignas)");
1236 $$
= newLink
(SPECIFIER
);
1237 SPEC_ALIGNAS
($$
) = 1;
1239 | ALIGNAS
'(' constant_expr
')'
1241 value
*val
= constExprValue
($3, true
);
1242 $$
= newLink
(SPECIFIER
);
1243 SPEC_ALIGNAS
($$
) = 0;
1245 werror
(E_CONST_EXPECTED
);
1246 else if
(ulFromVal
(val
) == 0 || isPowerOf2
(ulFromVal
(val
)) && ulFromVal
(val
) <= port
->mem.maxextalign
)
1247 SPEC_ALIGNAS
($$
) = ulFromVal
(val
);
1249 werror
(E_ALIGNAS
, ulFromVal
(val
));
1254 : direct_declarator
{ $$
= $1; }
1255 | pointer direct_declarator
1257 addDecl
($2,0,reverseLink
($1));
1263 : identifier attribute_specifier_sequence_opt
1264 |
'(' declarator
')' { $$
= $2; }
1265 | array_declarator attribute_specifier_sequence_opt
1266 | declarator2_function_attributes attribute_specifier_sequence_opt
1271 |
'(' declarator
')' { $$
= $2; }
1276 : direct_declarator
'[' type_qualifier_list_opt
']'
1280 p
= newLink
(DECLARATOR
);
1281 DCL_TYPE
(p
) = ARRAY
;
1286 if
(!options.std_c99
)
1287 werror
(E_QUALIFIED_ARRAY_PARAM_C99
);
1289 DCL_PTR_CONST
(p
) = SPEC_CONST
($3);
1290 DCL_PTR_RESTRICT
(p
) = SPEC_RESTRICT
($3);
1291 DCL_PTR_VOLATILE
(p
) = SPEC_VOLATILE
($3);
1292 DCL_PTR_ADDRSPACE
(p
) = SPEC_ADDRSPACE
($3);
1294 n
= newLink
(SPECIFIER
);
1295 SPEC_NEEDSPAR
(n
) = 1;
1301 | direct_declarator
'[' type_qualifier_list_opt assignment_expr
']'
1305 p
= newLink
(DECLARATOR
);
1306 DCL_TYPE
(p
) = ARRAY
;
1307 DCL_ELEM_AST
(p
) = $4;
1311 if
(!options.std_c99
)
1312 werror
(E_QUALIFIED_ARRAY_PARAM_C99
);
1313 DCL_PTR_CONST
(p
) = SPEC_CONST
($3);
1314 DCL_PTR_RESTRICT
(p
) = SPEC_RESTRICT
($3);
1315 DCL_PTR_VOLATILE
(p
) = SPEC_VOLATILE
($3);
1316 DCL_PTR_ADDRSPACE
(p
) = SPEC_ADDRSPACE
($3);
1318 n
= newLink
(SPECIFIER
);
1319 SPEC_NEEDSPAR
(n
) = 1;
1325 | direct_declarator
'[' STATIC type_qualifier_list_opt assignment_expr
']'
1329 if
(!options.std_c99
)
1330 werror
(E_STATIC_ARRAY_PARAM_C99
);
1332 p
= newLink
(DECLARATOR
);
1333 DCL_TYPE
(p
) = ARRAY
;
1334 DCL_ELEM_AST
(p
) = $5;
1338 if
(!options.std_c99
)
1339 werror
(E_QUALIFIED_ARRAY_PARAM_C99
);
1340 DCL_PTR_CONST
(p
) = SPEC_CONST
($4);
1341 DCL_PTR_RESTRICT
(p
) = SPEC_RESTRICT
($4);
1342 DCL_PTR_VOLATILE
(p
) = SPEC_VOLATILE
($4);
1343 DCL_PTR_ADDRSPACE
(p
) = SPEC_ADDRSPACE
($4);
1346 n
= newLink
(SPECIFIER
);
1347 SPEC_NEEDSPAR
(n
) = 1;
1350 | direct_declarator
'[' type_qualifier_list STATIC assignment_expr
']'
1354 if
(!options.std_c99
)
1356 werror
(E_QUALIFIED_ARRAY_PARAM_C99
);
1357 werror
(E_STATIC_ARRAY_PARAM_C99
);
1360 p
= newLink
(DECLARATOR
);
1361 DCL_TYPE
(p
) = ARRAY
;
1362 DCL_ELEM_AST
(p
) = $5;
1364 DCL_PTR_CONST
(p
) = SPEC_CONST
($3);
1365 DCL_PTR_RESTRICT
(p
) = SPEC_RESTRICT
($3);
1366 DCL_PTR_VOLATILE
(p
) = SPEC_VOLATILE
($3);
1367 DCL_PTR_ADDRSPACE
(p
) = SPEC_ADDRSPACE
($3);
1369 n
= newLink
(SPECIFIER
);
1370 SPEC_NEEDSPAR
(n
) = 1;
1375 declarator2_function_attributes
1376 : function_declarator
{ $$
= $1; }
1377 | function_declarator function_attributes
{
1378 // copy the functionAttributes (not the args and hasVargs !!)
1379 sym_link
*funcType
=$1->type
;
1381 while
(funcType
&& !IS_FUNC
(funcType
))
1382 funcType
= funcType
->next
;
1385 werror
(E_FUNC_ATTR
);
1388 struct value
*args
= FUNC_ARGS
(funcType
);
1389 unsigned hasVargs
= FUNC_HASVARARGS
(funcType
);
1390 bool noprototype
= FUNC_NOPROTOTYPE
(funcType
);
1392 memcpy
(&funcType
->funcAttrs
, &$2->funcAttrs
,
1393 sizeof
($2->funcAttrs
));
1395 FUNC_ARGS
(funcType
)=args
;
1396 FUNC_HASVARARGS
(funcType
)=hasVargs
;
1397 FUNC_NOPROTOTYPE
(funcType
)=noprototype
;
1400 memset
(&$2->funcAttrs
, 0,
1401 sizeof
($2->funcAttrs
));
1409 : declarator2
'(' ')'
1411 addDecl
($1, FUNCTION
, NULL
);
1413 // Up to C17, this was a function declarator without a prototype.
1414 if
(!options.std_c23
)
1416 FUNC_NOPROTOTYPE
($1->type
) = true
;
1417 if
(!options.lessPedantic
)
1418 werror
(W_FUNCDECL_WITH_NO_PROTOTYPE
);
1423 NestLevel
+= LEVEL_UNIT
;
1424 STACK_PUSH
(blockNum
, currBlockno
);
1425 btree_add_child
(currBlockno
, ++blockNo
);
1426 currBlockno
= blockNo
;
1427 seqPointNo
++; /* not a true sequence point, but helps resolve scope */
1429 parameter_type_list
')'
1433 bool is_fptr
= IS_FUNC
($1->type
); // Already a function, must be a function pointer.
1435 addDecl
($1, FUNCTION
, NULL
);
1436 funcType
= $1->type
;
1438 // For a function pointer, the parameter list here is for the returned type.
1440 funcType
= funcType
->next
;
1442 while
(funcType
&& !IS_FUNC
(funcType
))
1443 funcType
= funcType
->next
;
1447 FUNC_HASVARARGS
(funcType
) = IS_VARG
($4);
1448 FUNC_ARGS
(funcType
) = reverseVal
($4);
1450 FUNC_SDCCCALL
(funcType
) = -1;
1452 /* nest level was incremented to take care of the parms */
1453 leaveBlockScope
(currBlockno
);
1454 NestLevel
-= LEVEL_UNIT
;
1455 currBlockno
= STACK_POP
(blockNum
);
1456 seqPointNo
++; /* not a true sequence point, but helps resolve scope */
1458 // if this was a pointer (to a function)
1459 if
(!IS_FUNC
($1->type
))
1460 cleanUpLevel
(SymbolTab
, NestLevel
+ LEVEL_UNIT
);
1466 NestLevel
+= LEVEL_UNIT
;
1467 STACK_PUSH
(blockNum
, currBlockno
);
1468 btree_add_child
(currBlockno
, ++blockNo
);
1469 currBlockno
= blockNo
;
1470 seqPointNo
++; /* not a true sequence point, but helps resolve scope */
1474 if
(options.std_c23
)
1475 werror
(E_OLD_STYLE
,$1->name
);
1479 bool is_fptr
= IS_FUNC
($1->type
); // Already a function, must be a function pointer.
1481 addDecl
($1, FUNCTION
, NULL
);
1482 funcType
= $1->type
;
1484 // For a function pointer, the parameter list here is for the returned type.
1486 funcType
= funcType
->next
;
1488 while
(funcType
&& !IS_FUNC
(funcType
))
1489 funcType
= funcType
->next
;
1493 // TODO: A K&R function does not create a prototype.
1494 // => use FUNC_NOPROTOTYPE, once prototype-less functions are
1495 // fully supported and K&R functions can be treated as such
1496 funcType
->funcAttrs.oldStyle
= 1;
1498 // initially give all parameters in the identifier_list the implicit type int
1499 for
(symbol
*loop
= $4; loop
; loop
= loop
->next
) {
1501 loop
->type
= loop
->etype
= newIntLink
();
1503 newVal
= symbolVal
(loop
);
1504 newVal
->next
= FUNC_ARGS
(funcType
);
1505 FUNC_ARGS
(funcType
) = newVal
;
1508 FUNC_SDCCCALL
(funcType
) = -1;
1510 /* nest level was incremented to take care of the parms */
1511 leaveBlockScope
(currBlockno
);
1512 NestLevel
-= LEVEL_UNIT
;
1513 currBlockno
= STACK_POP
(blockNum
);
1514 seqPointNo
++; /* not a true sequence point, but helps resolve scope */
1516 // if this was a pointer (to a function)
1517 if
(!IS_FUNC
($1->type
))
1518 cleanUpLevel
(SymbolTab
, NestLevel
+ LEVEL_UNIT
);
1525 : unqualified_pointer
{ $$
= $1;}
1526 | unqualified_pointer AT
'(' constant_expr
')' /* Special case to allow __at at the end */
1528 sym_link
*n
= newLink
(SPECIFIER
);
1529 /* add this to the storage class specifier */
1530 SPEC_ABSA
(n
) = 1; /* set the absolute addr flag */
1531 /* now get the abs addr from value */
1532 SPEC_ADDR
(n
) = (unsigned int) ulFromVal
(constExprValue
($4,true
));
1536 | unqualified_pointer type_qualifier_list
1541 DCL_PTR_CONST
($1) = SPEC_CONST
($2);
1542 DCL_PTR_VOLATILE
($1) = SPEC_VOLATILE
($2);
1543 DCL_PTR_RESTRICT
($1) = SPEC_RESTRICT
($2);
1544 DCL_PTR_ADDRSPACE
($1) = SPEC_ADDRSPACE
($2);
1547 werror
(W_PTR_TYPE_INVALID
);
1549 | unqualified_pointer type_qualifier_list AT
'(' constant_expr
')' /* Special case to allow __at at the end */
1553 DCL_PTR_CONST
($1) = SPEC_CONST
($2);
1554 DCL_PTR_VOLATILE
($1) = SPEC_VOLATILE
($2);
1555 DCL_PTR_RESTRICT
($1) = SPEC_RESTRICT
($2);
1556 DCL_PTR_ADDRSPACE
($1) = SPEC_ADDRSPACE
($2);
1559 werror
(W_PTR_TYPE_INVALID
);
1561 sym_link
*n
= newLink
(SPECIFIER
);
1562 /* add this to the storage class specifier */
1563 SPEC_ABSA
(n
) = 1; /* set the absolute addr flag */
1564 /* now get the abs addr from value */
1565 SPEC_ADDR
(n
) = (unsigned int) ulFromVal
(constExprValue
($5,true
));
1569 | unqualified_pointer pointer
1573 DCL_TYPE
($2)=port
->unqualified_pointer
;
1575 | unqualified_pointer type_qualifier_list pointer
1578 if
(IS_SPEC
($2) && DCL_TYPE
($3) == UPOINTER
) {
1579 DCL_PTR_CONST
($1) = SPEC_CONST
($2);
1580 DCL_PTR_VOLATILE
($1) = SPEC_VOLATILE
($2);
1581 DCL_PTR_RESTRICT
($1) = SPEC_RESTRICT
($2);
1582 DCL_PTR_ADDRSPACE
($1) = SPEC_ADDRSPACE
($2);
1583 switch
(SPEC_SCLS
($2)) {
1585 DCL_TYPE
($3) = FPOINTER
;
1588 DCL_TYPE
($3) = IPOINTER
;
1591 DCL_TYPE
($3) = PPOINTER
;
1594 DCL_TYPE
($3) = POINTER
;
1597 DCL_TYPE
($3) = CPOINTER
;
1600 DCL_TYPE
($3) = EEPPOINTER
;
1603 // this could be just "constant"
1604 // werror(W_PTR_TYPE_INVALID);
1609 werror
(W_PTR_TYPE_INVALID
);
1617 $$
= newLink
(DECLARATOR
);
1618 DCL_TYPE
($$
)=UPOINTER
;
1624 | type_qualifier_list type_qualifier
1626 $$
= mergeDeclSpec
($1, $2, "type_qualifier_list type_qualifier skipped");
1630 type_qualifier_list_opt
1635 | type_qualifier_list
1643 | parameter_list
',' ELLIPSIS
{ $1->vArgs
= 1;}
1647 : parameter_declaration
1648 | parameter_list
',' parameter_declaration
1655 parameter_declaration
1656 : declaration_specifiers declarator
1660 if
(IS_SPEC
($1) && !IS_VALID_PARAMETER_STORAGE_CLASS_SPEC
($1))
1662 werror
(E_STORAGE_CLASS_FOR_PARAMETER
, $2->name
);
1664 pointerTypes
($2->type
, $1);
1665 if
(IS_SPEC
($2->etype
))
1666 SPEC_NEEDSPAR
($2->etype
) = 0;
1667 addDecl
($2, 0, $1);
1668 for
(loop
= $2; loop
; loop
->_isparm
= 1, loop
= loop
->next
)
1670 $$
= symbolVal
($2);
1671 ignoreTypedefType
= 0;
1677 $$
->etype
= getSpec
($$
->type
);
1678 ignoreTypedefType
= 0;
1683 : pointer
{ $$
= reverseLink
($1); }
1684 | direct_abstract_declarator
1685 | pointer direct_abstract_declarator
{ $1 = reverseLink
($1); $2->next
= $1; $$
= $2;
1686 if
(IS_PTR
($1) && IS_FUNC
($2))
1687 DCL_TYPE
($1) = CPOINTER
;
1691 direct_abstract_declarator
1692 : '(' abstract_declarator
')' { $$
= $2; }
1693 | array_abstract_declarator
1694 | function_abstract_declarator
1697 direct_abstract_declarator_opt
1699 | direct_abstract_declarator
1702 array_abstract_declarator
1703 : direct_abstract_declarator_opt
'[' ']' {
1704 $$
= newLink
(DECLARATOR
);
1705 DCL_TYPE
($$
) = ARRAY
;
1710 | direct_abstract_declarator_opt
'[' constant_expr
']'
1713 $$
= newLink
(DECLARATOR
);
1714 DCL_TYPE
($$
) = ARRAY
;
1715 DCL_ELEM
($$
) = (int) ulFromVal
(val
= constExprValue
($3, true
));
1721 function_abstract_declarator
1722 : '(' ')' { $$
= NULL
;}
1723 | direct_abstract_declarator
'(' ')' {
1724 // $1 must be a pointer to a function
1725 sym_link
*p
=newLink
(DECLARATOR
);
1726 DCL_TYPE
(p
) = FUNCTION
;
1728 // ((void (code *) ()) 0) ()
1729 $1=newLink
(DECLARATOR
);
1730 DCL_TYPE
($1)=CPOINTER
;
1735 |
'(' parameter_type_list
')' { $$
= NULL
;}
1736 | direct_abstract_declarator
'('
1738 NestLevel
+= LEVEL_UNIT
;
1739 STACK_PUSH
(blockNum
, currBlockno
);
1740 btree_add_child
(currBlockno
, ++blockNo
);
1741 currBlockno
= blockNo
;
1743 parameter_type_list
')'
1745 sym_link
*p
= newLink
(DECLARATOR
), *q
;
1746 DCL_TYPE
(p
) = FUNCTION
;
1748 FUNC_HASVARARGS
(p
) = IS_VARG
($4);
1749 FUNC_ARGS
(p
) = reverseVal
($4);
1751 /* nest level was incremented to take care of the parms */
1752 NestLevel
-= LEVEL_UNIT
;
1753 currBlockno
= STACK_POP
(blockNum
);
1756 /* ((void (code *) (void)) 0) () */
1757 $1 = newLink
(DECLARATOR
);
1758 DCL_TYPE
($1) = CPOINTER
;
1761 for
(q
= $1; q
&& q
->next
; q
= q
->next
);
1767 : assignment_expr
{ $$
= newiList
(INIT_NODE
,$1); }
1770 if
(!options.std_c23
)
1771 werror
(W_EMPTY_INIT_C23
);
1772 // {} behaves mostly like {0}, so we emulate that, and use the isempty flag for the few cases where there is a difference.
1773 $$
= newiList
(INIT_DEEP
, revinit
(newiList
(INIT_NODE
, newAst_VALUE
(constIntVal
("0")))));
1776 |
'{' initializer_list
'}' { $$
= newiList
(INIT_DEEP
,revinit
($2)); }
1777 |
'{' initializer_list
',' '}' { $$
= newiList
(INIT_DEEP
,revinit
($2)); }
1781 : designation_opt initializer
{ $2->designation
= $1; $$
= $2; }
1782 | initializer_list
',' designation_opt initializer
1784 $4->designation
= $3;
1796 : designator_list
'=' { $$
= revDesignation
($1); }
1801 | designator_list designator
{ $2->next
= $1; $$
= $2; }
1805 : '[' constant_expr
']'
1810 tval
= constExprValue
($2, true
);
1811 /* if it is not a constant then Error */
1812 if
(!tval ||
(SPEC_SCLS
(tval
->etype
) != S_LITERAL
))
1814 werror
(E_CONST_EXPECTED
);
1815 elemno
= 0; /* arbitrary fixup */
1819 if
((elemno
= (int) ulFromVal
(tval
)) < 0)
1821 werror
(E_BAD_DESIGNATOR
);
1822 elemno
= 0; /* arbitrary fixup */
1825 $$
= newDesignation
(DESIGNATOR_ARRAY
, &elemno
);
1827 |
'.' identifier
{ $$
= newDesignation
(DESIGNATOR_STRUCT
,$2); }
1830 static_assert_declaration
1831 : STATIC_ASSERT
'(' constant_expr
',' STRING_LITERAL
')' ';'
1833 value
*val
= constExprValue
($3, true
);
1835 werror
(E_CONST_EXPECTED
);
1836 else if
(!ullFromVal
(val
))
1837 werror
(W_STATIC_ASSERTION
, $5);
1839 | STATIC_ASSERT
'(' constant_expr
')' ';'
1841 value
*val
= constExprValue
($3, true
);
1842 if
(!options.std_c23
)
1843 werror
(E_STATIC_ASSERTION_C23
);
1845 werror
(E_CONST_EXPECTED
);
1846 else if
(!ullFromVal
(val
))
1847 werror
(W_STATIC_ASSERTION_2
);
1851 attribute_specifier_sequence
1852 : attribute_specifier_sequence attribute_specifier
1856 for
(a
= $$
; a
->next
; a
= a
->next
);
1859 | attribute_specifier
1865 attribute_specifier_sequence_opt
1870 | attribute_specifier_sequence
1877 : ATTR_START attribute_list
']' ']'
1879 if
(!options.std_c23
)
1880 werror
(E_ATTRIBUTE_C23
);
1890 | attribute_list
',' attribute_opt
1896 for
(a
= $$
; a
->next
; a
= a
->next
);
1905 $$
= newAttribute
($1, 0);
1907 | attribute_token attribute_argument_clause
1909 $$
= newAttribute
($1, 0);
1929 werror
(W_UNKNOWN_ATTRIBUTE
, $1->name
);
1931 | identifier TOK_SEP identifier
1936 dbuf_init
(&dbuf
, 64);
1937 dbuf_printf
(&dbuf
, "%s::%s", $1->name
, $3->name
);
1938 werror
(W_UNKNOWN_ATTRIBUTE
, dbuf_c_str
(&dbuf
));
1939 dbuf_destroy
(&dbuf
);
1943 attribute_argument_clause
1945 |
'(' balanced_token_sequence
')'
1948 balanced_token_sequence
1950 | balanced_token_sequence balanced_token
1959 /* C23 A.2.3 Statements */
1963 | unlabeled_statement
1968 : expression_statement
1969 | attribute_specifier_sequence_opt primary_block
1973 | attribute_specifier_sequence_opt jump_statement
1977 | critical_statement
1982 : compound_statement
1986 | selection_statement
1990 | iteration_statement
2012 $$
= newNode
(BLOCK
, NULL
, NULL
);
2019 $$
= createLabel
($1,NULL
);
2022 | attribute_specifier_sequence_opt CASE constant_range_expr
':'
2024 if
(!options.std_c2y
)
2025 werror
(E_CASE_RANGE_C2Y
);
2027 if
(STACK_EMPTY
(swStk
))
2028 $$
= createCaseRange
(NULL
,$3->left
,$3->right
,NULL
);
2030 $$
= createCaseRange
(STACK_PEEK
(swStk
),$3->left
,$3->right
,NULL
);
2032 | attribute_specifier_sequence_opt CASE constant_expr
':'
2034 if
(STACK_EMPTY
(swStk
))
2035 $$
= createCase
(NULL
,$3,NULL
);
2037 $$
= createCase
(STACK_PEEK
(swStk
),$3,NULL
);
2039 | attribute_specifier_sequence_opt DEFAULT
{ $
<asts
>$
= newNode
(DEFAULT
,NULL
,NULL
); } ':'
2041 if
(STACK_EMPTY
(swStk
))
2042 $$
= createDefault
(NULL
,$
<asts
>3,NULL
);
2044 $$
= createDefault
(STACK_PEEK
(swStk
),$
<asts
>3,NULL
);
2051 NestLevel
+= LEVEL_UNIT
;
2052 STACK_PUSH
(blockNum
, currBlockno
);
2053 btree_add_child
(currBlockno
, ++blockNo
);
2054 currBlockno
= blockNo
;
2055 ignoreTypedefType
= 0;
2062 leaveBlockScope
(currBlockno
);
2063 NestLevel
-= LEVEL_UNIT
;
2064 currBlockno
= STACK_POP
(blockNum
);
2069 : start_block end_block
{ $$
= createBlock
(NULL
, NULL
); }
2070 | start_block block_item_list end_block
2073 cleanUpLevel
(StructTab
, NestLevel
+ LEVEL_UNIT
);
2078 : statements_and_implicit
{ $$
= createBlock
(NULL
, $1); }
2079 | declaration_list
{ $$
= createBlock
($1, NULL
); }
2080 | declaration_list statements_and_implicit
{ $$
= createBlock
($1, $2); }
2083 expression_statement
2084 : expression_opt
';'
2085 | attribute_specifier_sequence expression
';' { $$
= $2; seqPointNo
++;}
2089 : ELSE statement
{ $$
= $2; }
2094 /* This gives us an unavoidable shift / reduce conflict, but yacc does the right thing for C */
2095 : IF
'(' expression
')' { seqPointNo
++;} statement else_statement
2098 $$
= createIf
($3, $6, $7 );
2099 $$
->lineno
= $3->lineno
;
2100 $$
->filename
= $3->filename
;
2103 | SWITCH
'(' expression
')' {
2105 static int swLabel
= 0;
2108 /* create a node for expression */
2109 ex
= newNode
(SWITCH
,$3,NULL
);
2110 STACK_PUSH
(swStk
,ex
); /* save it in the stack */
2111 ex
->values.switchVals.swNum
= swLabel
;
2113 /* now create the label */
2114 SNPRINTF
(lbuff
, sizeof
(lbuff
),
2115 "_swBrk_%d",swLabel
++);
2116 $
<sym
>$
= newSymbol
(lbuff
,NestLevel
);
2117 /* put label in the break stack */
2118 STACK_PUSH
(breakStack
,$
<sym
>$
);
2121 /* get back the switch form the stack */
2122 $$
= STACK_POP
(swStk
);
2123 $$
->right
= newNode
(NULLOP
,$6,createLabel
($
<sym
>5,NULL
));
2124 STACK_POP
(breakStack
);
2129 : while
'(' expression
')' { seqPointNo
++;} secondary_block
2132 $$
= createWhile
( $1, STACK_POP
(continueStack
),
2133 STACK_POP
(breakStack
), $3, $6 );
2134 $$
->lineno
= $1->lineDef
;
2135 $$
->filename
= $1->fileDef
;
2138 | do secondary_block WHILE
'(' expression
')' ';'
2142 $$
= createDo
( $1 , STACK_POP
(continueStack
),
2143 STACK_POP
(breakStack
), $5, $2);
2144 $$
->lineno
= $1->lineDef
;
2145 $$
->filename
= $1->fileDef
;
2148 | for
'(' expression_opt
';' expression_opt
';' expression_opt
')' secondary_block
2152 $$
= newNode
(FOR
,$9,NULL
);
2153 AST_FOR
($$
,trueLabel
) = $1;
2154 AST_FOR
($$
,continueLabel
) = STACK_POP
(continueStack
);
2155 AST_FOR
($$
,falseLabel
) = STACK_POP
(breakStack
);
2156 AST_FOR
($$
,condLabel
) = STACK_POP
(forStack
);
2157 AST_FOR
($$
,initExpr
) = $3;
2158 AST_FOR
($$
,condExpr
) = $5;
2159 AST_FOR
($$
,loopExpr
) = $7;
2161 /* This continue label is not at the correct location, */
2162 /* but we need to create it now for proper binding. The */
2163 /* code that handles the FOR node will move it to the */
2164 /* proper location inside the for loop. */
2165 if
(AST_FOR
($$
,continueLabel
)->isref
)
2166 $$
->right
= createLabel
(AST_FOR
($$
,continueLabel
),NULL
);
2167 $$
= newNode
(NULLOP
,$$
,createLabel
(AST_FOR
($$
,falseLabel
),NULL
));
2170 NestLevel
-= LEVEL_UNIT
;
2171 currBlockno
= STACK_POP
(blockNum
);
2173 | for
'(' declaration expression_opt
';' expression_opt
')'
2175 if
(!options.std_c99
)
2176 werror
(E_FOR_INITAL_DECLARATION_C99
);
2178 if
( $3 && IS_TYPEDEF
($3->etype
))
2179 allocVariables
($3);
2180 ignoreTypedefType
= 0;
2188 $$
= newNode
(FOR
,$9,NULL
);
2189 AST_FOR
($$
,trueLabel
) = $1;
2190 AST_FOR
($$
,continueLabel
) = STACK_POP
(continueStack
);
2191 AST_FOR
($$
,falseLabel
) = STACK_POP
(breakStack
);
2192 AST_FOR
($$
,condLabel
) = STACK_POP
(forStack
);
2193 AST_FOR
($$
,initExpr
) = 0;
2194 AST_FOR
($$
,condExpr
) = $4;
2195 AST_FOR
($$
,loopExpr
) = $6;
2197 /* This continue label is not at the correct location, */
2198 /* but we need to create it now for proper binding. The */
2199 /* code that handles the FOR node will move it to the */
2200 /* proper location inside the for loop. */
2201 if
(AST_FOR
($$
,continueLabel
)->isref
)
2202 $$
->right
= createLabel
(AST_FOR
($$
,continueLabel
),NULL
);
2203 $$
= createBlock
($3, newNode
(NULLOP
,$$
,createLabel
(AST_FOR
($$
,falseLabel
),NULL
)));
2204 cleanUpLevel
(StructTab
, NestLevel
+ LEVEL_UNIT
);
2207 leaveBlockScope
(currBlockno
);
2208 NestLevel
-= LEVEL_UNIT
;
2209 currBlockno
= STACK_POP
(blockNum
);
2214 : GOTO identifier
';' {
2215 if
(inCriticalBlock
) {
2216 werror
(E_INVALID_CRITICAL
);
2220 $$
= newAst_VALUE
(symbolVal
($2));
2221 $$
= newNode
(GOTO
,$$
,NULL
);
2225 /* make sure continue is in context */
2226 if
(STACK_EMPTY
(continueStack
) || STACK_PEEK
(continueStack
) == NULL
) {
2227 werror
(E_BREAK_CONTEXT
);
2231 $$
= newAst_VALUE
(symbolVal
(STACK_PEEK
(continueStack
)));
2232 $$
= newNode
(GOTO
,$$
,NULL
);
2233 /* mark the continue label as referenced */
2234 STACK_PEEK
(continueStack
)->isref
= 1;
2238 if
(STACK_EMPTY
(breakStack
) || STACK_PEEK
(breakStack
) == NULL
) {
2239 werror
(E_BREAK_CONTEXT
);
2242 $$
= newAst_VALUE
(symbolVal
(STACK_PEEK
(breakStack
)));
2243 $$
= newNode
(GOTO
,$$
,NULL
);
2244 STACK_PEEK
(breakStack
)->isref
= 1;
2249 if
(inCriticalBlock
) {
2250 werror
(E_INVALID_CRITICAL
);
2253 $$
= newNode
(RETURN
,NULL
,NULL
);
2256 | RETURN expression
';' {
2258 if
(inCriticalBlock
) {
2259 werror
(E_INVALID_CRITICAL
);
2262 $$
= newNode
(RETURN
,NULL
,$2);
2267 /* C23 A.2.4 External definitions */
2270 : external_declaration
2271 | translation_unit external_declaration
2274 external_declaration
2275 : function_definition
2281 ignoreTypedefType
= 0;
2282 if
($1 && $1->type
&& IS_FUNC
($1->type
))
2284 /* The only legal storage classes for
2285 * a function prototype (declaration)
2286 * are extern and static. extern is the
2287 * default. Thus, if this function isn't
2288 * explicitly marked static, mark it
2291 if
($1->etype
&& IS_SPEC
($1->etype
) && !SPEC_STAT
($1->etype
))
2293 SPEC_EXTR
($1->etype
) = 1;
2297 allocVariables
($1);
2298 cleanUpLevel
(SymbolTab
, 1);
2302 /* These empty braces here are apparently required by some version of GNU bison on MS Windows. See bug #2858. */
2308 { /* function return type not specified, which is allowed in C90 (and means int), but disallowed in C99 and later */
2309 werror
(W_RETURN_TYPE_OMITTED_INT
);
2310 addDecl
($1,0,newIntLink
());
2311 $1 = createFunctionDecl
($1);
2314 if
(FUNC_ISCRITICAL
($1->type
))
2315 inCriticalFunction
= 1;
2316 strncpyz
(function_name
, $1->name
, sizeof
(function_name
) - 3);
2317 memset
(function_name
+ sizeof
(function_name
) - 4, 0x00, 4);
2322 // merge kr_declaration_list from auxiliary node into function declaration
2323 mergeKRDeclListIntoFuncDecl
($1, (symbol
*) $3->left
);
2324 // discard auxiliary node and keep compound_statement as function_body
2327 $$
= createFunction
($1, $3);
2328 if
($1 && FUNC_ISCRITICAL
($1->type
))
2329 inCriticalFunction
= 0;
2331 | declaration_specifiers declarator
2333 sym_link
*p
= copyLinkChain
($1);
2334 pointerTypes
($2->type
,p
);
2336 $2 = createFunctionDecl
($2);
2339 if
(!strcmp
($2->name
, "_sdcc_external_startup")) // The rename (and semantics change happened) in SDCC 4.2.10. Keep this warning for two major releases afterwards.
2340 werror
(W__SDCC_EXTERNAL_STARTUP_DEF
);
2341 if
(FUNC_ISCRITICAL
($2->type
))
2342 inCriticalFunction
= 1;
2343 // warn for loss of calling convention for inlined functions.
2344 if
(FUNC_ISINLINE
($2->type
) &&
2345 ( FUNC_ISZ88DK_CALLEE
($2->type
) || FUNC_ISZ88DK_FASTCALL
($2->type
) ||
2346 FUNC_BANKED
($2->type
) || FUNC_REGBANK
($2->type
) ||
2347 FUNC_ISOVERLAY
($2->type
) || FUNC_ISISR
($2->type
) ))
2348 werror
(W_INLINE_FUNCATTR
, $2->name
);
2349 strncpyz
(function_name
, $2->name
, sizeof
(function_name
) - 3);
2350 memset
(function_name
+ sizeof
(function_name
) - 4, 0x00, 4);
2355 // merge kr_declaration_list from auxiliary node into function declaration
2356 mergeKRDeclListIntoFuncDecl
($2, (symbol
*) $4->left
);
2357 // discard auxiliary node and keep compound_statement as function_body
2360 $$
= createFunction
($2, $4);
2361 if
($2 && FUNC_ISCRITICAL
($2->type
))
2362 inCriticalFunction
= 0;
2367 : compound_statement
2369 // auxiliary node transports kr_declaration_list into function_definition, where the node is discarded
2370 $$
= newNode
(0, NULL
, $1);
2372 | kr_declaration_list compound_statement
2374 // auxiliary node transports kr_declaration_list into function_definition, where the node is discarded
2375 $$
= newNode
(0, (ast
*) $1, $2);
2379 /* SDCC-specific stuff */
2384 werror
(W_EMPTY_TRANSLATION_UNIT
);
2393 : function_attribute
2394 | function_attributes function_attribute
{ $$
= mergeSpec
($1,$2,"function_attribute"); }
2398 : USING
'(' constant_expr
')' {
2399 $$
= newLink
(SPECIFIER
);
2400 FUNC_REGBANK
($$
) = (int) ulFromVal
(constExprValue
($3, true
));
2402 | REENTRANT
{ $$
= newLink
(SPECIFIER
);
2405 | CRITICAL
{ $$
= newLink
(SPECIFIER
);
2406 FUNC_ISCRITICAL
($$
) = 1;
2408 | NAKED
{ $$
= newLink
(SPECIFIER
);
2411 | JAVANATIVE
{ $$
= newLink
(SPECIFIER
);
2412 FUNC_ISJAVANATIVE
($$
)=1;
2414 | OVERLAY
{ $$
= newLink
(SPECIFIER
);
2415 FUNC_ISOVERLAY
($$
)=1;
2417 | NONBANKED
{$$
= newLink
(SPECIFIER
);
2418 FUNC_NONBANKED
($$
) = 1;
2419 if
(FUNC_BANKED
($$
)) {
2420 werror
(W_BANKED_WITH_NONBANKED
);
2423 | SHADOWREGS
{$$
= newLink
(SPECIFIER
);
2424 FUNC_ISSHADOWREGS
($$
) = 1;
2426 | SD_WPARAM
{$$
= newLink
(SPECIFIER
);
2427 FUNC_ISWPARAM
($$
) = 1;
2429 | BANKED
{$$
= newLink
(SPECIFIER
);
2430 FUNC_BANKED
($$
) = 1;
2431 if
(FUNC_NONBANKED
($$
)) {
2432 werror
(W_BANKED_WITH_NONBANKED
);
2437 $$
= newLink
(SPECIFIER
);
2438 FUNC_INTNO
($$
) = $1;
2443 $$
= newLink
(SPECIFIER
);
2444 FUNC_INTNO
($$
) = INTNO_TRAP
;
2447 | SMALLC
{ $$
= newLink
(SPECIFIER
);
2448 FUNC_ISSMALLC
($$
) = 1;
2450 | RAISONANCE
{ $$
= newLink
(SPECIFIER
);
2451 FUNC_ISRAISONANCE
($$
) = 1;
2453 | IAR
{ $$
= newLink
(SPECIFIER
);
2456 | COSMIC
{ $$
= newLink
(SPECIFIER
);
2457 FUNC_ISCOSMIC
($$
) = 1;
2459 | SDCCCALL
'(' constant_expr
')'
2460 { $$
= newLink
(SPECIFIER
);
2461 FUNC_SDCCCALL
($$
) = ulFromVal
(constExprValue
($3, true
));
2463 | Z88DK_FASTCALL
{ $$
= newLink
(SPECIFIER
);
2464 FUNC_ISZ88DK_FASTCALL
($$
) = 1;
2466 | Z88DK_CALLEE
{ $$
= newLink
(SPECIFIER
);
2467 FUNC_ISZ88DK_CALLEE
($$
) = 1;
2469 | Z88DK_PARAMS_OFFSET
'(' constant_expr
')'
2471 value
*offset_v
= constExprValue
($3, true
);
2473 $$
= newLink
(SPECIFIER
);
2475 offset
= ulFromVal
(offset_v
);
2476 $$
->funcAttrs.z88dk_params_offset
= offset
;
2478 | Z88DK_SHORTCALL
'(' constant_expr
',' constant_expr
')'
2480 value
*rst_v
= constExprValue
($3, true
);
2481 value
*value_v
= constExprValue
($5, true
);
2482 int rst
= -1, value
= -1;
2483 $$
= newLink
(SPECIFIER
);
2486 rst
= ulFromVal
(rst_v
);
2488 value
= ulFromVal
(value_v
);
2490 if
( rst
< 0 || rst
> 56 ||
( rst %
8 ) )
2492 werror
(E_SHORTCALL_INVALID_VALUE
, "rst", rst
);
2494 if
( value
< 0 || value
> 0xfff )
2496 werror
(E_SHORTCALL_INVALID_VALUE
, "value", value
);
2498 $$
->funcAttrs.z88dk_shortcall_rst
= rst
;
2499 $$
->funcAttrs.z88dk_shortcall_val
= value
;
2500 FUNC_ISZ88DK_SHORTCALL
($$
) = 1;
2502 | PRESERVES_REGS
'(' identifier_list
')'
2504 const struct symbol
*regsym
;
2505 $$
= newLink
(SPECIFIER
);
2507 for
(regsym
= $3; regsym
; regsym
= regsym
->next
)
2511 if
(!port
->getRegByName ||
((regnum
= port
->getRegByName
(regsym
->name
)) < 0))
2512 werror
(W_UNKNOWN_REG
, regsym
->name
);
2514 $$
->funcAttrs.preserved_regs
[regnum
] = true
;
2519 offsetof_member_designator
2520 : identifier
{ $$
= newAst_VALUE
(symbolVal
($1)); }
2521 | offsetof_member_designator
'.' { ignoreTypedefType
= 1; } identifier
2523 ignoreTypedefType
= 0;
2524 $4 = newSymbol
($4->name
, NestLevel
);
2526 $$
= newNode
('.', $1, newAst_VALUE
(symbolVal
($4)));
2528 | offsetof_member_designator
'[' expression
']'
2530 $$
= newNode
('[', $1, $3);
2537 // essentially do $$ = newAst_VALUE (strVal("\"$function_name\""));
2539 value
* val
= newValue
();
2540 { // BUG: duplicate from strVal
2541 val
->type
= newLink
(DECLARATOR
);
2542 DCL_TYPE
(val
->type
) = ARRAY
;
2543 val
->type
->next
= val
->etype
= newLink
(SPECIFIER
);
2544 SPEC_SCLS
(val
->etype
) = S_LITERAL
;
2545 SPEC_CONST
(val
->etype
) = 1;
2546 SPEC_NOUN
(val
->etype
) = V_CHAR
;
2547 SPEC_USIGN
(val
->etype
) = !options.signed_char
;
2548 val
->etype
->select.s.b_implicit_sign
= true
;
2551 int ll
= 1 + strlen
(function_name
);
2552 char* s
= (char*) Safe_alloc
(ll
*sizeof
(char));
2554 s
= strncpy
(s
, function_name
, ll
);
2558 SPEC_CVAL
(val
->etype
).v_char
= s
;
2559 DCL_ELEM
(val
->type
) = ll
;
2560 $$
= newAst_VALUE
( val
);
2562 | STRING_LITERAL
{ $$
= newAst_VALUE
(strVal
($1)); }
2566 : INTERRUPT
{ $$
= INTNO_UNSPEC
; }
2567 | INTERRUPT
'(' constant_expr
')'
2569 value
*val
= constExprValue
($3, true
);
2570 int intno
= (int) ulFromVal
(val
);
2571 if
(val
&& (intno
>= 0) && (intno
<= INTNO_MAX
))
2575 werror
(E_INT_BAD_INTNO
, intno
);
2583 $$
= newLink
(SPECIFIER
);
2584 SPEC_NOUN
($$
) = V_SBIT
;
2585 SPEC_SCLS
($$
) = S_SBIT
;
2588 ignoreTypedefType
= 1;
2595 $$
= newLink
(SPECIFIER
);
2596 FUNC_REGBANK
($$
) = 0;
2597 SPEC_NOUN
($$
) = V_CHAR
;
2598 SPEC_SCLS
($$
) = S_SFR
;
2600 ignoreTypedefType
= 1;
2603 $$
= newLink
(SPECIFIER
);
2604 FUNC_REGBANK
($$
) = 1;
2605 SPEC_NOUN
($$
) = V_CHAR
;
2606 SPEC_SCLS
($$
) = S_SFR
;
2608 ignoreTypedefType
= 1;
2614 $$
= newLink
(SPECIFIER
);
2615 FUNC_REGBANK
($$
) = 0;
2616 SPEC_NOUN
($$
) = V_INT
;
2617 SPEC_SCLS
($$
) = S_SFR
;
2619 ignoreTypedefType
= 1;
2625 $$
= newLink
(SPECIFIER
);
2626 FUNC_REGBANK
($$
) = 0;
2627 SPEC_NOUN
($$
) = V_INT
;
2628 SPEC_SCLS
($$
) = S_SFR
;
2631 ignoreTypedefType
= 1;
2637 |
{ /* synthesize a name add to structtable */
2638 ignoreTypedefType
= 0;
2639 $$
= newStruct
(genSymName
(NestLevel
));
2640 $$
->level
= NestLevel
;
2641 $$
->block
= currBlockno
;
2643 //addSym (StructTab, $$, $$->tag, $$->level, currBlockno, 0);
2649 { /* add name to structure table */
2650 ignoreTypedefType
= 0;
2651 $$
= newStruct
($1->name
);
2652 $$
->level
= NestLevel
;
2653 $$
->block
= currBlockno
;
2655 //$$ = findSymWithBlock (StructTab, $1, currBlockno);
2658 // $$ = newStruct($1->name);
2659 // $$->level = NestLevel;
2661 // //addSym (StructTab, $$, $$->tag, $$->level, currBlockno, 0);
2671 val
= constExprValue
($2, true
);
2672 if
(!val
) // Not a constant expression
2674 werror
(E_CONST_EXPECTED
);
2675 val
= constIntVal
("0");
2677 else if
(!IS_INT
(val
->type
) && !IS_CHAR
(val
->type
) && !IS_BOOL
(val
->type
))
2679 werror
(E_ENUM_NON_INTEGER
);
2680 SNPRINTF
(lbuff
, sizeof
(lbuff
), "%lld", (long long int) ullFromVal
(val
));
2681 val
= constVal
(lbuff
);
2688 SNPRINTF
(lbuff
, sizeof
(lbuff
), "%lld", (long long int) ullFromVal
(cenum
)+1);
2689 $$
= cenum
= constVal
(lbuff
);
2693 $$
= cenum
= constCharVal
(0);
2698 specifier_qualifier_list
: type_specifier_list_
{ $$
= finalizeSpec
($1); };
2700 type_specifier_list_
2701 : type_specifier_qualifier
2702 //| type_specifier_list_ type_specifier { $$ = mergeSpec ($1,$2, "type_specifier_list"); }
2703 | type_specifier_list_ type_specifier_qualifier
{
2704 /* if the decl $2 is not a specifier */
2705 /* find the spec and replace it */
2706 $$
= mergeDeclSpec
($1, $2, "type_specifier_list type_specifier skipped");
2710 type_specifier_list_without_struct_or_union
2711 : type_specifier_qualifier_without_struct_or_union
2712 | type_specifier_list_without_struct_or_union type_specifier_qualifier_without_struct_or_union
2714 /* if the decl $2 is not a specifier */
2715 /* find the spec and replace it */
2716 $$
= mergeDeclSpec
($1, $2, "type_specifier_list type_specifier skipped");
2722 | identifier_list
',' identifier
2730 : declaration_specifiers
2732 if
(IS_SPEC
($1) && !IS_VALID_PARAMETER_STORAGE_CLASS_SPEC
($1))
2734 werror
(E_STORAGE_CLASS_FOR_PARAMETER
, "type name");
2736 $$
= $1; ignoreTypedefType
= 0;
2738 | declaration_specifiers abstract_declarator
2740 /* go to the end of the list */
2743 if
(IS_SPEC
($1) && !IS_VALID_PARAMETER_STORAGE_CLASS_SPEC
($1))
2745 werror
(E_STORAGE_CLASS_FOR_PARAMETER
, "type name");
2747 pointerTypes
($2,$1);
2748 for
(p
= $2; p
&& p
->next
; p
= p
->next
)
2752 werror
(E_SYNTAX_ERROR
, yytext
);
2759 ignoreTypedefType
= 0;
2765 if
(inCriticalFunction || inCriticalBlock
)
2766 werror
(E_INVALID_CRITICAL
);
2767 inCriticalBlock
= 1;
2768 STACK_PUSH
(continueStack
,NULL
);
2769 STACK_PUSH
(breakStack
,NULL
);
2775 : critical statement
{
2776 STACK_POP
(breakStack
);
2777 STACK_POP
(continueStack
);
2778 $$
= newNode
(CRITICAL
,$2,NULL
);
2779 inCriticalBlock
= 0;
2783 statements_and_implicit
2785 | statement_list implicit_block
2787 $$
= newNode
(NULLOP
, $1, $2);
2788 if
(!options.std_c99
)
2789 werror
(E_DECL_AFTER_STATEMENT_C99
);
2793 declaration_after_statement
2795 NestLevel
+= SUBLEVEL_UNIT
;
2796 STACK_PUSH
(blockNum
, currBlockno
);
2797 btree_add_child
(currBlockno
, ++blockNo
);
2798 currBlockno
= blockNo
;
2799 ignoreTypedefType
= 0;
2801 declaration_list
{ $$
= $2; }
2805 : declaration_after_statement statements_and_implicit
2807 leaveBlockScope
(currBlockno
);
2808 NestLevel
-= SUBLEVEL_UNIT
;
2809 currBlockno
= STACK_POP
(blockNum
);
2810 $$
= createBlock
($1, $2);
2811 cleanUpLevel
(StructTab
, NestLevel
+ SUBLEVEL_UNIT
);
2813 | declaration_after_statement
2815 leaveBlockScope
(currBlockno
);
2816 NestLevel
-= SUBLEVEL_UNIT
;
2817 currBlockno
= STACK_POP
(blockNum
);
2818 $$
= createBlock
($1, NULL
);
2819 cleanUpLevel
(StructTab
, NestLevel
+ SUBLEVEL_UNIT
);
2826 /* if this is typedef declare it immediately */
2827 if
( $1 && IS_TYPEDEF
($1->etype
)) {
2828 allocVariables
($1);
2833 ignoreTypedefType
= 0;/*printf("1 %s %d %d\n", $1->name, IS_ARRAY ($1->type), DCL_ARRAY_VLA ($1->type));
2834 if (IS_ARRAY ($1->type) && DCL_ARRAY_VLA ($1->type))
2835 werror (E_VLA_OBJECT);
2840 | declaration_list declaration
2844 /* if this is a typedef */
2845 if
($2 && IS_TYPEDEF
($2->etype
)) {
2846 allocVariables
($2);
2850 /* get to the end of the previous decl */
2860 ignoreTypedefType
= 0;/*printf("2 %s %d %d\n", $1->name, IS_ARRAY ($1->type), DCL_ARRAY_VLA ($1->type));
2861 if (IS_ARRAY ($2->type) && DCL_ARRAY_VLA ($2->type))
2862 werror (E_VLA_OBJECT);
2868 // The parameter declarations in K&R-style functions need to be handled in a special way to avoid
2869 // ambiguities in the grammer. We do this by not allowing attributes on the parameter declarations.
2870 // Otherwise, in e.g.
2871 // void f(x) [[attribute]] int x; {}
2872 // it would be unclear if the attribute applies to the type of f vs. the declaration of x.
2874 : declaration_specifiers init_declarator_list
';'
2876 /* add the specifier list to the id */
2877 symbol
*sym
, *sym1
;
2879 for
(sym1
= sym
= reverseSyms
($2);sym
!= NULL
;sym
= sym
->next
) {
2880 sym_link
*lnk
= copyLinkChain
($1);
2881 sym_link
*l0
= NULL
, *l1
= NULL
, *l2
= NULL
;
2882 /* check illegal declaration */
2883 for
(l0
= sym
->type
; l0
!= NULL
; l0
= l0
->next
)
2886 /* check if creating instances of structs with flexible arrays */
2887 for
(l1
= lnk
; l1
!= NULL
; l1
= l1
->next
)
2888 if
(IS_STRUCT
(l1
) && SPEC_STRUCT
(l1
)->b_flexArrayMember
)
2890 if
(!options.std_c99
&& l0
== NULL
&& l1
!= NULL
&& SPEC_EXTR
($1) != 1)
2891 werror
(W_FLEXARRAY_INSTRUCT
, sym
->name
);
2892 /* check if creating instances of function type */
2893 for
(l1
= lnk
; l1
!= NULL
; l1
= l1
->next
)
2896 for
(l2
= lnk
; l2
!= NULL
; l2
= l2
->next
)
2899 if
(l0
== NULL
&& l2
== NULL
&& l1
!= NULL
)
2900 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_TYPE_IS_FUNCTION
, sym
->name
);
2901 /* do the pointer stuff */
2902 pointerTypes
(sym
->type
,lnk
);
2903 addDecl
(sym
,0,lnk
);
2914 /* if this is typedef declare it immediately */
2915 if
( $1 && IS_TYPEDEF
($1->etype
)) {
2916 allocVariables
($1);
2918 ignoreTypedefType
= 0;
2922 checkTypeSanity
($1->etype
, $1->name
);
2926 | kr_declaration_list kr_declaration
2930 /* if this is a typedef */
2931 if
($2 && IS_TYPEDEF
($2->etype
)) {
2932 allocVariables
($2);
2934 ignoreTypedefType
= 0;
2938 checkTypeSanity
($2->etype
, $2->name
);
2939 /* get to the end of the previous decl */
2953 : unlabeled_statement
{ $$
= $1; }
2954 | label
{ $$
= $1; }
2955 | statement_list unlabeled_statement
{ $$
= newNode
(NULLOP
,$1,$2);}
2956 | statement_list label
{ $$
= newNode
(NULLOP
,$1,$2);}
2959 while
: WHILE
{ /* create and push the continue , break & body labels */
2960 static int Lblnum
= 0;
2962 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_whilecontinue_%d",Lblnum
);
2963 STACK_PUSH
(continueStack
,newSymbol
(lbuff
,NestLevel
));
2965 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_whilebreak_%d",Lblnum
);
2966 STACK_PUSH
(breakStack
,newSymbol
(lbuff
,NestLevel
));
2968 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_whilebody_%d",Lblnum
++);
2969 $$
= newSymbol
(lbuff
,NestLevel
);
2973 do
: DO
{ /* create and push the continue , break & body Labels */
2974 static int Lblnum
= 0;
2977 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_docontinue_%d",Lblnum
);
2978 STACK_PUSH
(continueStack
,newSymbol
(lbuff
,NestLevel
));
2980 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_dobreak_%d",Lblnum
);
2981 STACK_PUSH
(breakStack
,newSymbol
(lbuff
,NestLevel
));
2983 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_dobody_%d",Lblnum
++);
2984 $$
= newSymbol
(lbuff
,NestLevel
);
2988 for
: FOR
{ /* create & push continue, break & body labels */
2989 static int Lblnum
= 0;
2991 NestLevel
+= LEVEL_UNIT
;
2992 STACK_PUSH
(blockNum
, currBlockno
);
2993 btree_add_child
(currBlockno
, ++blockNo
);
2994 currBlockno
= blockNo
;
2995 ignoreTypedefType
= 0;
2998 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_forcontinue_%d",Lblnum
);
2999 STACK_PUSH
(continueStack
,newSymbol
(lbuff
,NestLevel
));
3001 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_forbreak_%d",Lblnum
);
3002 STACK_PUSH
(breakStack
,newSymbol
(lbuff
,NestLevel
));
3004 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_forbody_%d",Lblnum
);
3005 $$
= newSymbol
(lbuff
,NestLevel
);
3007 SNPRINTF
(lbuff
, sizeof
(lbuff
), "_forcond_%d",Lblnum
++);
3008 STACK_PUSH
(forStack
,newSymbol
(lbuff
,NestLevel
));
3017 : ASM
'(' asm_string_literal
')' ';'
3022 ex
= newNode
(INLINEASM
, NULL
, NULL
);
3023 ex
->values.inlineasm
= strdup
(copyStr
($3, NULL
));
3032 ex
= newNode
(INLINEASM
, NULL
, NULL
);
3033 ex
->values.inlineasm
= strdup
($1);
3040 : ADDRESSMOD identifier identifier
';' {
3042 if
((sym
= findSymWithLevel
(AddrspaceTab
, $3)) && sym
->level
== $3->level
)
3043 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_PREVIOUS_DEF
);
3044 if
(!findSymWithLevel
(SymbolTab
, $2))
3045 werror
(E_ID_UNDEF
, $2->name
);
3046 addSym
(AddrspaceTab
, $3, $3->name
, $3->level
, $3->block
, 0);
3047 sym
= findSymWithLevel
(AddrspaceTab
, $3);
3048 sym
->addressmod
[0] = findSymWithLevel
(SymbolTab
, $2);
3049 sym
->addressmod
[1] = 0;
3051 | ADDRESSMOD identifier SD_CONST identifier
';' {
3054 if
((sym
= findSymWithLevel
(AddrspaceTab
, $4)) && sym
->level
== $4->level
)
3055 werrorfl
(sym
->fileDef
, sym
->lineDef
, E_PREVIOUS_DEF
);
3056 if
(!findSymWithLevel
(SymbolTab
, $2))
3057 werror
(E_ID_UNDEF
, $2->name
);
3058 addSym
(AddrspaceTab
, $4, $4->name
, $4->level
, $4->block
, 0);
3059 sym
= findSymWithLevel
(AddrspaceTab
, $4);
3060 sym
->addressmod
[0] = findSymWithLevel
(SymbolTab
, $2);
3061 sym
->addressmod
[1] = 0;
3062 type
= newLink
(SPECIFIER
);
3063 SPEC_CONST
(type
) = 1;
3064 sym
->type
= sym
->etype
= type
;
3069 : IDENTIFIER
{ $$
= newSymbol
($1, NestLevel
); }