diff mbox series

[C++PATCH] Lambda names are anonymous

Message ID 36bb0af3-dbf1-b881-3f5f-9083f8755be5@acm.org
State New
Headers show
Series [C++PATCH] Lambda names are anonymous | expand

Commit Message

Nathan Sidwell May 31, 2019, 1:23 p.m. UTC
Lambda types have names that are anonymous for all intents and purposes, 
but sometimes need to be distinguished from other unnamed types.  We 
currently create lambda names specially.  This patch changes that to use 
the anon-name machinery, and then set another spare bit on that 
identifier to mark it specially.

The 'LAMBDA_TYPE_P' macro can accept any node (not just types), but that 
(a) is different to the TYPE_ANON_P and other such macros, and (b) 
nearly all use cases fall into:
i) we know we have a type,
ii) we're doing LAMBDA_TYPE_P (DECL_CONTEXT (thing))

This suggests replacing LAMBDA_TYPE_P with:
1) TYPE_LAMBDA_P for cases we have a type
2) DECL_LAMBDA_SCOPE_P for the context case (mirroring DECL_CLASS_SCOPE_P)

I'll do that in a later patch.

nathan
diff mbox series

Patch

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

	* cp-tree.h (IDENTIFIER_LAMBDA_P): New.
	(TYPE_ANON_P): New.
	(LAMBDA_TYPE_P, TYPE_UNNAMED_P):  Likewise.
	(LAMBDANAME_PREFIX, LAMBDANAME_FORMAT): Delete.
	(make_lambda_name): Don't declare.
	* error.c (dump_aggr_type): Check for lambdas before other
	anonymous names.
	* lambda.c (begin_lambda_type): Use make_anon_name.
	* cp-lang.c (cxx_dwarf_name): Lambda names smell anonymous.
	* mangle.c (write_local_name): Likewise.
	* name-lookup.c (lambda_cnt, make_lambda_name): Delete.

Index: gcc/cp/cp-lang.c
===================================================================
--- gcc/cp/cp-lang.c	(revision 271809)
+++ gcc/cp/cp-lang.c	(working copy)
@@ -110,6 +110,5 @@  cxx_dwarf_name (tree t, int verbosity)
   gcc_assert (DECL_P (t));
 
-  if (DECL_NAME (t)
-      && (IDENTIFIER_ANON_P (DECL_NAME (t)) || LAMBDA_TYPE_P (t)))
+  if (DECL_NAME (t) && IDENTIFIER_ANON_P (DECL_NAME (t)))
     return NULL;
   if (verbosity >= 2)
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 271809)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -1298,7 +1298,14 @@  struct GTY (()) tree_trait_expr {
 };
 
+/* Identifiers used for lambda types are almost anonymous.  Use this
+   spare flag to distinguish them (they also have the anonymous flag).  */
+#define IDENTIFIER_LAMBDA_P(NODE) \
+  (IDENTIFIER_NODE_CHECK(NODE)->base.protected_flag)
+
 /* Based off of TYPE_UNNAMED_P.  */
