Allow typedefs to override inherited type names.
This commit is contained in:
parent
bb182cf3ce
commit
a849249a86
12
lexor.lex
12
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
51
parse.y
51
parse.y
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
25
pform.cc
25
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<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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue