public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* c++: Reorganize per-scope lambda discriminators
@ 2022-11-01 10:23 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2022-11-01 10:23 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 802 bytes --]


We currently use a per-extra-scope counter to discriminate multiple
lambdas in a particular such scope.  This is not ABI compliant.  This
patch merely refactors the existing code to make it easier to drop in
a conformant mangling -- there's no functional change here.  I rename
the LAMBDA_EXPR_DISCIMINATOR to LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR,
foreshadowing that there'll be a new discriminator.  To provide ABI
warnings we'll need to calculate both, and that requires some
repacking of the lambda_expr's fields.  Finally, although we end up
calling the discriminator setter and the scope recorder (nearly)
always consecutively, it's clearer to handle it as two separate
operations.  That also allows us to remove the instantiation
special-case for a null extra-scope.

nathan


-- 
Nathan Sidwell

[-- Attachment #2: 0001-c-Reorganize-per-scope-lambda-discriminators.patch --]
[-- Type: text/x-patch, Size: 21993 bytes --]

From 0122faae30fe1ad1dfa8c69f3d3f0428b996b600 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan@acm.org>
Date: Mon, 31 Oct 2022 06:11:28 -0400
Subject: [PATCH] c++: Reorganize per-scope lambda discriminators

We currently use a per-extra-scope counter to discriminate multiple
lambdas in a particular such scope.  This is not ABI compliant.  This
patch merely refactors the existing code to make it easier to drop in
a conformant mangling -- there's no functional change here.  I rename
the LAMBDA_EXPR_DISCIMINATOR to LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR,
foreshadowing that there'll be a new discriminator.  To provide ABI
warnings we'll need to calculate both, and that requires some
repacking of the lambda_expr's fields.  Finally, although we end up
calling the discriminator setter and the scope recorder (nearly)
always consecutively, it's clearer to handle it as two separate
operations.  That also allows us to remove the instantiation
special-case for a null extra-scope.

	gcc/cp/
	* cp-tree.h (LAMBDA_EXPR_DISCRIMINATOR): Rename to ...
	(LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR): ... here.
	(struct tree_lambda_expr): Make default_capture_mode &
	discriminator_scope bitfields.
	(record_null_lambda_scope) Delete.
	(record_lambda_scope_discriminator): Declare.
	* lambda.cc (struct lambda_discriminator): New struct.
	(lambda_scope, lambda_scope_stack): Adjust types.
	(lambda_count): Delete.
	(struct tree_int): Delete.
	(start_lambda_scope, finish_lambda_scope): Adjust.
	(record_lambda_scope): Only record the scope.
	(record_lambda_scope_discriminator): New.
	* mangle.cc (write_closure_type_name): Adjust.
	* module.cc (trees_out::core_vals): Likewise,
	(trees_in::core_vals): Likewise.
	* parser.cc (cp_parser_lambda_expression): Call
	record_lambda_scope_discriminator.
	* pt.cc (tsubst_lambda_expr): Adjust record_lambda_scope caling.  Call
	record_lambda_scope_discriminator. Commonize control flow on tsubsting
	the operator function.
	libcc1/
	* libcp1plugin.cc (plugin_start_closure): Adjust.
	gcc/testsuite/
	* g++.dg/abi/lambda-sig1-17.C: New.
	* g++.dg/abi/lambda-sig1.h: New.
	* g++.dg/cpp1y/lambda-mangle-1.C: Extracted to ...
	* g++.dg/cpp1y/lambda-mangle-1.h: ... here.
	* g++.dg/cpp1y/lambda-mangle-1-11.C: New
	* g++.dg/cpp1y/lambda-mangle-1-17.C
---
 gcc/cp/cp-tree.h                              |  17 +--
 gcc/cp/lambda.cc                              | 114 +++++++++---------
 gcc/cp/mangle.cc                              |   2 +-
 gcc/cp/module.cc                              |   4 +-
 gcc/cp/parser.cc                              |   5 +-
 gcc/cp/pt.cc                                  |  50 +++-----
 gcc/testsuite/g++.dg/abi/lambda-sig1-17.C     |  26 ++++
 gcc/testsuite/g++.dg/abi/lambda-sig1.h        |  42 +++++++
 .../g++.dg/cpp1y/lambda-mangle-1-11.C         |  25 ++++
 .../g++.dg/cpp1y/lambda-mangle-1-17.C         |  25 ++++
 .../{lambda-mangle-1.C => lambda-mangle-1.h}  |   3 +-
 libcc1/libcp1plugin.cc                        |   2 +-
 12 files changed, 208 insertions(+), 107 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-17.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1.h
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C
 rename gcc/testsuite/g++.dg/cpp1y/{lambda-mangle-1.C => lambda-mangle-1.h} (98%)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6d84514e4c0..4c0bacb91da 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1500,9 +1500,10 @@ enum cp_lambda_default_capture_mode_type {
 #define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope)
 
-/* If EXTRA_SCOPE, this is the number of the lambda within that scope.  */
-#define LAMBDA_EXPR_DISCRIMINATOR(NODE) \
-  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator)
+/* Lambdas in the same extra scope might need a discriminating count.
+   This is a single per-scope count.  */
+#define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope)
 
 /* During parsing of the lambda, a vector of capture proxies which need
    to be pushed once we're done processing a nested lambda.  */
@@ -1530,8 +1531,8 @@ struct GTY (()) tree_lambda_expr
   tree regen_info;
   vec<tree, va_gc> *pending_proxies;
   location_t locus;
-  enum cp_lambda_default_capture_mode_type default_capture_mode : 8;
-  short int discriminator;
+  enum cp_lambda_default_capture_mode_type default_capture_mode : 2;
+  unsigned discriminator_scope : 15; // Per-scope discriminator
 };
 
 /* Non-zero if this template specialization has access violations that
@@ -7778,10 +7779,10 @@ extern tree cp_build_vec_convert		(tree, location_t, tree,
 						 tsubst_flags_t);
 extern tree cp_build_bit_cast			(location_t, tree, tree,
 						 tsubst_flags_t);
-extern void start_lambda_scope			(tree);
-extern void record_lambda_scope			(tree);
-extern void record_null_lambda_scope		(tree);
+extern void start_lambda_scope			(tree decl);
 extern void finish_lambda_scope			(void);
+extern void record_lambda_scope			(tree lambda);
+extern void record_lambda_scope_discriminator	(tree lambda);
 extern tree start_lambda_function		(tree fn, tree lambda_expr);
 extern void finish_lambda_function		(tree body);
 extern bool regenerated_lambda_fn_p		(tree);
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index e9d5d4dc1c5..d2673e2ceeb 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1444,79 +1444,77 @@ is_lambda_ignored_entity (tree val)
   return false;
 }
 
-/* Lambdas that appear in variable initializer or default argument scope
-   get that in their mangling, so we need to record it.  We might as well
-   use the count for function and namespace scopes as well.  */
-static GTY(()) tree lambda_scope;
-static GTY(()) int lambda_count;
-struct GTY(()) tree_int
+/* Lambdas that appear in variable initializer or default argument
+   scope get that in their mangling, so we need to record it.  Also,
+   multiple lambdas in the same scope may need a mangling
+   discriminator.  Record in the same data structure.  */
+struct GTY(()) lambda_discriminator
 {
-  tree t;
-  int i;
+  tree scope;
+  unsigned nesting; // Inside a function, VAR_DECLs get the function
+  		    // as scope. This counts that nesting.
+  unsigned count;   // The per-scope counter.
 };
