X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.y;h=c5944eaf8dd0e8b4fce9aa2c398fc8810dd7228e;hb=67613b6eceb41c8a242c2556a0f59311adb0b388;hp=44e903b60673c0f5920f46e411eb5ccf1f7879d4;hpb=8db693bdaa3becc17799485bea481d5a52119ca5;p=fw%2Fsdcc diff --git a/src/SDCC.y b/src/SDCC.y index 44e903b6..c5944eaf 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -44,6 +44,9 @@ int xstackPtr = 0 ; /* xstack pointer */ int reentrant = 0 ; int blockNo = 0 ; /* sequential block number */ int currBlockno=0 ; +int inCritical= 0 ; +int seqPointNo= 1 ; /* sequence point number */ +int ignoreTypedefType=0; extern int yylex(); int yyparse(void); extern int noLineno ; @@ -57,6 +60,9 @@ STACK_DCL(swStk ,ast *,MAX_NEST_LEVEL) STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3) value *cenum = NULL ; /* current enumeration type chain*/ +bool uselessDecl = TRUE; + +#define YYDEBUG 1 %} %expect 6 @@ -65,12 +71,12 @@ value *cenum = NULL ; /* current enumeration type chain*/ symbol *sym ; /* symbol table pointer */ structdef *sdef; /* structure definition */ char yychar[SDCC_NAME_MAX+1]; - sym_link *lnk ; /* declarator or specifier */ + sym_link *lnk ; /* declarator or specifier */ int yyint; /* integer value returned */ value *val ; /* for integer constant */ initList *ilist; /* initial list */ - char *yyinline; /* inlined assembler code */ - ast *asts; /* expression tree */ + const char *yyinline; /* inlined assembler code */ + ast *asts; /* expression tree */ } %token IDENTIFIER TYPE_NAME @@ -92,17 +98,18 @@ value *cenum = NULL ; /* current enumeration type chain*/ %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE %token RRC RLC %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT +%token DUMMY_READ_VOLATILE ENDCRITICAL SWAP %type Interrupt_storage -%type identifier declarator declarator2 enumerator_list enumerator -%type struct_declarator +%type identifier declarator declarator2 declarator3 enumerator_list enumerator +%type struct_declarator function_declarator function_declarator2 %type struct_declarator_list struct_declaration struct_declaration_list %type declaration init_declarator_list init_declarator %type declaration_list identifier_list parameter_identifier_list -%type declarator2_function_attributes while do for +%type declarator2_function_attributes while do for critical %type pointer type_specifier_list type_specifier type_name %type storage_class_specifier struct_or_union_specifier -%type declaration_specifiers sfr_reg_bit type_specifier2 +%type declaration_specifiers sfr_reg_bit sfr_attributes type_specifier2 %type function_attribute function_attributes enum_specifier %type abstract_declarator abstract_declarator2 unqualified_pointer %type parameter_type_list parameter_list parameter_declaration opt_assign_expr @@ -116,6 +123,7 @@ value *cenum = NULL ; /* current enumeration type chain*/ %type statement_list statement labeled_statement compound_statement %type expression_statement selection_statement iteration_statement %type jump_statement function_body else_statement string_literal +%type critical_statement %type initializer initializer_list %type unary_operator assignment_operator struct_or_union @@ -133,6 +141,7 @@ external_definition blockNo=0; } | declaration { + ignoreTypedefType = 0; if ($1 && $1->type && IS_FUNC($1->type)) { @@ -157,12 +166,12 @@ external_definition ; function_definition - : declarator function_body { /* function type not specified */ + : function_declarator function_body { /* function type not specified */ /* assume it to be 'int' */ addDecl($1,0,newIntLink()); $$ = createFunction($1,$2); } - | declaration_specifiers declarator function_body + | declaration_specifiers function_declarator function_body { pointerTypes($2->type,copyLinkChain($1)); addDecl($2,0,$1); @@ -369,21 +378,21 @@ inclusive_or_expr logical_and_expr : inclusive_or_expr - | logical_and_expr AND_OP inclusive_or_expr - { $$ = newNode(AND_OP,$1,$3);} + | logical_and_expr AND_OP { seqPointNo++;} inclusive_or_expr + { $$ = newNode(AND_OP,$1,$4);} ; logical_or_expr : logical_and_expr - | logical_or_expr OR_OP logical_and_expr - { $$ = newNode(OR_OP,$1,$3); } + | logical_or_expr OR_OP { seqPointNo++;} logical_and_expr + { $$ = newNode(OR_OP,$1,$4); } ; conditional_expr : logical_or_expr - | logical_or_expr '?' logical_or_expr ':' conditional_expr + | logical_or_expr '?' { seqPointNo++;} logical_or_expr ':' conditional_expr { - $$ = newNode(':',$3,$5) ; + $$ = newNode(':',$4,$6) ; $$ = newNode('?',$1,$$) ; } ; @@ -398,34 +407,45 @@ assignment_expr $$ = newNode($2,$1,$3); break; case MUL_ASSIGN: - $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('*',removePreIncDecOps(copyAst($1)),$3)); break; case DIV_ASSIGN: - $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('/',removePreIncDecOps(copyAst($1)),$3)); break; case MOD_ASSIGN: - $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('%',removePreIncDecOps(copyAst($1)),$3)); break; case ADD_ASSIGN: - $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('+',removePreIncDecOps(copyAst($1)),$3)); break; case SUB_ASSIGN: - $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('-',removePreIncDecOps(copyAst($1)),$3)); break; case LEFT_ASSIGN: - $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode(LEFT_OP,removePreIncDecOps(copyAst($1)),$3)); break; case RIGHT_ASSIGN: - $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode(RIGHT_OP,removePreIncDecOps(copyAst($1)),$3)); break; case AND_ASSIGN: - $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('&',removePreIncDecOps(copyAst($1)),$3)); break; case XOR_ASSIGN: - $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3)); + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('^',removePreIncDecOps(copyAst($1)),$3)); break; case OR_ASSIGN: - $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); + /* $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); */ + $$ = newNode('=',removePostIncDecOps(copyAst($1)), + newNode('|',removePreIncDecOps(copyAst($1)),$3)); break; default : $$ = NULL; @@ -450,7 +470,7 @@ assignment_operator expr : assignment_expr - | expr ',' assignment_expr { $$ = newNode(',',$1,$3);} + | expr ',' { seqPointNo++;} assignment_expr { $$ = newNode(',',$1,$4);} ; constant_expr @@ -458,7 +478,13 @@ constant_expr ; declaration - : declaration_specifiers ';' { $$ = NULL ; } + : declaration_specifiers ';' + { + if (uselessDecl) + werror(W_USELESS_DECL); + uselessDecl = TRUE; + $$ = NULL ; + } | declaration_specifiers init_declarator_list ';' { /* add the specifier list to the id */ @@ -471,6 +497,7 @@ declaration addDecl (sym,0,lnk) ; } + uselessDecl = TRUE; $$ = sym1 ; } ; @@ -541,14 +568,24 @@ storage_class_specifier ; Interrupt_storage - : INTERRUPT CONSTANT { $$ = (int) floatFromVal($2) ; } + : INTERRUPT { $$ = INTNO_UNSPEC ; } + | INTERRUPT CONSTANT + { int intno = (int) floatFromVal($2); + if ((intno >= 0) && (intno <= INTNO_MAX)) + $$ = intno; + else + { + werror(E_INT_BAD_INTNO, intno); + $$ = INTNO_UNSPEC; + } + } ; type_specifier : type_specifier2 | type_specifier2 AT constant_expr { - /* add this to the storage class specifier */ + /* add this to the storage class specifier */ SPEC_ABSA($1) = 1; /* set the absolute addr flag */ /* now get the abs addr from value */ SPEC_ADDR($1) = (int) floatFromVal(constExprValue($3,TRUE)) ; @@ -559,30 +596,37 @@ type_specifier2 : CHAR { $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_CHAR ; + ignoreTypedefType = 1; } | SHORT { $$=newLink(SPECIFIER); $$->select.s._short = 1 ; + ignoreTypedefType = 1; } | INT { $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_INT ; + ignoreTypedefType = 1; } | LONG { $$=newLink(SPECIFIER); SPEC_LONG($$) = 1 ; + ignoreTypedefType = 1; } | SIGNED { $$=newLink(SPECIFIER); $$->select.s._signed = 1; + ignoreTypedefType = 1; } | UNSIGNED { $$=newLink(SPECIFIER); SPEC_USIGN($$) = 1 ; + ignoreTypedefType = 1; } | VOID { $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_VOID ; + ignoreTypedefType = 1; } | CONST { $$=newLink(SPECIFIER); @@ -595,6 +639,7 @@ type_specifier2 | FLOAT { $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_FLOAT; + ignoreTypedefType = 1; } | XDATA { $$ = newLink (SPECIFIER); @@ -603,9 +648,6 @@ type_specifier2 | CODE { $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_CODE ; - if (port->mem.code_ro) { - SPEC_CONST($$) = 1; - } } | EEPROM { $$ = newLink (SPECIFIER) ; @@ -629,11 +671,18 @@ type_specifier2 SPEC_SCLS($$) = S_BIT ; SPEC_BLEN($$) = 1; SPEC_BSTR($$) = 0; + ignoreTypedefType = 1; } - | struct_or_union_specifier + | struct_or_union_specifier { + uselessDecl = FALSE; + $$ = $1 ; + ignoreTypedefType = 1; + } | enum_specifier { cenum = NULL ; + uselessDecl = FALSE; + ignoreTypedefType = 1; $$ = $1 ; } | TYPE_NAME @@ -643,6 +692,7 @@ type_specifier2 sym = findSym(TypedefTab,NULL,$1) ; $$ = p = copyLinkChain(sym->type); SPEC_TYPEDEF(getSpec(p)) = 0; + ignoreTypedefType = 1; } | sfr_reg_bit ; @@ -652,25 +702,77 @@ sfr_reg_bit $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_SBIT; SPEC_SCLS($$) = S_SBIT; + SPEC_BLEN($$) = 1; + SPEC_BSTR($$) = 0; + ignoreTypedefType = 1; + } + | sfr_attributes + ; + +sfr_attributes + : SFR { + $$ = newLink(SPECIFIER) ; + FUNC_REGBANK($$) = 0; + SPEC_NOUN($$) = V_CHAR; + SPEC_SCLS($$) = S_SFR ; + SPEC_USIGN($$) = 1 ; + ignoreTypedefType = 1; } - | SFR { + | SFR BANKED { $$ = newLink(SPECIFIER) ; - SPEC_NOUN($$) = V_CHAR; - SPEC_SCLS($$) = S_SFR ; - SPEC_USIGN($$) = 1 ; + FUNC_REGBANK($$) = 1; + SPEC_NOUN($$) = V_CHAR; + SPEC_SCLS($$) = S_SFR ; + SPEC_USIGN($$) = 1 ; + ignoreTypedefType = 1; } ; struct_or_union_specifier - : struct_or_union opt_stag '{' struct_declaration_list '}' + : struct_or_union opt_stag + { + if (!$2->type) + { + $2->type = $1; + } + else + { + if ($2->type != $1) + werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union"); + } + + } + '{' struct_declaration_list '}' { structdef *sdef ; + symbol *sym, *dsym; - /* Create a structdef */ + // check for errors in structure members + for (sym=$5; sym; sym=sym->next) { + if (IS_ABSOLUTE(sym->etype)) { + werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "'at'"); + SPEC_ABSA(sym->etype) = 0; + } + if (IS_SPEC(sym->etype) && SPEC_SCLS(sym->etype)) { + werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "storage class"); + printTypeChainRaw (sym->type,NULL); + SPEC_SCLS(sym->etype) = 0; + } + for (dsym=sym->next; dsym; dsym=dsym->next) { + if (*dsym->name && strcmp(sym->name, dsym->name)==0) { + werrorfl(sym->fileDef, sym->lineDef, E_DUPLICATE_MEMBER, + $1==STRUCT ? "struct" : "union", sym->name); + werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF); + } + } + } + + /* Create a structdef */ sdef = $2 ; - sdef->fields = reverseSyms($4) ; /* link the fields */ + sdef->fields = reverseSyms($5) ; /* link the fields */ sdef->size = compStructSize($1,sdef); /* update size of */ - + promoteAnonStructs ($1, sdef); + /* Create the specifier */ $$ = newLink (SPECIFIER) ; SPEC_NOUN($$) = V_STRUCT; @@ -680,7 +782,17 @@ struct_or_union_specifier { $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_STRUCT; - SPEC_STRUCT($$) = $2 ; + SPEC_STRUCT($$) = $2; + + if (!$2->type) + { + $2->type = $1; + } + else + { + if ($2->type != $1) + werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union"); + } } ; @@ -712,11 +824,12 @@ struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration { - symbol *sym = $2; - /* go to the end of the chain */ - while (sym->next) sym = sym->next; + symbol *sym=$2; + /* go to the end of the chain */ + while (sym->next) sym=sym->next; sym->next = $1 ; + $$ = $2; } ; @@ -727,21 +840,23 @@ struct_declaration /* add this type to all the symbols */ symbol *sym ; for ( sym = $2 ; sym != NULL ; sym = sym->next ) { + sym_link *btype = copyLinkChain($1); /* make the symbol one level up */ sym->level-- ; - pointerTypes(sym->type,copyLinkChain($1)); + pointerTypes(sym->type,btype); if (!sym->type) { - sym->type = copyLinkChain($1); + sym->type = btype; sym->etype = getSpec(sym->type); } else - addDecl (sym,0,copyLinkChain($1)); + addDecl (sym,0,btype); /* make sure the type is complete and sane */ checkTypeSanity(sym->etype, sym->name); } - $$ = $2; + ignoreTypedefType = 0; + $$ = $2; } ; @@ -756,61 +871,97 @@ struct_declarator_list struct_declarator : declarator - | ':' constant_expr { + | ':' constant_expr { + int bitsize; $$ = newSymbol (genSymName(NestLevel),NestLevel) ; - $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE)); + bitsize= (int) floatFromVal(constExprValue($2,TRUE)); + if (bitsize > (port->s.int_size * 8)) { + bitsize = port->s.int_size * 8; + werror(E_BITFLD_SIZE, bitsize); + } + if (!bitsize) + bitsize = BITVAR_PAD; + $$->bitVar = bitsize; } | declarator ':' constant_expr - { - $1->bitVar = (int) floatFromVal(constExprValue($3,TRUE)); + { + int bitsize; + bitsize= (int) floatFromVal(constExprValue($3,TRUE)); + if (bitsize > (port->s.int_size * 8)) { + bitsize = port->s.int_size * 8; + werror(E_BITFLD_SIZE, bitsize); + } + if (!bitsize) { + $$ = newSymbol (genSymName(NestLevel),NestLevel) ; + $$->bitVar = BITVAR_PAD; + werror(W_BITFLD_NAMED); + } + else + $1->bitVar = bitsize; } + | { $$ = newSymbol ("", NestLevel) ; } + ; enum_specifier : ENUM '{' enumerator_list '}' { - //addSymChain ($3); - //allocVariables(reverseSyms($3)) ; - $$ = copyLinkChain(cenum->type); - } - | ENUM identifier '{' enumerator_list '}' { - symbol *csym ; - - $2->type = copyLinkChain(cenum->type); - $2->etype = getSpec($2->type); - /* add this to the enumerator table */ - if (!(csym=findSym(enumTab,$2,$2->name)) && - (csym && csym->level == $2->level)) - werror(E_DUPLICATE_TYPEDEF,csym->name); - - addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); - //addSymChain ($4); - //allocVariables (reverseSyms($4)); - $$ = copyLinkChain(cenum->type); - SPEC_SCLS(getSpec($$)) = 0 ; - } - | ENUM identifier { - symbol *csym ; + $$ = newEnumType ($3); //copyLinkChain(cenum->type); + SPEC_SCLS(getSpec($$)) = 0; + } - /* check the enumerator table */ - if ((csym = findSym(enumTab,$2,$2->name))) - $$ = copyLinkChain(csym->type); - else { - $$ = newLink(SPECIFIER) ; - SPEC_NOUN($$) = V_INT ; - } + | ENUM identifier '{' enumerator_list '}' { + symbol *csym ; + sym_link *enumtype; - SPEC_SCLS(getSpec($$)) = 0 ; - } + csym=findSym(enumTab,$2,$2->name); + if ((csym && csym->level == $2->level)) + { + werrorfl($2->fileDef, $2->lineDef, E_DUPLICATE_TYPEDEF,csym->name); + werrorfl(csym->fileDef, csym->lineDef, E_PREVIOUS_DEF); + } + + enumtype = newEnumType ($4); //copyLinkChain(cenum->type); + SPEC_SCLS(getSpec(enumtype)) = 0; + $2->type = enumtype; + + /* add this to the enumerator table */ + if (!csym) + addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); + $$ = copyLinkChain(enumtype); + } + | ENUM identifier { + symbol *csym ; + + /* check the enumerator table */ + if ((csym = findSym(enumTab,$2,$2->name))) + $$ = copyLinkChain(csym->type); + else { + $$ = newLink(SPECIFIER) ; + SPEC_NOUN($$) = V_INT ; + } + } ; enumerator_list : enumerator | enumerator_list ',' { } - | enumerator_list ',' enumerator { - $3->next = $1 ; - $$ = $3 ; - } + | enumerator_list ',' enumerator + { + symbol *dsym; + + for (dsym=$1; dsym; dsym=dsym->next) + { + if (strcmp($3->name, dsym->name)==0) + { + werrorfl($3->fileDef, $3->lineDef, E_DUPLICATE_MEMBER, "enum", $3->name); + werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF); + } + } + + $3->next = $1 ; + $$ = $3 ; + } ; enumerator @@ -830,8 +981,15 @@ enumerator opt_assign_expr : '=' constant_expr { value *val ; - - val = constExprValue($2,TRUE); + + val = constExprValue($2,TRUE); + if (!IS_INT(val->type) && !IS_CHAR(val->type)) + { + werror(E_ENUM_NON_INTEGER); + SNPRINTF(lbuff, sizeof(lbuff), + "%d",(int) floatFromVal(val)); + val = constVal(lbuff); + } $$ = cenum = val ; } | { @@ -849,6 +1007,20 @@ opt_assign_expr ; declarator + : declarator3 { $$ = $1 ; } + | pointer declarator3 + { + addDecl ($2,0,reverseLink($1)); + $$ = $2 ; + } + ; + +declarator3 + : declarator2_function_attributes { $$ = $1 ; } + | declarator2 { $$ = $1 ; } + ; + +function_declarator : declarator2_function_attributes { $$ = $1; } | pointer declarator2_function_attributes { @@ -856,33 +1028,44 @@ declarator $$ = $2 ; } ; - + declarator2_function_attributes - : declarator2 { $$ = $1 ; } - | declarator2 function_attribute { - // copy the functionAttributes (not the args and hasVargs !!) - sym_link *funcType=$1->etype; - struct value *args=FUNC_ARGS(funcType); - unsigned hasVargs=FUNC_HASVARARGS(funcType); - - memcpy (&funcType->funcAttrs, &$2->funcAttrs, - sizeof($2->funcAttrs)); - - FUNC_ARGS(funcType)=args; - FUNC_HASVARARGS(funcType)=hasVargs; - - // just to be sure - memset (&$2->funcAttrs, 0, - sizeof($2->funcAttrs)); - - addDecl ($1,0,$2); + : function_declarator2 { $$ = $1 ; } + | function_declarator2 function_attribute { + // copy the functionAttributes (not the args and hasVargs !!) + struct value *args; + unsigned hasVargs; + sym_link *funcType=$1->type; + + while (funcType && !IS_FUNC(funcType)) + funcType = funcType->next; + + if (!funcType) + werror (E_FUNC_ATTR); + else + { + args=FUNC_ARGS(funcType); + hasVargs=FUNC_HASVARARGS(funcType); + + memcpy (&funcType->funcAttrs, &$2->funcAttrs, + sizeof($2->funcAttrs)); + + FUNC_ARGS(funcType)=args; + FUNC_HASVARARGS(funcType)=hasVargs; + + // just to be sure + memset (&$2->funcAttrs, 0, + sizeof($2->funcAttrs)); + + addDecl ($1,0,$2); + } } ; declarator2 : identifier | '(' declarator ')' { $$ = $2; } - | declarator2 '[' ']' + | declarator3 '[' ']' { sym_link *p; @@ -891,64 +1074,77 @@ declarator2 DCL_ELEM(p) = 0 ; addDecl($1,0,p); } - | declarator2 '[' constant_expr ']' + | declarator3 '[' constant_expr ']' { sym_link *p ; value *tval; - p = (tval = constExprValue($3,TRUE))->etype; + tval = constExprValue($3,TRUE); /* if it is not a constant then Error */ - if ( SPEC_SCLS(p) != S_LITERAL) + p = newLink (DECLARATOR); + DCL_TYPE(p) = ARRAY ; + if ( !tval || (SPEC_SCLS(tval->etype) != S_LITERAL)) { werror(E_CONST_EXPECTED) ; + /* Assume a single item array to limit the cascade */ + /* of additional errors. */ + DCL_ELEM(p) = 1; + } else { - p = newLink (DECLARATOR); - DCL_TYPE(p) = ARRAY ; DCL_ELEM(p) = (int) floatFromVal(tval) ; - addDecl($1,0,p); } + addDecl($1,0,p); } - | declarator2 '(' ')' { addDecl ($1,FUNCTION,NULL) ; } - | declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')' + ; + +function_declarator2 + : declarator2 '(' ')' { addDecl ($1,FUNCTION,NULL) ; } + | declarator2 '(' { NestLevel++ ; currBlockno++; } + parameter_type_list ')' { + sym_link *funcType; addDecl ($1,FUNCTION,NULL) ; + + funcType = $1->type; + while (funcType && !IS_FUNC(funcType)) + funcType = funcType->next; - FUNC_HASVARARGS($1->type) = IS_VARG($4); - FUNC_ARGS($1->type) = reverseVal($4); + assert (funcType); + + FUNC_HASVARARGS(funcType) = IS_VARG($4); + FUNC_ARGS(funcType) = reverseVal($4); /* nest level was incremented to take care of the parms */ NestLevel-- ; currBlockno--; // if this was a pointer (to a function) - if (IS_PTR($1->type)) { - // move the args and hasVargs to the function - FUNC_ARGS($1->etype)=FUNC_ARGS($1->type); - FUNC_HASVARARGS($1->etype)=FUNC_HASVARARGS($1->type); - memset (&$1->type->funcAttrs, 0, - sizeof($1->type->funcAttrs)); - // remove the symbol args (if any) + if (!IS_FUNC($1->type)) cleanUpLevel(SymbolTab,NestLevel+1); - } $$ = $1; } | declarator2 '(' parameter_identifier_list ')' { werror(E_OLD_STYLE,$1->name) ; - /* assume it returns an int */ $1->type = $1->etype = newIntLink(); $$ = $1 ; } ; - + pointer : unqualified_pointer { $$ = $1 ;} | unqualified_pointer type_specifier_list { - $$ = $1 ; - DCL_TSPEC($1) = $2; + $$ = $1 ; + if (IS_SPEC($2)) { + DCL_TSPEC($1) = $2; + DCL_PTR_CONST($1) = SPEC_CONST($2); + DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2); + } + else + werror (W_PTR_TYPE_INVALID); } | unqualified_pointer pointer { @@ -1039,11 +1235,11 @@ parameter_type_list ; parameter_list - : parameter_declaration + : parameter_declaration | parameter_list ',' parameter_declaration { $3->next = $1 ; - $$ = $3 ; + $$ = $3 ; } ; @@ -1056,16 +1252,18 @@ parameter_declaration for (loop=$2;loop;loop->_isparm=1,loop=loop->next); addSymChain ($2); $$ = symbolVal($2); + ignoreTypedefType = 0; } | type_name { $$ = newValue() ; $$->type = $1; $$->etype = getSpec($$->type); + ignoreTypedefType = 0; } ; type_name - : type_specifier_list { $$ = $1 ;} + : type_specifier_list { $$ = $1; ignoreTypedefType = 0;} | type_specifier_list abstract_declarator { /* go to the end of the list */ @@ -1078,13 +1276,17 @@ type_name p->next = $1 ; } $$ = $2 ; + ignoreTypedefType = 0; } ; abstract_declarator : pointer { $$ = reverseLink($1); } | abstract_declarator2 - | pointer abstract_declarator2 { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;} + | pointer abstract_declarator2 { $1 = reverseLink($1); $1->next = $2 ; $$ = $1; + if (IS_PTR($1) && IS_FUNC($2)) + DCL_TYPE($1) = CPOINTER; + } ; abstract_declarator2 @@ -1128,22 +1330,21 @@ abstract_declarator2 } $1->next=p; } - | abstract_declarator2 '(' parameter_type_list ')' { - if (!IS_VOID($3->etype)) { - // this is nonsense, so let's just burp something - werror(E_TOO_FEW_PARMS); - } else { - // $1 must be a pointer to a function + | abstract_declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')' { sym_link *p=newLink(DECLARATOR); DCL_TYPE(p) = FUNCTION; - if (!$1) { - // ((void (code *) (void)) 0) () - $1=newLink(DECLARATOR); - DCL_TYPE($1)=CPOINTER; - $$ = $1; - } - $1->next=p; - } + + FUNC_HASVARARGS(p) = IS_VARG($4); + FUNC_ARGS(p) = reverseVal($4); + + /* nest level was incremented to take care of the parms */ + NestLevel-- ; + currBlockno--; + p->next = $1; + $$ = p; + + // remove the symbol args (if any) + cleanUpLevel(SymbolTab,NestLevel+1); } ; @@ -1165,21 +1366,60 @@ statement | selection_statement | iteration_statement | jump_statement + | critical_statement | INLINEASM ';' { - ast *ex = newNode(INLINEASM,NULL,NULL); + ast *ex; + seqPointNo++; + ex = newNode(INLINEASM,NULL,NULL); ex->values.inlineasm = strdup($1); + seqPointNo++; $$ = ex; } ; +critical + : CRITICAL { + inCritical++; + STACK_PUSH(continueStack,NULL); + STACK_PUSH(breakStack,NULL); + $$ = NULL; + } + ; + +critical_statement + : critical statement { + STACK_POP(breakStack); + STACK_POP(continueStack); + inCritical--; + $$ = newNode(CRITICAL,$2,NULL); + } + ; + labeled_statement // : identifier ':' statement { $$ = createLabel($1,$3); } : identifier ':' { $$ = createLabel($1,NULL); } - | CASE constant_expr ':' statement { $$ = createCase(STACK_PEEK(swStk),$2,$4); } - | DEFAULT ':' statement { $$ = createDefault(STACK_PEEK(swStk),$3); } + | CASE constant_expr ':' statement + { + if (STACK_EMPTY(swStk)) + $$ = createCase(NULL,$2,$4); + else + $$ = createCase(STACK_PEEK(swStk),$2,$4); + } + | DEFAULT { $$ = newNode(DEFAULT,NULL,NULL); } ':' statement + { + if (STACK_EMPTY(swStk)) + $$ = createDefault(NULL,$2,$4); + else + $$ = createDefault(STACK_PEEK(swStk),$2,$4); + } ; -start_block : '{' { STACK_PUSH(blockNum,currBlockno); currBlockno = ++blockNo ; } +start_block : '{' + { + STACK_PUSH(blockNum,currBlockno); + currBlockno = ++blockNo ; + ignoreTypedefType = 0; + } ; end_block : '}' { currBlockno = STACK_POP(blockNum); } @@ -1208,6 +1448,7 @@ declaration_list } else $$ = $1 ; + ignoreTypedefType = 0; } | declaration_list declaration @@ -1230,6 +1471,7 @@ declaration_list else $$ = $2 ; } + ignoreTypedefType = 0; } ; @@ -1240,7 +1482,7 @@ statement_list expression_statement : ';' { $$ = NULL;} - | expr ';' + | expr ';' { $$ = $1; seqPointNo++;} ; else_statement @@ -1250,11 +1492,17 @@ else_statement selection_statement - : IF '(' expr ')' statement else_statement { noLineno++ ; $$ = createIf ($3, $5, $6 ); noLineno--;} + : IF '(' expr ')' { seqPointNo++;} statement else_statement + { + noLineno++ ; + $$ = createIf ($3, $6, $7 ); + noLineno--; + } | SWITCH '(' expr ')' { ast *ex ; static int swLabel = 0 ; + seqPointNo++; /* create a node for expression */ ex = newNode(SWITCH,$3,NULL); STACK_PUSH(swStk,ex); /* save it in the stack */ @@ -1323,16 +1571,17 @@ for : FOR { /* create & push continue, break & body labels */ ; iteration_statement - : while '(' expr ')' statement + : while '(' expr ')' { seqPointNo++;} statement { noLineno++ ; $$ = createWhile ( $1, STACK_POP(continueStack), - STACK_POP(breakStack), $3, $5 ); + STACK_POP(breakStack), $3, $6 ); $$->lineno = $1->lineDef ; noLineno-- ; } | do statement WHILE '(' expr ')' ';' { + seqPointNo++; noLineno++ ; $$ = createDo ( $1 , STACK_POP(continueStack), STACK_POP(breakStack), $5, $2); @@ -1367,8 +1616,8 @@ iteration_statement ; expr_opt - : { $$ = NULL ; } - | expr + : { $$ = NULL ; seqPointNo++; } + | expr { $$ = $1 ; seqPointNo++; } ; jump_statement @@ -1379,7 +1628,7 @@ jump_statement } | CONTINUE ';' { /* make sure continue is in context */ - if (STACK_PEEK(continueStack) == NULL) { + if (STACK_EMPTY(continueStack) || STACK_PEEK(continueStack) == NULL) { werror(E_BREAK_CONTEXT); $$ = NULL; } @@ -1391,7 +1640,7 @@ jump_statement } } | BREAK ';' { - if (STACK_PEEK(breakStack) == NULL) { + if (STACK_EMPTY(breakStack) || STACK_PEEK(breakStack) == NULL) { werror(E_BREAK_CONTEXT); $$ = NULL; } else { @@ -1400,8 +1649,24 @@ jump_statement STACK_PEEK(breakStack)->isref = 1; } } - | RETURN ';' { $$ = newNode(RETURN,NULL,NULL) ; } - | RETURN expr ';' { $$ = newNode(RETURN,NULL,$2) ; } + | RETURN ';' { + seqPointNo++; + if (inCritical) { + werror(E_INVALID_CRITICAL); + $$ = NULL; + } else { + $$ = newNode(RETURN,NULL,NULL); + } + } + | RETURN expr ';' { + seqPointNo++; + if (inCritical) { + werror(E_INVALID_CRITICAL); + $$ = NULL; + } else { + $$ = newNode(RETURN,NULL,$2); + } + } ; identifier