From a849249a86f8d0800c699b53701e1c2e81159602 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 21 Feb 2014 20:48:34 -0800 Subject: [PATCH] Allow typedefs to override inherited type names. --- lexor.lex | 12 ++++++------ parse.y | 51 +++++++++++++++++++++++++++++++++++++-------------- parse_misc.h | 2 ++ pform.cc | 25 +++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/lexor.lex b/lexor.lex index 68435444c..dbcb6a251 100644 --- a/lexor.lex +++ b/lexor.lex @@ -325,8 +325,8 @@ TU [munpf] if (in_package_scope) { if (rc == IDENTIFIER) { if (data_type_t*type = pform_test_type_identifier(in_package_scope, yylval.text)) { - delete[]yylval.text; - yylval.data_type = type; + yylval.type_identifier.text = yylval.text; + yylval.type_identifier.type = type; rc = TYPE_IDENTIFIER; } } @@ -361,8 +361,8 @@ TU [munpf] return this as a TYPE_IDENTIFIER instead. */ if (rc == IDENTIFIER && gn_system_verilog()) { if (data_type_t*type = pform_test_type_identifier(yylval.text)) { - delete[]yylval.text; - yylval.data_type = type; + yylval.type_identifier.text = yylval.text; + yylval.type_identifier.type = type; rc = TYPE_IDENTIFIER; } } @@ -382,8 +382,8 @@ TU [munpf] } if (gn_system_verilog()) { if (data_type_t*type = pform_test_type_identifier(yylval.text)) { - delete[]yylval.text; - yylval.data_type = type; + yylval.type_identifier.text = yylval.text; + yylval.type_identifier.type = type; return TYPE_IDENTIFIER; } } diff --git a/parse.y b/parse.y index d9b8f0166..667c792fc 100644 --- a/parse.y +++ b/parse.y @@ -417,6 +417,11 @@ static void current_function_set_statement(const YYLTYPE&loc, vector property_qualifier_t property_qualifier; PPackage*package; + struct { + char*text; + data_type_t*type; + } type_identifier; + struct { data_type_t*type; list*exprs; @@ -431,7 +436,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector }; %token IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL -%token TYPE_IDENTIFIER +%token TYPE_IDENTIFIER %token PACKAGE_IDENTIFIER %token DISCIPLINE_IDENTIFIER %token PATHPULSE_IDENTIFIER @@ -730,10 +735,11 @@ class_identifier $$ = tmp; } | TYPE_IDENTIFIER - { class_type_t*tmp = dynamic_cast($1); + { class_type_t*tmp = dynamic_cast($1.type); if (tmp == 0) { - yyerror(@1, "Type name is not a predeclared class name."); + yyerror(@1, "Type name \"%s\"is not a predeclared class name.", $1.text); } + delete[]$1.text; $$ = tmp; } ; @@ -743,13 +749,14 @@ class_identifier does indeed match a name. */ class_declaration_endlabel_opt : ':' TYPE_IDENTIFIER - { class_type_t*tmp = dynamic_cast ($2); + { class_type_t*tmp = dynamic_cast ($2.type); if (tmp == 0) { - yyerror(@2, "error: class declaration endlabel is not a class name\n"); + yyerror(@2, "error: class declaration endlabel \"%s\" is not a class name\n", $2.text); $$ = 0; } else { $$ = strdupnew(tmp->name.str()); } + delete[]$2.text; } | ':' IDENTIFIER { $$ = $2; } @@ -767,12 +774,14 @@ class_declaration_endlabel_opt class_declaration_extends_opt /* IEEE1800-2005: A.1.2 */ : K_extends TYPE_IDENTIFIER - { $$.type = $2; + { $$.type = $2.type; $$.exprs= 0; + delete[]$2.text; } | K_extends TYPE_IDENTIFIER '(' expression_list_with_nuls ')' - { $$.type = $2; + { $$.type = $2.type; $$.exprs = $4; + delete[]$2.text; } | { $$.type = 0; $$.exprs = 0; } @@ -1013,14 +1022,16 @@ data_type /* IEEE1800-2005: A.2.2.1 */ $$ = tmp; } | TYPE_IDENTIFIER dimensions_opt - { if ($2) $$ = new parray_type_t($1, $2); - else $$ = $1; + { if ($2) $$ = new parray_type_t($1.type, $2); + else $$ = $1.type; + delete[]$1.text; } | PACKAGE_IDENTIFIER K_SCOPE_RES { lex_in_package_scope($1); } TYPE_IDENTIFIER { lex_in_package_scope(0); - $$ = $4; + $$ = $4.type; + delete[]$4.text; } | K_string { string_type_t*tmp = new string_type_t; @@ -2143,6 +2154,20 @@ type_declaration delete[]$3; } + /* If the IDENTIFIER already is a typedef, it is possible for this + code to override the definition, but only if the typedef is + inherited from a different scope. */ + | K_typedef data_type TYPE_IDENTIFIER ';' + { perm_string name = lex_strings.make($3.text); + if (pform_test_type_identifier_local(name)) { + yyerror(@3, "error: Typedef identifier \"%s\" is already a type name.", $3.text); + + } else { + pform_set_typedef(name, $2); + } + delete[]$3.text; + } + /* These are forward declarations... */ | K_typedef K_class IDENTIFIER ';' @@ -2170,9 +2195,6 @@ type_declaration delete[]$2; } - | K_typedef data_type TYPE_IDENTIFIER ';' - { yyerror(@3, "error: Typedef identifier is already a type name."); } - | K_typedef error ';' { yyerror(@2, "error: Syntax error in typedef clause."); yyerrok; @@ -3108,9 +3130,10 @@ expr_primary /* There are a few special cases (notably $bits argument) where the expression may be a type name. Let the elaborator sort this out. */ | TYPE_IDENTIFIER - { PETypename*tmp = new PETypename($1); + { PETypename*tmp = new PETypename($1.type); FILE_NAME(tmp,@1); $$ = tmp; + delete[]$1.text; } /* The hierarchy_identifier rule matches simple identifiers as well as diff --git a/parse_misc.h b/parse_misc.h index 7887818c0..46a937042 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -96,6 +96,8 @@ extern void lex_in_package_scope(PPackage*pkg); extern data_type_t* pform_test_type_identifier(const char*txt); extern data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt); +extern bool pform_test_type_identifier_local(perm_string txt); + /* * Test if this identifier is a package name. The pform needs to help * the lexor here because the parser detects packages and saves them. diff --git a/pform.cc b/pform.cc index f2d360521..8d62ddf40 100644 --- a/pform.cc +++ b/pform.cc @@ -584,6 +584,31 @@ data_type_t* pform_test_type_identifier(const char*txt) return 0; } +/* + * The parser uses this function to test if the name is a typedef in + * the current scope. We use this to know if we can override the + * definition because it shadows a containing scope. + */ +bool pform_test_type_identifier_local(perm_string name) +{ + if (lexical_scope == 0) { + if (test_type_identifier_in_root(name)) + return true; + else + return false; + } + + LexicalScope*cur_scope = lexical_scope; + + map::iterator cur; + + cur = cur_scope->typedefs.find(name); + if (cur != cur_scope->typedefs.end()) + return true; + + return false; +} + PECallFunction* pform_make_call_function(const struct vlltype&loc, const pform_name_t&name, const list&parms)