-static GTY(()) vec<tree_int, va_gc> *lambda_scope_stack;
+// The current scope.
+static GTY(()) lambda_discriminator lambda_scope;
+// Stack of previous scopes.
+static GTY(()) vec<lambda_discriminator, va_gc> *lambda_scope_stack;
+
+// Push DECL as lambda extra scope, also new discriminator counters.
 
 void
 start_lambda_scope (tree decl)
 {
-  tree_int ti;
-  gcc_assert (decl);
-  /* Once we're inside a function, we ignore variable scope and just push
-     the function again so that popping works properly.  */
+  gcc_checking_assert (decl);
   if (current_function_decl && TREE_CODE (decl) == VAR_DECL)
-    decl = current_function_decl;
-  ti.t = lambda_scope;
-  ti.i = lambda_count;
-  vec_safe_push (lambda_scope_stack, ti);
-  if (lambda_scope != decl)
-    {
-      /* Don't reset the count if we're still in the same function.  */
-      lambda_scope = decl;
-      lambda_count = 0;
-    }
-}
-
-void
-record_lambda_scope (tree lambda)
-{
-  LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;
-  LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;
-  if (lambda_scope)
-    {
-      tree closure = LAMBDA_EXPR_CLOSURE (lambda);
-      gcc_checking_assert (closure);
-      maybe_key_decl (lambda_scope, TYPE_NAME (closure));
-    }
-}
-
-/* This lambda is an instantiation of a lambda in a template default argument
-   that got no LAMBDA_EXPR_EXTRA_SCOPE, so this shouldn't either.  But we do
-   need to use and increment the global count to avoid collisions.  */
-
-void
-record_null_lambda_scope (tree lambda)
-{
-  if (vec_safe_is_empty (lambda_scope_stack))
-    record_lambda_scope (lambda);
+    // If we're inside a function, we ignore variable scope.  Don't push.
+    lambda_scope.nesting++;
   else
     {
-      tree_int *p = lambda_scope_stack->begin();
-      LAMBDA_EXPR_EXTRA_SCOPE (lambda) = p->t;
-      LAMBDA_EXPR_DISCRIMINATOR (lambda) = p->i++;
+      vec_safe_push (lambda_scope_stack, lambda_scope);
+      lambda_scope.scope = decl;
+      lambda_scope.nesting = 0;
+      lambda_scope.count = 0;
     }
-  gcc_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == NULL_TREE);
 }
 
+// Pop from the current lambda extra scope.
+
 void
 finish_lambda_scope (void)
 {
-  tree_int *p = &lambda_scope_stack->last ();
-  if (lambda_scope != p->t)
+  if (!lambda_scope.nesting--)
     {
-      lambda_scope = p->t;
-      lambda_count = p->i;
+      lambda_scope = lambda_scope_stack->last ();
+      lambda_scope_stack->pop ();
     }
-  lambda_scope_stack->pop ();
+}
+
+// Record the current lambda scope into LAMBDA
+
+void
+record_lambda_scope (tree lambda)
+{
+  LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope.scope;
+  if (lambda_scope.scope)
+    {
+      tree closure = LAMBDA_EXPR_CLOSURE (lambda);
+      gcc_checking_assert (closure);
+      maybe_key_decl (lambda_scope.scope, TYPE_NAME (closure));
+    }
+}
+
+// Record the per-scope discriminator of LAMBDA.  If the extra scope
+// is empty, we must use the empty scope counter, which might not be
+// the live one.
+
+void
+record_lambda_scope_discriminator (tree lambda)
+{
+  auto *slot = (vec_safe_is_empty (lambda_scope_stack)
+		|| LAMBDA_EXPR_EXTRA_SCOPE (lambda)
+		? &lambda_scope : lambda_scope_stack->begin ());
+  LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda) = slot->count++;
 }
 
 tree
@@ -1648,6 +1646,10 @@ prune_lambda_captures (tree body)
     }
 }
 
