diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index 00c44d975..f8f65b108 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -457,6 +457,19 @@ void DFHack::flagarrayToString(std::vector *pvec, const void *p, static const struct_field_info *find_union_tag_candidate(const struct_field_info *fields, const struct_field_info *union_field) { + if (union_field->extra && union_field->extra->union_tag_field) + { + auto defined_field_name = union_field->extra->union_tag_field; + for (auto field = fields; field->mode != struct_field_info::END; field++) + { + if (!strcmp(field->name, defined_field_name)) + { + return field; + } + } + return nullptr; + } + std::string name(union_field->name); if (name.length() >= 4 && name.substr(name.length() - 4) == "data") { diff --git a/library/xml b/library/xml index 6ad3e99e1..ab463895a 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 6ad3e99e1ed26f1b0af210f941ace905a70b50e7 +Subproject commit ab463895a32b47f3b4165b669e0e35994589caa7 diff --git a/plugins/devel/check-structures-sanity/check-structures-sanity.h b/plugins/devel/check-structures-sanity/check-structures-sanity.h index 45d882fef..da790edf0 100644 --- a/plugins/devel/check-structures-sanity/check-structures-sanity.h +++ b/plugins/devel/check-structures-sanity/check-structures-sanity.h @@ -117,6 +117,7 @@ public: const std::string *validate_stl_string_pointer(const void *const*); #endif static const char *const *get_enum_item_key(enum_identity *identity, int64_t value); + static const char *const *get_enum_item_attr_or_key(enum_identity *identity, int64_t value, const char *attr_name); private: color_ostream & fail(int, const QueueItem &, const CheckedStructure &); @@ -134,8 +135,8 @@ private: void dispatch_class(const QueueItem &, const CheckedStructure &); void dispatch_buffer(const QueueItem &, const CheckedStructure &); void dispatch_stl_ptr_vector(const QueueItem &, const CheckedStructure &); - void dispatch_tagged_union(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &); - void dispatch_tagged_union_vector(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &); + void dispatch_tagged_union(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &, const char *); + void dispatch_tagged_union_vector(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &, const char *); void dispatch_untagged_union(const QueueItem &, const CheckedStructure &); void check_unknown_pointer(const QueueItem &); void check_stl_vector(const QueueItem &, type_identity *, type_identity *); diff --git a/plugins/devel/check-structures-sanity/dispatch.cpp b/plugins/devel/check-structures-sanity/dispatch.cpp index 1fd85ce52..fcc6b0b8e 100644 --- a/plugins/devel/check-structures-sanity/dispatch.cpp +++ b/plugins/devel/check-structures-sanity/dispatch.cpp @@ -545,13 +545,14 @@ void Checker::dispatch_field(const QueueItem & item, const CheckedStructure & cs auto tag_ptr = PTR_ADD(item.ptr, tag_field->offset); QueueItem tag_item(item, tag_field->name, tag_ptr); CheckedStructure tag_cs(tag_field); + auto attr_name = field->extra ? field->extra->union_tag_attr : nullptr; if (tag_cs.identity->isContainer()) { - dispatch_tagged_union_vector(field_item, tag_item, field_cs, tag_cs); + dispatch_tagged_union_vector(field_item, tag_item, field_cs, tag_cs, attr_name); } else { - dispatch_tagged_union(field_item, tag_item, field_cs, tag_cs); + dispatch_tagged_union(field_item, tag_item, field_cs, tag_cs, attr_name); } return; } @@ -602,7 +603,7 @@ void Checker::dispatch_stl_ptr_vector(const QueueItem & item, const CheckedStruc auto ptr_type = wrap_in_pointer(identity->getItemType()); check_stl_vector(item, ptr_type, identity->getIndexEnumType()); } -void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs) +void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs, const char *attr_name) { if (tag_cs.identity->type() != IDTYPE_ENUM || cs.identity->type() != IDTYPE_UNION) { @@ -664,7 +665,7 @@ void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & ta } } - auto tag_name = get_enum_item_key(tag_identity, tag_value); + auto tag_name = get_enum_item_attr_or_key(tag_identity, tag_value, attr_name); if (!tag_name) { FAIL("tagged union tag (accessed as " << tag_item.path << ") value (" << tag_value << ") not defined in enum " << tag_cs.identity->getFullName()); @@ -701,7 +702,7 @@ void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & ta FAIL("tagged union missing " << *tag_name << " field to match tag (accessed as " << tag_item.path << ") value (" << tag_value << ")"); } -void Checker::dispatch_tagged_union_vector(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs) +void Checker::dispatch_tagged_union_vector(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs, const char *attr_name) { auto union_container_identity = static_cast(cs.identity); CheckedStructure union_item_cs(union_container_identity->getItemType()); @@ -735,7 +736,7 @@ void Checker::dispatch_tagged_union_vector(const QueueItem & item, const QueueIt for (size_t i = 0; i < vec_union.second.count && i < vec_tag.second.count; i++) { - dispatch_tagged_union(QueueItem(item, i, vec_union.first), QueueItem(tag_item, i, vec_tag.first), union_item_cs, tag_item_cs); + dispatch_tagged_union(QueueItem(item, i, vec_union.first), QueueItem(tag_item, i, vec_tag.first), union_item_cs, tag_item_cs, attr_name); vec_union.first = PTR_ADD(vec_union.first, union_item_cs.identity->byte_size()); vec_tag.first = PTR_ADD(vec_tag.first, tag_item_cs.identity->byte_size()); } diff --git a/plugins/devel/check-structures-sanity/validate.cpp b/plugins/devel/check-structures-sanity/validate.cpp index 04ef8422c..68b3269ae 100644 --- a/plugins/devel/check-structures-sanity/validate.cpp +++ b/plugins/devel/check-structures-sanity/validate.cpp @@ -389,6 +389,11 @@ const std::string *Checker::validate_stl_string_pointer(const void *const* base) #endif const char *const *Checker::get_enum_item_key(enum_identity *identity, int64_t value) +{ + return get_enum_item_attr_or_key(identity, value, nullptr); +} + +const char *const *Checker::get_enum_item_attr_or_key(enum_identity *identity, int64_t value, const char *attr_name) { size_t index; if (auto cplx = identity->getComplex()) @@ -409,5 +414,26 @@ const char *const *Checker::get_enum_item_key(enum_identity *identity, int64_t v index = value - identity->getFirstItem(); } + if (attr_name) + { + auto attrs = identity->getAttrs(); + auto attr_type = identity->getAttrType(); + if (!attrs || !attr_type) + { + return nullptr; + } + + attrs = PTR_ADD(attrs, attr_type->byte_size() * index); + for (auto field = attr_type->getFields(); field->mode != struct_field_info::END; field++) + { + if (!strcmp(field->name, attr_name)) + { + return reinterpret_cast(PTR_ADD(attrs, field->offset)); + } + } + + return nullptr; + } + return &identity->getKeys()[index]; }