Detect and complain about some constructor chain errors
This.new is not allowed. super.new beyond the first statement is not allowed. And while I'm at it, clean up the use of "@" and "#" in the code as tokens for this and super.
This commit is contained in:
parent
292d174cad
commit
156644d91e
|
|
@ -2601,7 +2601,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
/* Add the implicit this reference when requested. */
|
||||
if (add_this_flag) {
|
||||
assert(use_path.empty());
|
||||
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||
use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN)));
|
||||
}
|
||||
|
||||
// If there is no object to the left of the method name, then
|
||||
|
|
@ -3906,7 +3906,7 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
|||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
|
|
@ -5766,7 +5766,7 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
|||
|
||||
// The return value of the initializer is the "this"
|
||||
// variable, instead of the "new&" scope name.
|
||||
NetNet*res1 = new1_scope->find_signal(perm_string::literal("@"));
|
||||
NetNet*res1 = new1_scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, res1);
|
||||
|
||||
NetESignal*eres = new NetESignal(res1);
|
||||
|
|
@ -5853,7 +5853,7 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
|||
|
||||
// The return value for the constructor is actually the "this"
|
||||
// variable, instead of the "new" scope name.
|
||||
NetNet*res = new_scope->find_signal(perm_string::literal("@"));
|
||||
NetNet*res = new_scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, res);
|
||||
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
|||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
|
|
|
|||
|
|
@ -578,10 +578,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
// source code for the definition may be:
|
||||
// function new(...);
|
||||
// endfunction
|
||||
// In this case, the "@" port is the synthetic "this"
|
||||
// argument and we also use it as a return value at the
|
||||
// same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal("@"));
|
||||
// In this case, the "@" port (THIS_TOKEN) is the synthetic
|
||||
// "this" argument and we also use it as a return value at
|
||||
// the same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, ret_sig);
|
||||
|
||||
if (debug_elaborate)
|
||||
|
|
|
|||
23
elaborate.cc
23
elaborate.cc
|
|
@ -3002,6 +3002,25 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
|
||||
assert(list_[idx]);
|
||||
|
||||
// Detect the error that a super.new() statement is in the
|
||||
// midst of a block. Report the error. Continue on with the
|
||||
// elaboration so that other errors might be found.
|
||||
if (PChainConstructor*supernew = dynamic_cast<PChainConstructor*> (list_[idx])) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PBlock::elaborate: "
|
||||
<< "Found super.new statement, idx=" << idx << ", "
|
||||
<< " at " << supernew->get_fileline() << "."
|
||||
<< endl;
|
||||
}
|
||||
if (idx > 0) {
|
||||
des->errors += 1;
|
||||
cerr << supernew->get_fileline() << ": error: "
|
||||
<< "super.new(...) must be the first statement in a block."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
NetProc*tmp = list_[idx]->elaborate(des, nscope);
|
||||
// If the statement fails to elaborate, then simply
|
||||
// ignore it. Presumably, the elaborate for the
|
||||
|
|
@ -3266,7 +3285,7 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
// Need the "this" variable for the current constructor. We're
|
||||
// going to pass this to the chained constructor.
|
||||
NetNet*var_this = scope->find_signal(perm_string::literal("@"));
|
||||
NetNet*var_this = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
|
||||
// If super.new is an implicit constructor, then there are no
|
||||
// arguments (other than "this" to worry about, so make a
|
||||
|
|
@ -3728,7 +3747,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
|||
/* Add the implicit this reference when requested. */
|
||||
if (add_this_flag) {
|
||||
assert(use_path.empty());
|
||||
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||
use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN)));
|
||||
}
|
||||
|
||||
// There is no signal to search for so this cannot be a method.
|
||||
|
|
|
|||
7
parse.y
7
parse.y
|
|
@ -68,7 +68,7 @@ static LexicalScope::lifetime_t var_lifetime;
|
|||
|
||||
static pform_name_t* pform_create_this(void)
|
||||
{
|
||||
name_component_t name (perm_string::literal("@"));
|
||||
name_component_t name (perm_string::literal(THIS_TOKEN));
|
||||
pform_name_t*res = new pform_name_t;
|
||||
res->push_back(name);
|
||||
return res;
|
||||
|
|
@ -76,7 +76,7 @@ static pform_name_t* pform_create_this(void)
|
|||
|
||||
static pform_name_t* pform_create_super(void)
|
||||
{
|
||||
name_component_t name (perm_string::literal("#"));
|
||||
name_component_t name (perm_string::literal(SUPER_TOKEN));
|
||||
pform_name_t*res = new pform_name_t;
|
||||
res->push_back(name);
|
||||
return res;
|
||||
|
|
@ -6897,6 +6897,9 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
| implicit_class_handle '.' K_new '(' expression_list_with_nuls ')' ';'
|
||||
{ PChainConstructor*tmp = new PChainConstructor(*$5);
|
||||
FILE_NAME(tmp, @3);
|
||||
if (peek_head_name(*$1) == THIS_TOKEN) {
|
||||
yyerror(@1, "error: this.new is invalid syntax. Did you mean super.new?");
|
||||
}
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net)
|
|||
return;
|
||||
|
||||
list<perm_string>*this_name = new list<perm_string>;
|
||||
this_name->push_back(perm_string::literal("@"));
|
||||
this_name->push_back(perm_string::literal(THIS_TOKEN));
|
||||
vector<pform_tf_port_t>*this_port = pform_make_task_ports(loc,
|
||||
NetNet::PINPUT,
|
||||
pform_cur_class->type,
|
||||
|
|
|
|||
|
|
@ -381,6 +381,14 @@ inline perm_string peek_tail_name(const pform_name_t&that)
|
|||
return that.back().name;
|
||||
}
|
||||
|
||||
/*
|
||||
* In pform names, the "super" and "this" keywords are converted to
|
||||
* These tokens so that they don't interfere with the namespace and
|
||||
* are handled specially.
|
||||
*/
|
||||
# define SUPER_TOKEN "#"
|
||||
# define THIS_TOKEN "@"
|
||||
|
||||
extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
|
||||
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
|
||||
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
|
||||
|
|
|
|||
Loading…
Reference in New Issue