-#define LAMBDA_TYPE_P(NODE) \
-  (CLASS_TYPE_P (NODE) && CLASSTYPE_LAMBDA_EXPR (NODE))
+#define LAMBDA_TYPE_P(NODE)			\
+  (TREE_CODE (NODE) == RECORD_TYPE		\
+   && TYPE_LINKAGE_IDENTIFIER (NODE)				\
+   && IDENTIFIER_LAMBDA_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
 
 /* Test if FUNCTION_DECL is a lambda function.  */
@@ -1936,7 +1943,13 @@  enum languages { lang_c, lang_cplusplus
 #define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE)))
 
-/* Nonzero if NODE has no name for linkage purposes.  */
-#define TYPE_UNNAMED_P(NODE) \
-  (OVERLOAD_TYPE_P (NODE) && IDENTIFIER_ANON_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
+/* Any kind of anonymous type.  */
+#define TYPE_ANON_P(NODE)					\
+  (TYPE_LINKAGE_IDENTIFIER (NODE)				\
+   && IDENTIFIER_ANON_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
+
+/* Nonzero if NODE, a TYPE, has no name for linkage purposes.  */
+#define TYPE_UNNAMED_P(NODE)					\
+  (TYPE_ANON_P (NODE)						\
+   && !IDENTIFIER_LAMBDA_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
 
 /* The _DECL for this _TYPE.  */
@@ -5358,7 +5371,4 @@  extern GTY(()) vec<tree, va_gc> *keyed_c
 #endif	/* NO_DOT_IN_LABEL */
 
-#define LAMBDANAME_PREFIX "__lambda"
-#define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d"
-
 #define UDLIT_OP_ANSI_PREFIX "operator\"\""
 #define UDLIT_OP_ANSI_FORMAT UDLIT_OP_ANSI_PREFIX "%s"
@@ -6366,5 +6376,4 @@  extern bool note_iteration_stmt_body_sta
 extern void note_iteration_stmt_body_end	(bool);
 extern void determine_local_discriminator	(tree);
-extern tree make_lambda_name			(void);
 extern int decls_match				(tree, tree, bool = true);
 extern bool maybe_version_functions		(tree, tree, bool);
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 271809)
+++ gcc/cp/error.c	(working copy)
@@ -739,12 +739,5 @@  dump_aggr_type (cxx_pretty_printer *pp,
     }
 
-  if (!name || IDENTIFIER_ANON_P (name))
-    {
-      if (flags & TFF_CLASS_KEY_OR_ENUM)
-	pp_string (pp, M_("<unnamed>"));
-      else
-	pp_printf (pp, M_("<unnamed %s>"), variety);
-    }
-  else if (LAMBDA_TYPE_P (t))
+  if (LAMBDA_TYPE_P (t))
     {
       /* A lambda's "type" is essentially its signature.  */
@@ -756,6 +749,14 @@  dump_aggr_type (cxx_pretty_printer *pp,
       pp_greater (pp);
     }
+  else if (!name || IDENTIFIER_ANON_P (name))
+    {
+      if (flags & TFF_CLASS_KEY_OR_ENUM)
+	pp_string (pp, M_("<unnamed>"));
+      else
+	pp_printf (pp, M_("<unnamed %s>"), variety);
+    }
   else
     pp_cxx_tree_identifier (pp, name);
+
   if (tmplate)
     dump_template_parms (pp, TYPE_TEMPLATE_INFO (t),
Index: gcc/cp/lambda.c
===================================================================
--- gcc/cp/lambda.c	(revision 271809)
+++ gcc/cp/lambda.c	(working copy)
@@ -129,20 +129,13 @@  tree
 begin_lambda_type (tree lambda)
 {
-  tree type;
+  /* Lambda names are nearly but not quite anonymous.  */
+  tree name = make_anon_name ();
+  IDENTIFIER_LAMBDA_P (name) = true;
 
-  {
-    /* Unique name.  This is just like an unnamed class, but we cannot use
-       make_anon_name because of certain checks against TYPE_UNNAMED_P.  */
-    tree name;
-    name = make_lambda_name ();
-
-    /* Create the new RECORD_TYPE for this lambda.  */
-    type = xref_tag (/*tag_code=*/record_type,
-                     name,
-                     /*scope=*/ts_lambda,
-                     /*template_header_p=*/false);
-    if (type == error_mark_node)
-      return error_mark_node;
-  }
+  /* Create the new RECORD_TYPE for this lambda.  */
+  tree type = xref_tag (/*tag_code=*/record_type, name,
+			/*scope=*/ts_lambda, /*template_header_p=*/false);
+  if (type == error_mark_node)
+    return error_mark_node;
 
   /* Designate it as a struct so that we can use aggregate initialization.  */
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 271809)
+++ gcc/cp/mangle.c	(working copy)
@@ -2005,6 +2005,5 @@  write_local_name (tree function, const t
       if (DECL_DISCRIMINATOR_P (local_entity)
 	  && !(TREE_CODE (local_entity) == TYPE_DECL
-	       && (LAMBDA_TYPE_P (TREE_TYPE (local_entity))
-		   || TYPE_UNNAMED_P (TREE_TYPE (local_entity)))))
+	       && TYPE_ANON_P (TREE_TYPE (local_entity))))
 	write_discriminator (discriminator_for_local_entity (local_entity));
     }
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 271809)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -3798,20 +3798,4 @@  constructor_name_p (tree name, tree type
 }
 
-/* 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.  */
-
-static GTY(()) int lambda_cnt = 0;
-
-tree
-make_lambda_name (void)
-{
-  char buf[32];
-
-  sprintf (buf, LAMBDANAME_FORMAT, lambda_cnt++);
-  return get_identifier (buf);
-}
-
 /* Same as pushdecl, but define X in binding-level LEVEL.  We rely on the
    caller to set DECL_CONTEXT properly.