2019-05-24  Nathan Sidwell  <nathan@acm.org>

	gcc/
	* tree.h (IDENTIFIER_ANON_P): New.
	(anon_aggrname_format, anon_aggname_p): Don't declare.
	(make_anon_name): Declare.
	* lto-streamer-out.c (DFS::DFS_write_tree_body): Use IDENTIFIER_ANON_P.
	(hash_tree): Likewise.
	* tree-streamer-out.c (write_ts_decl_minimal_tree): Likewise.
	* tree.c (anon_aggrname_p, anon_aggrname_format): Delete.
	(anon_cnt, make_anon_name): New.

 	gcc/cp/
	* cp-tree.h (make_anon_name): Drop declaration.
	(TYPE_UNNAMED_P): Use IDENTIFIER_ANON_P.
	* cp-lang.c (cxx_dwarf_name): Likewise.
	* class.c (find_flexarrays): Likewise.
	* decl.c (name_unnamed_type, xref_tag_1): Likewise.
	* error.c (dump_aggr_type): Likewise.
	* pt.c (push_template_decl_real): Likewise.
	* name-lookup.c (consider_binding_level): Likewise.
	(anon_cnt, make_anon_name): Delete.

	gcc/d/
	* types.cc (fixup_anonymous_offset): Use IDENTIFIER_ANON_P.
	(layout_aggregate_members): Use make_anon_name.

Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 271599)
+++ gcc/cp/class.c	(working copy)
@@ -6586,5 +6586,5 @@ find_flexarrays (tree t, flexmems_t *fme
 	  && DECL_IMPLICIT_TYPEDEF_P (fld)
 	  && CLASS_TYPE_P (TREE_TYPE (fld))
-	  && anon_aggrname_p (DECL_NAME (fld)))
+	  && IDENTIFIER_ANON_P (DECL_NAME (fld)))
 	{
 	  /* Check the nested unnamed type referenced via a typedef
Index: gcc/cp/cp-lang.c
===================================================================
--- gcc/cp/cp-lang.c	(revision 271599)
+++ gcc/cp/cp-lang.c	(working copy)
@@ -111,5 +111,5 @@ cxx_dwarf_name (tree t, int verbosity)
 
   if (DECL_NAME (t)
-      && (anon_aggrname_p (DECL_NAME (t)) || LAMBDA_TYPE_P (t)))
+      && (IDENTIFIER_ANON_P (DECL_NAME (t)) || LAMBDA_TYPE_P (t)))
     return NULL;
   if (verbosity >= 2)
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 271599)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -1938,5 +1938,5 @@ enum languages { lang_c, lang_cplusplus
 /* Nonzero if NODE has no name for linkage purposes.  */
 #define TYPE_UNNAMED_P(NODE) \
-  (OVERLOAD_TYPE_P (NODE) && anon_aggrname_p (TYPE_LINKAGE_IDENTIFIER (NODE)))
+  (OVERLOAD_TYPE_P (NODE) && IDENTIFIER_ANON_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
 
 /* The _DECL for this _TYPE.  */
@@ -6351,5 +6351,4 @@ extern tree strip_fnptr_conv			(tree);
 /* in name-lookup.c */
 extern void maybe_push_cleanup_level		(tree);
-extern tree make_anon_name			(void);
 extern tree maybe_push_decl			(tree);
 extern tree current_decl_namespace		(void);
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 271599)
+++ gcc/cp/decl.c	(working copy)
@@ -10234,13 +10234,10 @@ name_unnamed_type (tree type, tree decl)
   /* Replace the anonymous name with the real name everywhere.  */
   for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
-    {
-      if (anon_aggrname_p (TYPE_IDENTIFIER (t)))
-	/* We do not rename the debug info representing the
-	   unnamed tagged type because the standard says in
-	   [dcl.typedef] that the naming applies only for
-	   linkage purposes.  */
-	/*debug_hooks->set_name (t, decl);*/
-	TYPE_NAME (t) = decl;
-    }
+    if (IDENTIFIER_ANON_P (TYPE_IDENTIFIER (t)))
+      /* We do not rename the debug info representing the unnamed
+	 tagged type because the standard says in [dcl.typedef] that
+	 the naming applies only for linkage purposes.  */
+      /*debug_hooks->set_name (t, decl);*/
+      TYPE_NAME (t) = decl;
 
   if (TYPE_LANG_SPECIFIC (type))
@@ -14062,5 +14059,5 @@ xref_tag_1 (enum tag_types tag_code, tre
      make type node and push name.  Name lookup is not required.  */
   tree t = NULL_TREE;
-  if (scope != ts_lambda && !anon_aggrname_p (name))
+  if (scope != ts_lambda && !IDENTIFIER_ANON_P (name))
     t = lookup_and_check_tag  (tag_code, name, scope, template_header_p);
   
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 271599)
+++ gcc/cp/error.c	(working copy)
@@ -739,5 +739,5 @@ dump_aggr_type (cxx_pretty_printer *pp,
     }
 
-  if (name == 0 || anon_aggrname_p (name))
+  if (!name || IDENTIFIER_ANON_P (name))
     {
       if (flags & TFF_CLASS_KEY_OR_ENUM)
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 271599)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -3798,23 +3798,7 @@ constructor_name_p (tree name, tree type
 }
 
-/* Counter used to create anonymous type names.  */
-
-static GTY(()) int anon_cnt;
-
-/* Return an IDENTIFIER which can be used as a name for
-   unnamed structs and unions.  */
-
-tree
-make_anon_name (void)
-{
-  char buf[32];
-
-  sprintf (buf, anon_aggrname_format (), anon_cnt++);
-  return get_identifier (buf);
-}
-
-/* This code is practically identical to that for creating
-   anonymous names, but is just used for lambdas instead.  This isn't really
-   necessary, but it's convenient to avoid treating lambdas like other
+/* This code is practically identical to that for creating anonymous
+   names, but is just used for lambdas instead.  This isn't really
+   necessary, but it's convenient to avoid mistaking lambdas for other
    unnamed types.  */
 
@@ -5983,5 +5967,5 @@ consider_binding_level (tree name, best_
       /* Don't suggest names that are for anonymous aggregate types, as
 	 they are an implementation detail generated by the compiler.  */
-      if (anon_aggrname_p (suggestion))
+      if (IDENTIFIER_ANON_P (suggestion))
 	continue;
 
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 271599)
+++ gcc/cp/pt.c	(working copy)
@@ -5502,5 +5502,5 @@ push_template_decl_real (tree decl, bool
 	member_template_p = true;
       if (TREE_CODE (decl) == TYPE_DECL
-	  && anon_aggrname_p (DECL_NAME (decl)))
+	  && IDENTIFIER_ANON_P (DECL_NAME (decl)))
 	{
 	  error ("template class without a name");
Index: gcc/d/types.cc
===================================================================
--- gcc/d/types.cc	(revision 271599)
+++ gcc/d/types.cc	(working copy)
@@ -240,5 +240,5 @@ fixup_anonymous_offset (tree fields, tre
 	 Set the anonymous decl offset to its first member.  */
       tree ftype = TREE_TYPE (fields);
-      if (TYPE_NAME (ftype) && anon_aggrname_p (TYPE_IDENTIFIER (ftype)))
+      if (TYPE_NAME (ftype) && IDENTIFIER_ANON_P (TYPE_IDENTIFIER (ftype)))
 	{
 	  tree vfields = TYPE_FIELDS (ftype);
@@ -325,10 +325,5 @@ layout_aggregate_members (Dsymbols *memb
       if (ad != NULL)
 	{
-	  /* Use a counter to create anonymous type names.  */
-	  static int anon_cnt = 0;
-	  char buf[32];
-	  sprintf (buf, anon_aggrname_format (), anon_cnt++);
-
-	  tree ident = get_identifier (buf);
+	  tree ident = make_anon_name ();
 	  tree type = make_node (ad->isunion ? UNION_TYPE : RECORD_TYPE);
 	  ANON_AGGR_TYPE_P (type) = 1;
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c	(revision 271599)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -783,5 +783,5 @@ DFS::DFS_write_tree_body (struct output_
       if (DECL_NAME (expr)
 	  && TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
-	  && anon_aggrname_p (DECL_NAME (expr)))
+	  && IDENTIFIER_ANON_P (DECL_NAME (expr)))
 	;
       else
@@ -1212,5 +1212,5 @@ hash_tree (struct streamer_tree_cache_d
       if (DECL_NAME (t)
 	  && TREE_CODE (DECL_NAME (t)) == IDENTIFIER_NODE
-	  && anon_aggrname_p (DECL_NAME (t)))
+	  && IDENTIFIER_ANON_P (DECL_NAME (t)))
 	;
       else
Index: gcc/tree-streamer-out.c
===================================================================
--- gcc/tree-streamer-out.c	(revision 271599)
+++ gcc/tree-streamer-out.c	(working copy)
@@ -580,5 +580,5 @@ write_ts_decl_minimal_tree_pointers (str
   if (DECL_NAME (expr)
       && TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
-      && anon_aggrname_p (DECL_NAME (expr)))
+      && IDENTIFIER_ANON_P (DECL_NAME (expr)))
     stream_write_tree (ob, NULL_TREE, ref_p);
   else
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 271599)
+++ gcc/tree.c	(working copy)
@@ -9746,38 +9746,30 @@ clean_symbol_name (char *p)
 }
 
-/* For anonymous aggregate types, we need some sort of name to
-   hold on to.  In practice, this should not appear, but it should
-   not be harmful if it does.  */
-bool 
-anon_aggrname_p(const_tree id_node)
-{
-#ifndef NO_DOT_IN_LABEL
- return (IDENTIFIER_POINTER (id_node)[0] == '.'
-	 && IDENTIFIER_POINTER (id_node)[1] == '_');
-#else /* NO_DOT_IN_LABEL */
-#ifndef NO_DOLLAR_IN_LABEL
-  return (IDENTIFIER_POINTER (id_node)[0] == '$' \
-	  && IDENTIFIER_POINTER (id_node)[1] == '_');
-#else /* NO_DOLLAR_IN_LABEL */
-#define ANON_AGGRNAME_PREFIX "__anon_"
-  return (!strncmp (IDENTIFIER_POINTER (id_node), ANON_AGGRNAME_PREFIX, 
-		    sizeof (ANON_AGGRNAME_PREFIX) - 1));
-#endif	/* NO_DOLLAR_IN_LABEL */
-#endif	/* NO_DOT_IN_LABEL */
-}
+static GTY(()) unsigned anon_cnt = 0; /* Saved for PCH.  */
+
+/* Create a unique anonymous identifier.  The identifier is still a
+   valid assembly label.  */
 
-/* Return a format for an anonymous aggregate name.  */
-const char *
-anon_aggrname_format()
+tree
+make_anon_name ()
 {
-#ifndef NO_DOT_IN_LABEL
- return "._%d";
-#else /* NO_DOT_IN_LABEL */
-#ifndef NO_DOLLAR_IN_LABEL
-  return "$_%d";
-#else /* NO_DOLLAR_IN_LABEL */
-  return "__anon_%d";
-#endif	/* NO_DOLLAR_IN_LABEL */
-#endif	/* NO_DOT_IN_LABEL */
+  const char *fmt = 
+#if !defined (NO_DOT_IN_LABEL)
+    "."
+#elif !defined (NO_DOLLAR_IN_LABEL)
+    "$"
+#else
+    "_"
+#endif
+    "_anon_%d";
+
+  char buf[24];
+  int len = snprintf (buf, sizeof (buf), fmt, anon_cnt++);
+  gcc_checking_assert (len < int (sizeof (buf)));
+
+  tree id = get_identifier_with_length (buf, len);
+  IDENTIFIER_ANON_P (id) = true;
+
+  return id;
 }
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 271599)
+++ gcc/tree.h	(working copy)
@@ -933,4 +933,9 @@ extern void omp_clause_range_check_faile
   ((NODE)->base.deprecated_flag)
 
+/* Nonzero indicates an IDENTIFIER_NODE that names an anonymous
+   aggregate, (as created by anon_aggr_name_format).  */
+#define IDENTIFIER_ANON_P(NODE) \
+  (IDENTIFIER_NODE_CHECK (NODE)->base.private_flag)
+
 /* Nonzero in an IDENTIFIER_NODE if the name is a local alias, whose
    uses are to be substituted for uses of the TREE_CHAINed identifier.  */
@@ -5442,7 +5447,7 @@ target_opts_for_fn (const_tree fndecl)
 /* For anonymous aggregate types, we need some sort of name to
    hold on to.  In practice, this should not appear, but it should
-   not be harmful if it does.  */
-extern const char *anon_aggrname_format();
-extern bool anon_aggrname_p (const_tree);
+   not be harmful if it does.  Identifiers returned will be
+   IDENTIFIER_ANON_P.  */
+extern tree make_anon_name ();
 
 /* The tree and const_tree overload templates.   */
