Accept initialized const static properties
Static property declaration initializers are elaborated as standalone initialization processes instead of through a class constructor. The const-property bookkeeping therefore does not see the initializer and reports an initialized `const static` property as missing initialization. Record whether each parsed property has a declaration initializer and mark an initialized static const property when its signal is created. Also mark the signal as const and its declaration assignment as an initializer. This permits that initial assignment while rejecting later writes. Uninitialized static const properties remain errors. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
b883f7713c
commit
4ffeb748f4
|
|
@ -1132,6 +1132,12 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
|||
// part of the sig, as the l-value.
|
||||
NetNet*psig = class_type->find_static_property(method_name);
|
||||
ivl_assert(*this, psig);
|
||||
if (psig->get_const()) {
|
||||
cerr << get_fileline() << ": error: Assignment to const signal `"
|
||||
<< psig->name() << "` is not allowed." << endl;
|
||||
des->errors++;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lv = new NetAssign_(psig);
|
||||
return lv;
|
||||
|
|
|
|||
|
|
@ -419,6 +419,14 @@ void netclass_t::elaborate_sig(Design*des, PClass*pclass)
|
|||
auto sig = new NetNet(class_scope_, cur->first, NetNet::REG,
|
||||
use_type);
|
||||
sig->set_line(cur->second);
|
||||
sig->set_const(cur->second.qual.test_const());
|
||||
|
||||
if (cur->second.qual.test_const() &&
|
||||
cur->second.has_initializer) {
|
||||
int pidx = property_idx_from_name(cur->first);
|
||||
ivl_assert(cur->second, pidx >= 0);
|
||||
set_prop_initialized(pidx);
|
||||
}
|
||||
}
|
||||
|
||||
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
||||
|
|
|
|||
|
|
@ -87,13 +87,14 @@ void pform_class_property(const struct vlltype&loc,
|
|||
}
|
||||
|
||||
pform_cur_class->type->properties[curp->name.first]
|
||||
= class_type_t::prop_info_t(property_qual,use_type);
|
||||
= class_type_t::prop_info_t(property_qual, use_type,
|
||||
curp->expr != nullptr);
|
||||
FILE_NAME(&pform_cur_class->type->properties[curp->name.first], loc);
|
||||
|
||||
if (PExpr*rval = curp->expr.release()) {
|
||||
PExpr*lval = new PEIdent(curp->name.first, curp->name.second);
|
||||
FILE_NAME(lval, loc);
|
||||
PAssign*tmp = new PAssign(lval, rval);
|
||||
auto tmp = new PAssign(lval, rval, false, true);
|
||||
FILE_NAME(tmp, loc);
|
||||
|
||||
if (property_qual.test_static())
|
||||
|
|
|
|||
|
|
@ -401,11 +401,14 @@ struct class_type_t : public data_type_t {
|
|||
// This is a map of the properties. Map the name to the type.
|
||||
struct prop_info_t : public LineInfo {
|
||||
inline prop_info_t() : qual(property_qualifier_t::make_none()) { }
|
||||
inline prop_info_t(property_qualifier_t q, data_type_t*t) : qual(q), type(t) { }
|
||||
inline prop_info_t(property_qualifier_t q, data_type_t *t,
|
||||
bool init)
|
||||
: qual(q), type(t), has_initializer(init) { }
|
||||
prop_info_t(prop_info_t&&) = default;
|
||||
prop_info_t& operator=(prop_info_t&&) = default;
|
||||
property_qualifier_t qual;
|
||||
std::unique_ptr<data_type_t> type;
|
||||
bool has_initializer = false;
|
||||
};
|
||||
std::map<perm_string, struct prop_info_t> properties;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue