diff --git a/elab_type.cc b/elab_type.cc index ae9b5f39a..62f28bbd7 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -180,6 +180,7 @@ netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const netstruct_t*res = new netstruct_t; res->packed(packed_flag); + res->set_signed(signed_flag); if (union_flag) res->union_flag(true); diff --git a/netstruct.h b/netstruct.h index d5f9eb0a2..767819e4b 100644 --- a/netstruct.h +++ b/netstruct.h @@ -51,6 +51,10 @@ class netstruct_t : public LineInfo, public ivl_type_s { void packed(bool flag); bool packed(void) const; + // When the struct is accessed as a primary it can be signed or unsigned + void set_signed(bool flag) { signed_ = flag; } + bool get_signed(void) const { return signed_; } + // Append a new member to the struct/union. This must be done // after the union_flag and packed settings are set. This // function does error checking, and the "des" argument is @@ -74,6 +78,7 @@ class netstruct_t : public LineInfo, public ivl_type_s { private: bool union_; bool packed_; + bool signed_; std::vectormembers_; }; diff --git a/parse.y b/parse.y index 7491fcbeb..8680fe3e6 100644 --- a/parse.y +++ b/parse.y @@ -457,6 +457,11 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector number pos_neg_number %type signing unsigned_signed_opt signed_unsigned_opt %type import_export -%type K_genvar_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt +%type K_genvar_opt K_reg_opt K_static_opt K_virtual_opt %type udp_reg_opt edge_operator %type drive_strength drive_strength_opt dr_strength0 dr_strength1 %type udp_input_sym udp_output_sym @@ -642,6 +647,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector struct_union_member %type struct_union_member_list %type struct_data_type +%type packed_signing %type class_declaration_extends_opt @@ -2988,38 +2994,54 @@ enum_name } ; -struct_data_type - : K_struct K_packed_opt '{' struct_union_member_list '}' +/* `signed` and `unsigned` are only valid if preceded by `packed` */ +packed_signing /* IEEE 1800-2012 A.2.2.1 */ + : K_packed unsigned_signed_opt + { $$.packed_flag = true; + $$.signed_flag = $2; + } + | + { $$.packed_flag = false; + $$.signed_flag = false; + } + ; + +struct_data_type /* IEEE 1800-2012 A.2.2.1 */ + : K_struct packed_signing '{' struct_union_member_list '}' { struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); - tmp->packed_flag = $2; + tmp->packed_flag = $2.packed_flag; + tmp->signed_flag = $2.signed_flag; tmp->union_flag = false; tmp->members .reset($4); $$ = tmp; } - | K_union K_packed_opt '{' struct_union_member_list '}' + | K_union packed_signing '{' struct_union_member_list '}' { struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); - tmp->packed_flag = $2; + tmp->packed_flag = $2.packed_flag; + tmp->signed_flag = $2.signed_flag; tmp->union_flag = true; tmp->members .reset($4); $$ = tmp; } - | K_struct K_packed_opt '{' error '}' + | K_struct packed_signing '{' error '}' { yyerror(@3, "error: Errors in struct member list."); yyerrok; struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); - tmp->packed_flag = $2; + tmp->packed_flag = $2.packed_flag; + tmp->signed_flag = $2.signed_flag; tmp->union_flag = false; $$ = tmp; } - | K_union K_packed_opt '{' error '}' + | K_union packed_signing '{' error '}' { yyerror(@3, "error: Errors in union member list."); yyerrok; struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); - tmp->packed_flag = $2; + tmp->packed_flag = $2.packed_flag; + tmp->signed_flag = $2.signed_flag; tmp->union_flag = true; $$ = tmp; } @@ -7453,7 +7475,6 @@ unique_priority collect those rules here. */ K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ; -K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ; K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ; K_static_opt : K_static { $$ = true; } | { $$ = false; } ; K_virtual_opt : K_virtual { $$ = true; } | { $$ = false; } ; diff --git a/pform_types.h b/pform_types.h index 4e67a72db..2b15810fb 100644 --- a/pform_types.h +++ b/pform_types.h @@ -207,6 +207,7 @@ struct struct_type_t : public data_type_t { bool packed_flag; bool union_flag; + bool signed_flag; std::unique_ptr< std::list > members; };