+2021-01-27  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf-string.c (ctf_str_add): Treat adding a NULL as adding "".
+       (ctf_str_add_ref): Likewise.
+       (ctf_str_add_external): Likewise.
+       * ctf-types.c (ctf_type_name_raw): Always return "" for offset 0.
+       * ctf-dedup.c (ctf_dedup_multiple_input_dicts): Don't armour
+       against NULL name.
+       (ctf_dedup_maybe_synthesize_forward): Likewise.
+
 2021-01-27  Nick Alcock  <nick.alcock@oracle.com>
 
        * ctf-create.c (ctf_serialize): Fix shadowing.
 
   name = ctf_type_name_raw (input_fp, input_id);
 
   if ((fwdkind == CTF_K_STRUCT || fwdkind == CTF_K_UNION)
-      && name && name[0] != '\0')
+      && name[0] != '\0')
     {
       const void *origin;
 
   ctf_dedup_t *td = &target->ctf_dedup;
   int kind;
   int fwdkind;
-  const char *name;
+  const char *name = ctf_type_name_raw (input, id);
   const char *decorated;
   void *v;
   ctf_id_t emitted_forward;
 
   if (!ctf_dynset_exists (od->cd_conflicting_types, hval, NULL)
       || target->ctf_flags & LCTF_CHILD
-      || !ctf_type_name_raw (input, id)
+      || name[0] == '\0'
       || (((kind = ctf_type_kind_unsliced (input, id)) != CTF_K_STRUCT
           && kind != CTF_K_UNION && kind != CTF_K_FORWARD)))
     return 0;
 
   fwdkind = ctf_type_kind_forwarded (input, id);
-  name = ctf_type_name_raw (input, id);
 
   ctf_dprintf ("Using synthetic forward for conflicted struct/union with "
               "hval %s\n", hval);
 
 ctf_str_add (ctf_dict_t *fp, const char *str)
 {
   ctf_str_atom_t *atom;
+
   if (!str)
-    return 0;
+    str = "";
 
   atom = ctf_str_add_ref_internal (fp, str, FALSE, TRUE, 0);
   if (!atom)
 ctf_str_add_ref (ctf_dict_t *fp, const char *str, uint32_t *ref)
 {
   ctf_str_atom_t *atom;
+
   if (!str)
-    return 0;
+    str = "";
 
   atom = ctf_str_add_ref_internal (fp, str, TRUE, TRUE, ref);
   if (!atom)
 ctf_str_add_external (ctf_dict_t *fp, const char *str, uint32_t offset)
 {
   ctf_str_atom_t *atom;
+
   if (!str)
-    return 0;
+    str = "";
 
   atom = ctf_str_add_ref_internal (fp, str, FALSE, FALSE, 0);
   if (!atom)
 
 }
 
 /* Lookup the given type ID and return its raw, unadorned, undecorated name.
-   The name will live as long as its ctf_dict_t does.  */
+   The name will live as long as its ctf_dict_t does.
+
+   The only decoration is that a NULL return always means an error: nameless
+   types return a null string.  */
 
 const char *
 ctf_type_name_raw (ctf_dict_t *fp, ctf_id_t type)
   if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
     return NULL;               /* errno is set for us.  */
 
+  if (tp->ctt_name == 0)
+    return "";
+
   return ctf_strraw (fp, tp->ctt_name);
 }