* @brief The first type must be TK_STRUCTURE. * The second type must not be TK_ALIAS. */
| 333 | * The second type must not be TK_ALIAS. |
| 334 | */ |
| 335 | bool TypeAssignability::assignable_struct(const MinimalTypeObject& ta, |
| 336 | const MinimalTypeObject& tb) const |
| 337 | { |
| 338 | if (TK_STRUCTURE != tb.kind) { |
| 339 | return false; |
| 340 | } |
| 341 | |
| 342 | // Extensibility kind must match |
| 343 | const TypeFlag extensibility_mask = IS_FINAL | IS_APPENDABLE | IS_MUTABLE; |
| 344 | const ACE_CDR::UShort a_exten = ta.struct_type.struct_flags & extensibility_mask; |
| 345 | if (a_exten != (tb.struct_type.struct_flags & extensibility_mask)) { |
| 346 | return false; |
| 347 | } |
| 348 | |
| 349 | // If T1 is appendable, then members with the same member_index have the |
| 350 | // same member ID, the same setting for the 'optional' attribute and the |
| 351 | // T1 member type is strongly assignable from the T2 member type. |
| 352 | // If T1 is final, then they meet the same condition as for T1 being |
| 353 | // appendable and in addition T1 and T2 have the same set of member IDs. |
| 354 | if (IS_FINAL == a_exten && |
| 355 | ta.struct_type.member_seq.length() != tb.struct_type.member_seq.length()) { |
| 356 | return false; |
| 357 | } |
| 358 | if (IS_APPENDABLE == a_exten || IS_FINAL == a_exten) { |
| 359 | const unsigned num_members = (std::min)(ta.struct_type.member_seq.length(), |
| 360 | tb.struct_type.member_seq.length()); |
| 361 | for (unsigned i = 0; i < num_members; ++i) { |
| 362 | if (ta.struct_type.member_seq[i].common.member_id != |
| 363 | tb.struct_type.member_seq[i].common.member_id || |
| 364 | (ta.struct_type.member_seq[i].common.member_flags & IS_OPTIONAL) != |
| 365 | (tb.struct_type.member_seq[i].common.member_flags & IS_OPTIONAL) || |
| 366 | !strongly_assignable(ta.struct_type.member_seq[i].common.member_type_id, |
| 367 | tb.struct_type.member_seq[i].common.member_type_id)) { |
| 368 | return false; |
| 369 | } |
| 370 | } |
| 371 | } |
| 372 | |
| 373 | // Any members in T1 and T2 that have the same name also have |
| 374 | // the same ID, and vice versa |
| 375 | MatchedSet matched_members; |
| 376 | for (unsigned i = 0; i < ta.struct_type.member_seq.length(); ++i) { |
| 377 | const MemberId id_a = ta.struct_type.member_seq[i].common.member_id; |
| 378 | const ACE_CDR::ULong name_a = to_uint(ta.struct_type.member_seq[i].detail.name_hash); |
| 379 | for (unsigned j = 0; j < tb.struct_type.member_seq.length(); ++j) { |
| 380 | const MemberId id_b = tb.struct_type.member_seq[j].common.member_id; |
| 381 | const ACE_CDR::ULong name_b = to_uint(tb.struct_type.member_seq[j].detail.name_hash); |
| 382 | |
| 383 | if (!type_consistency_.ignore_member_names) { |
| 384 | if ((name_a == name_b && id_a != id_b) || (id_a == id_b && name_a != name_b)) { |
| 385 | return false; |
| 386 | } else if (name_a == name_b && id_a == id_b) { |
| 387 | matched_members.push_back(std::make_pair(&ta.struct_type.member_seq[i], |
| 388 | &tb.struct_type.member_seq[j])); |
| 389 | break; |
| 390 | } |
| 391 | } else if (id_a == id_b) { |
| 392 | matched_members.push_back(std::make_pair(&ta.struct_type.member_seq[i], |
nothing calls this directly
no test coverage detected