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:
Lars-Peter Clausen 2026-08-06 22:37:14 -07:00
parent b883f7713c
commit 4ffeb748f4
4 changed files with 21 additions and 3 deletions

View File

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

View File

@ -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()

View File

@ -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())

View File

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