+// Record the per-scope per-signature discriminator of LAMBDA.  If the
+// extra scope is empty, we must use the empty scope counter, which
+// might not be the live one.
+
 void
 finish_lambda_function (tree body)
 {
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index e39621876ef..a62c9756c91 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1810,7 +1810,7 @@ write_closure_type_name (const tree type)
 
   write_method_parms (parms, /*method_p=*/1, fn);
   write_char ('E');
-  write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
+  write_compact_number (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda));
 }
 
 /* Convert NUMBER to ascii using base BASE and generating at least
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 9957df510e6..df05b524136 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -6327,7 +6327,7 @@ trees_out::core_vals (tree t)
       if (streaming_p ())
 	{
 	  WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode);
-	  WU (((lang_tree_node *)t)->lambda_expression.discriminator);
+	  WU (((lang_tree_node *)t)->lambda_expression.discriminator_scope);
 	}
       break;
 
@@ -6819,7 +6819,7 @@ trees_in::core_vals (tree t)
 	= state->read_location (*this);
       RUC (cp_lambda_default_capture_mode_type,
 	   ((lang_tree_node *)t)->lambda_expression.default_capture_mode);
-      RU (((lang_tree_node *)t)->lambda_expression.discriminator);
+      RU (((lang_tree_node *)t)->lambda_expression.discriminator_scope);
       break;
 
     case OVERLOAD:
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 6da32801bab..e0e3cf3eaf6 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -11035,6 +11035,7 @@ cp_parser_lambda_expression (cp_parser* parser)
     return error_mark_node;
 
   record_lambda_scope (lambda_expr);
+  record_lambda_scope_discriminator (lambda_expr);
 
   /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set.  */
   determine_visibility (TYPE_NAME (type));
@@ -11085,9 +11086,7 @@ cp_parser_lambda_expression (cp_parser* parser)
       ok = false;
 
     if (ok)
-      {
-	cp_parser_lambda_body (parser, lambda_expr);
-      }
+      cp_parser_lambda_body (parser, lambda_expr);
     else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
       {
 	if (cp_parser_skip_to_closing_brace (parser))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 51bfbbcd36d..fc6279c00a3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19866,21 +19866,13 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
-    {
-      /* A lambda in a default argument outside a class gets no
-	 LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI.  But
-	 tsubst_default_argument calls start_lambda_scope, so we need to
-	 specifically ignore it here, and use the global scope.  */
-      record_null_lambda_scope (r);
-
-      /* If we're pushed into another scope (PR105652), fix it.  */
-      if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t)))
-	TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type))
-	  = TYPE_CONTEXT (TREE_TYPE (t));
-    }
-  else
+  if (LAMBDA_EXPR_EXTRA_SCOPE (t))
     record_lambda_scope (r);
+  else if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t)))
+    /* If we're pushed into another scope (PR105652), fix it.  */
+    TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type))
+      = TYPE_CONTEXT (TREE_TYPE (t));
+  record_lambda_scope_discriminator (r);
 
   /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set.  */
   determine_visibility (TYPE_NAME (type));
@@ -19911,29 +19903,17 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       fntype = build_memfn_type (fntype, type,
 				 type_memfn_quals (fntype),
 				 type_memfn_rqual (fntype));
-      tree fn, tmpl;
-      if (oldtmpl)
+      tree inst = (oldtmpl
+		   ? tsubst_template_decl (oldtmpl, args, complain, fntype)
+		   : tsubst_function_decl (oldfn, args, complain, fntype));
+      if (inst == error_mark_node)
 	{
-	  tmpl = tsubst_template_decl (oldtmpl, args, complain, fntype);
-	  if (tmpl == error_mark_node)
-	    {
-	      r = error_mark_node;
-	      goto out;
-	    }
-	  fn = DECL_TEMPLATE_RESULT (tmpl);
-	  finish_member_declaration (tmpl);
-	}
-      else
-	{
-	  tmpl = NULL_TREE;
-	  fn = tsubst_function_decl (oldfn, args, complain, fntype);
-	  if (fn == error_mark_node)
-	    {
-	      r = error_mark_node;
-	      goto out;
-	    }
-	  finish_member_declaration (fn);
+	  r = error_mark_node;
+	  goto out;
 	}
