name = ctf_strraw (real_input, tp->ctt_name);
- /* Hide conflicting types, if we were asked to: also hide if a type with this
- name already exists and is not a forward. */
- if (cu_mapped && is_conflicting)
+ /* Hide conflicting types, if this type is conflicting and a type with this
+ name already exists in the target and is not a forward. We don't want to
+ hide them if they are the only type of that name in a per-CU child, as is
+ usually the case, but in cu-mapped links and in the final phase after
+ cu-mapping distinct conflicting types from different CUs can end up in the
+ same cu-mapped target. Hide all but one in this case: it doesn't matter
+ which, all the conflicting types necessarily lost the popularity contest
+ anyway.
+
+ cu_mapped links get absolutely *everything* marked non-root, named or not.
+ cu-mapped links, when we are merging multiple child CUs into one, are the
+ only point at which we can ever put conflicting and nonconflicting
+ instances of the same type into the same dict, and which one comes first is
+ arbitrary. Rather than having to figure out when we insert a type whether
+ another one is coming that might conflict with it without being so marked,
+ just mark everything as non-root: we'll disregard it in the next phase of
+ cu-mapped linking anyway.
+
+ Note that enums also get their enumerands checked, below. */
+
+ if (cu_mapped)
isroot = 0;
- else if (name
- && (maybe_dup = ctf_lookup_by_rawname (target, kind, name)) != 0)
+ else if (is_conflicting && name
+ && ((maybe_dup = ctf_lookup_by_rawname (target, kind, name)) != 0))
{
if (ctf_type_kind (target, maybe_dup) != CTF_K_FORWARD)
isroot = 0;
{
int val;
errtype = _("enum");
+
+ /* Check enumerands for duplication: this is an extension of the isroot
+ check above. */
+
+ if (isroot)
+ {
+ const char *enumerand;
+ while ((enumerand = ctf_enum_next (input, type, &i, &val)) != NULL)
+ {
+ if (is_conflicting && name
+ && ctf_dynhash_lookup (target->ctf_names, enumerand) != NULL)
+ isroot = 0;
+ }
+ if (ctf_errno (input) != ECTF_NEXT_END)
+ goto err_input;
+ }
+
if ((new_type = ctf_add_enum (target, isroot, name)) == CTF_ERR)
goto err_input; /* errno is set for us. */