Allow typedefs to override inherited type names.

This commit is contained in:
Stephen Williams 2014-02-21 20:48:34 -08:00
parent bb182cf3ce
commit a849249a86
4 changed files with 70 additions and 20 deletions

View File

@ -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;
}
}

51
parse.y
View File

@ -417,6 +417,11 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
property_qualifier_t property_qualifier;
PPackage*package;
struct {
char*text;
data_type_t*type;
} type_identifier;
struct {
data_type_t*type;
list<PExpr*>*exprs;
@ -431,7 +436,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
};
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
%token <data_type> TYPE_IDENTIFIER
%token <type_identifier> TYPE_IDENTIFIER
%token <package> PACKAGE_IDENTIFIER
%token <discipline> DISCIPLINE_IDENTIFIER
%token <text> PATHPULSE_IDENTIFIER
@ -730,10 +735,11 @@ class_identifier
$$ = tmp;
}
| TYPE_IDENTIFIER
{ class_type_t*tmp = dynamic_cast<class_type_t*>($1);
{ class_type_t*tmp = dynamic_cast<class_type_t*>($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<class_type_t*> ($2);
{ class_type_t*tmp = dynamic_cast<class_type_t*> ($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

View File

@ -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.

View File

@ -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<perm_string,data_type_t*>::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<PExpr*>&parms)