+      finish_member_declaration (inst);
+
+      tree fn = oldtmpl ? DECL_TEMPLATE_RESULT (inst) : inst;
 
       /* Let finish_function set this.  */
       DECL_DECLARED_CONSTEXPR_P (fn) = false;
diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C
new file mode 100644
index 00000000000..cb71209f957
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-sig1-17.C
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++20 } }
+// { dg-options -fabi-version=17 }
+
+#include "lambda-sig1.h"
+
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE3_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfT_E1_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfT_E4_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlT_E2_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE3_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE6_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E1_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E4_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfT_E7_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E2_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E5_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE0_clEi:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE3_clEi:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliT_E1_clIiEEDaiS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliT_E4_clIiEEDaiS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlT_E2_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlT_E_clIiEEDaS1_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1.h b/gcc/testsuite/g++.dg/abi/lambda-sig1.h
new file mode 100644
index 00000000000..a8b77ae0ebf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-sig1.h
@@ -0,0 +1,42 @@
+template<typename T, unsigned I> struct X 
+{
+  void Fn () 
+  {
+    {
+      auto v1 = []<typename U> (U) {};
+      auto v2 = [] (T) {};
+      auto v3 = []<typename U> (T, U) {};
+
+      v1 (1);
+      v2 (1);
+      v3 (1, 2);
+    }
+    if constexpr (I) 
+      {
+	auto v1 = []<typename U> (U) {};
+	auto v2 = [] (T) {};
+	auto v3 = []<typename U> (T, U) {};
+
+	v1 (1);
+	v2 (1);
+	v3 (1, 2);
+      }
+    {
+      auto v1 = []<typename U> (U) {};
+      auto v2 = [] (T) {};
+      auto v3 = []<typename U> (T, U) {};
+
+      v1 (1);
+      v2 (1);
+      v3 (1, 2);
+    }
+    
+  };
+};
+
+void f (X<int, 0> &x, X<float, 0> &y, X<float, 1> &z)
+{
+  x.Fn ();
+  y.Fn ();
+  z.Fn ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C
new file mode 100644
index 00000000000..9847587950c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options -fabi-version=11 }
+
+// PRs 78621
+
+#include "lambda-mangle-1.h"
+
+// We erroneously mangled lambda auto parms as-if template parameters (T<n>_),
+// rather than auto (Da). Fixed in abi version 11
+
+
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } }
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C
new file mode 100644
index 00000000000..31af5b89bfd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options -fabi-version=17 }
+
+// PRs 78621
+
+#include "lambda-mangle-1.h"
+
+// We erroneously mangled lambda auto parms as-if template parameters (T<n>_),
+// rather than auto (Da). Fixed in abi version 11
+// Up to abi version 17 we had a single per-scope discriminator
+
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } }
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h
similarity index 98%
rename from gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
rename to gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h
index 8f135358465..c91ce0186d8 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.h
@@ -23,7 +23,7 @@ template<typename S, typename T>
 {
 }
 
-void Foo ()
+inline void Foo ()
 {
   auto lam = [](auto &) { };
   auto lam_1 = [](int &, auto &) { };
@@ -70,6 +70,7 @@ template<typename X> void Bar ()
 void Baz ()
 {
   Bar<short> ();
+  Foo ();
 }
 
 // { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index e2d5039a0a1..b0f0cb96626 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -1655,7 +1655,7 @@ plugin_start_closure_class_type (cc1_plugin::connection *self,
 
   /* Instead of calling record_lambda_scope, do this:  */
   LAMBDA_EXPR_EXTRA_SCOPE (lambda_expr) = extra_scope;
-  LAMBDA_EXPR_DISCRIMINATOR (lambda_expr) = discriminator;
+  LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda_expr) = discriminator;
 
   tree decl = TYPE_NAME (type);
   determine_visibility (decl);
-- 
2.38.1


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-11-01 10:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-01 10:23 c++: Reorganize per-scope lambda discriminators Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).