]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: per-scope, per-signature lambda discriminators
authorNathan Sidwell <nathan@acm.org>
Mon, 31 Oct 2022 10:11:28 +0000 (06:11 -0400)
committerNathan Sidwell <nathan@acm.org>
Tue, 1 Nov 2022 21:44:36 +0000 (17:44 -0400)
This implements ABI-compliant lambda discriminators.  Not only do we
have per-scope counters, but we also distinguish by lambda signature.
Only lambdas with the same signature will need non-zero
discriminators.  As the discriminator is signature-dependent, we have
to process the lambda function's declaration before we can determine
it.  For templated and generic lambdas the signature is that of the
uninstantiated lambda -- not separate for each instantiation.

With this change, gcc and clang now produce the same lambda manglings
for all these testcases.

gcc/cp/
* cp-tree.h (LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR): New.
(struct tree_lambda_expr): Add discriminator_sig bitfield.
(recrd_lambda_scope_sig_discriminator): Declare.
* lambda.cc (struct lambda_sig_count): New.
(lambda_discriminator): Add signature vector.
(start_lambda_scope): Adjust.
(compare_lambda_template_head, compare_lambda_sig): New.
(record_lambda_scope_sig_discriminator): New.
* mangle.cc (write_closure_type): Use the scope-sig discriminator for
ABI >= 18.  Emit abi mangling warning if needed.
* module.cc (trees_out::core_vals): Stream the new discriminator.
(trees_in::core_vals): Likewise.
* parser.cc (cp_parser_lambda_declarator_opt): Call
record_lambda_scope_sig_discriminator.
* pt.cc (tsubst_lambda_expr): Likewise.
libcc1/
* libcp1plugin.cc (plugin_start_lambda_closure_class_type):
Initialize the per-scope, per-signature discriminator.
gcc/testsuite/
* g++.dg/abi/lambda-sig1-18.C: New.
* g++.dg/abi/lambda-sig1-18vs17.C: New.
* g++.dg/cpp1y/lambda-mangle-1-18.C: New.

gcc/cp/cp-tree.h
gcc/cp/lambda.cc
gcc/cp/mangle.cc
gcc/cp/module.cc
gcc/cp/parser.cc
gcc/cp/pt.cc
gcc/testsuite/g++.dg/abi/lambda-sig1-18.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C [new file with mode: 0644]
libcc1/libcp1plugin.cc

index 4c0bacb91da1f3ca1dc7bb9fe09449a5be5a82d5..d13bb3d4c0eb3d9a6918763946af4f774c3112d2 100644 (file)
@@ -1501,9 +1501,12 @@ enum cp_lambda_default_capture_mode_type {
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope)
 
 /* Lambdas in the same extra scope might need a discriminating count.
-   This is a single per-scope count.  */
+   For ABI 17, we have single per-scope count, for ABI 18, we have
+   per-scope, per-signature numbering.  */
 #define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope)
+#define LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_sig)
 
 /* During parsing of the lambda, a vector of capture proxies which need
    to be pushed once we're done processing a nested lambda.  */
@@ -1533,6 +1536,7 @@ struct GTY (()) tree_lambda_expr
   location_t locus;
   enum cp_lambda_default_capture_mode_type default_capture_mode : 2;
   unsigned discriminator_scope : 15; // Per-scope discriminator
+  unsigned discriminator_sig : 15; // Per-scope, per-signature discriminator
 };
 
 /* Non-zero if this template specialization has access violations that
@@ -7783,6 +7787,7 @@ 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 void record_lambda_scope_sig_discriminator (tree lambda, tree fn);
 extern tree start_lambda_function              (tree fn, tree lambda_expr);
 extern void finish_lambda_function             (tree body);
 extern bool regenerated_lambda_fn_p            (tree);
index d2673e2ceebadaa4dadb3e374b0cccf69ed34892..c7a9268251b4b78896bd610f3016675ca15d3c13 100644 (file)
@@ -1447,13 +1447,21 @@ is_lambda_ignored_entity (tree val)
 /* 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.  */
+   discriminator.  In ABI <= 17, there is a single per-scope sequence
+   number.  In ABI >= 18, there are per-scope per-signature sequence
+   numbers.  */
+struct GTY(()) lambda_sig_count
+{
+  tree fn; // The lambda fn whose sig this is.
+  unsigned count;
+};
 struct GTY(()) lambda_discriminator
 {
   tree scope;
   unsigned nesting; // Inside a function, VAR_DECLs get the function
                    // as scope. This counts that nesting.
   unsigned count;   // The per-scope counter.
+  vec<lambda_sig_count, va_gc> *discriminators; // Per-signature counters
 };
 // The current scope.
 static GTY(()) lambda_discriminator lambda_scope;
@@ -1475,6 +1483,7 @@ start_lambda_scope (tree decl)
       lambda_scope.scope = decl;
       lambda_scope.nesting = 0;
       lambda_scope.count = 0;
+      lambda_scope.discriminators = nullptr;
     }
 }
 
@@ -1504,6 +1513,116 @@ record_lambda_scope (tree lambda)
     }
 }
 
+// Compare lambda template heads TMPL_A and TMPL_B, used for both
+// templated lambdas, and template template parameters of said lambda.
+
+static bool
+compare_lambda_template_head (tree tmpl_a, tree tmpl_b)
+{
+  // We only need one level of template parms
+  tree inner_a = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl_a));
+  tree inner_b = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl_b));
+
+  // We only compare explicit template parms, ignoring trailing
+  // synthetic ones.
+  int len_a = TREE_VEC_LENGTH (inner_a);
+  int len_b = TREE_VEC_LENGTH (inner_b);
+  
+  for (int ix = 0, len = MAX (len_a, len_b); ix != len; ix++)
+    {
+      tree parm_a = NULL_TREE;
+      if (ix < len_a)
+       {
+         parm_a = TREE_VEC_ELT (inner_a, ix);
+         if (parm_a == error_mark_node)
+           return false;
+         parm_a = TREE_VALUE (parm_a);
+         if (DECL_VIRTUAL_P (parm_a))
+           parm_a = NULL_TREE;
+       }
+      
+      tree parm_b = NULL_TREE;
+      if (ix < len_b)
+       {
+         parm_b = TREE_VEC_ELT (inner_b, ix);
+         if (parm_b == error_mark_node)
+           return false;
+         parm_b = TREE_VALUE (parm_b);
+         if (DECL_VIRTUAL_P (parm_b))
+           parm_b = NULL_TREE;
+       }
+
+      if (!parm_a && !parm_b)
+       // we're done
+       break;
+
+      if (!(parm_a && parm_b))
+       return false;
+
+      if (TREE_CODE (parm_a) != TREE_CODE (parm_b))
+       return false;
+
+      if (TREE_CODE (parm_a) == PARM_DECL)
+       {
+         if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm_a))
+             != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm_b)))
+           return false;
+
+         if (!same_type_p (TREE_TYPE (parm_a), TREE_TYPE (parm_b)))
+           return false;
+       }
+      else 
+       {
+         if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm_a))
+             != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm_b)))
+           return false;
+
+         if (TREE_CODE (parm_a) != TEMPLATE_DECL)
+           gcc_checking_assert (TREE_CODE (parm_a) == TYPE_DECL);
+         else if (!compare_lambda_template_head (parm_a, parm_b))
+           return false;
+       }
+    }
+
+  return true;
+}
+
+// Compare lambda signatures FN_A and FN_B, they may be TEMPLATE_DECLs too.
+
+static bool
+compare_lambda_sig (tree fn_a, tree fn_b)
+{
+  if (TREE_CODE (fn_a) == TEMPLATE_DECL
+      && TREE_CODE (fn_b) == TEMPLATE_DECL)
+    {
+      if (!compare_lambda_template_head (fn_a, fn_b))
+       return false;
+      fn_a = DECL_TEMPLATE_RESULT (fn_a);
+      fn_b = DECL_TEMPLATE_RESULT (fn_b);
+    }
+  else if (TREE_CODE (fn_a) == TEMPLATE_DECL
+          || TREE_CODE (fn_b) == TEMPLATE_DECL)
+    return false;
+
+  if (fn_a == error_mark_node
+      || fn_b == error_mark_node)
+    return false;
+
+  for (tree args_a = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn_a))),
+        args_b = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn_b)));
+       args_a || args_b;
+       args_a = TREE_CHAIN (args_a), args_b = TREE_CHAIN (args_b))
+    {
+      if (!args_a || !args_b)
+       return false;
+      // This check also deals with differing varadicness
+      if (!same_type_p (TREE_VALUE (args_a), TREE_VALUE (args_b)))
+       return false;
+    }
+
+  return true;
+}
+
 // 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.
@@ -1517,6 +1636,33 @@ record_lambda_scope_discriminator (tree lambda)
   LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda) = slot->count++;
 }
 
+// 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
+record_lambda_scope_sig_discriminator (tree lambda, tree fn)
+{
+  auto *slot = (vec_safe_is_empty (lambda_scope_stack)
+               || LAMBDA_EXPR_EXTRA_SCOPE (lambda)
+               ? &lambda_scope : lambda_scope_stack->begin ());
+  gcc_checking_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == slot->scope);
+
+  // A linear search, we're not expecting this to be a big list, and
+  // this avoids needing a signature hash function.
+  lambda_sig_count *sig;
+  if (unsigned ix = vec_safe_length (slot->discriminators))
+    for (sig = slot->discriminators->begin (); ix--; sig++)
+      if (compare_lambda_sig (fn, sig->fn))
+       goto found;
+  {
+    lambda_sig_count init = {fn, 0};
+    sig = vec_safe_push (slot->discriminators, init);
+  }
+ found:
+  LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda) = sig->count++;
+}
+
 tree
 start_lambda_function (tree fco, tree lambda_expr)
 {
index a62c9756c9161622830b8c2dcf45d958f09c3779..e97428e8f30a1249a55da11f3f2e972fa75f5513 100644 (file)
@@ -1810,7 +1810,13 @@ write_closure_type_name (const tree type)
 
   write_method_parms (parms, /*method_p=*/1, fn);
   write_char ('E');
-  write_compact_number (LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda));
+  if ((LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda)
+       != LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda))
+      && abi_warn_or_compat_version_crosses (18))
+    G.need_abi_warning = true;
+  write_compact_number (abi_version_at_least (18)
+                       ? LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda)
+                       : LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR (lambda));
 }
 
 /* Convert NUMBER to ascii using base BASE and generating at least
index df05b524136fbe5571c1585e99d6ded82bf33aea..0e9af318ba48e987b9617f7212775848aa3c44d7 100644 (file)
@@ -6328,6 +6328,7 @@ trees_out::core_vals (tree t)
        {
          WU (((lang_tree_node *)t)->lambda_expression.default_capture_mode);
          WU (((lang_tree_node *)t)->lambda_expression.discriminator_scope);
+         WU (((lang_tree_node *)t)->lambda_expression.discriminator_sig);
        }
       break;
 
@@ -6820,6 +6821,7 @@ trees_in::core_vals (tree t)
       RUC (cp_lambda_default_capture_mode_type,
           ((lang_tree_node *)t)->lambda_expression.default_capture_mode);
       RU (((lang_tree_node *)t)->lambda_expression.discriminator_scope);
+      RU (((lang_tree_node *)t)->lambda_expression.discriminator_sig);
       break;
 
     case OVERLOAD:
index e0e3cf3eaf6c128055b1ff091f00083855510358..fd59de491cd9ccaf4ef71d43dea257385d64abd1 100644 (file)
@@ -11712,6 +11712,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       fco = finish_fully_implicit_template (parser, fco);
 
     finish_member_declaration (fco);
+    record_lambda_scope_sig_discriminator (lambda_expr, fco);
 
     obstack_free (&declarator_obstack, p);
 
index fc6279c00a3e6c6592a2831d90641be7c5e708c1..c3fc56a13ffc8bccb6965083cf243db2ad18a837 100644 (file)
@@ -19912,6 +19912,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          goto out;
        }
       finish_member_declaration (inst);
+      record_lambda_scope_sig_discriminator (r, inst);
 
       tree fn = oldtmpl ? DECL_TEMPLATE_RESULT (inst) : inst;
 
diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-18.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-18.C
new file mode 100644 (file)
index 0000000..88692ed
--- /dev/null
@@ -0,0 +1,34 @@
+// { dg-do compile { target c++20 } }
+// { dg-options -fabi-version=18 }
+
+#include "lambda-sig1.h"
+
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyfT_E_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyfT_E0_clIiEEDafS1_:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlfE1_clEf:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyfT_E_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyfT_E0_clIiEEDafS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyfT_E1_clIiEEDafS1_:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyT_E0_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIfLj1EE2FnEvENKUlTyT_E1_clIiEEDaS1_:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE_clEi:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUliE0_clEi:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyiT_E_clIiEEDaiS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyiT_E0_clIiEEDaiS1_:} } }
+
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZZN1XIiLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C b/gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C
new file mode 100644 (file)
index 0000000..b191fb3
--- /dev/null
@@ -0,0 +1,40 @@
+// { dg-do compile { target c++20 } }
+// { dg-options {-fabi-version=18 -Wabi=17} }
+
+#include "lambda-sig1.h"
+
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfT_E7_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyfT_E1_clIiEEDafS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlT_E5_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyT_E1_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE6_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE1_cvPFvfEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENUlfE6_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENUlfE1_4_FUNEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE6_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE1_clEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfT_E4_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyfT_E0_clIiEEDafS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlT_E2_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyT_E0_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE3_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE0_cvPFvfEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENUlfE3_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENUlfE0_4_FUNEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE3_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfT_E1_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyfT_E_clIiEEDafS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlT_E_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlTyT_E_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE0_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE_cvPFvfEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENUlfE0_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENUlfE_4_FUNEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj1EE2FnEvENKUlfE0_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj1EE2FnEvENKUlfE_clEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfT_E4_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyfT_E0_clIiEEDafS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlT_E2_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE3_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE0_cvPFvfEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENUlfE3_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENUlfE0_4_FUNEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE3_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfT_E1_clIiEEDafS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyfT_E_clIiEEDafS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlT_E_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE0_cvPFvfEEv'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE_cvPFvfEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENUlfE0_4_FUNEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENUlfE_4_FUNEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIfLj0EE2FnEvENKUlfE0_clEf'\) and '-fabi-version=18' \('_ZZN1XIfLj0EE2FnEvENKUlfE_clEf'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliT_E4_clIiEEDaiS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyiT_E0_clIiEEDaiS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUlT_E2_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyT_E0_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE3_cvPFviEEv'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE0_cvPFviEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENUliE3_4_FUNEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENUliE0_4_FUNEi'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE3_clEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE0_clEi'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliT_E1_clIiEEDaiS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyiT_E_clIiEEDaiS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUlT_E_clIiEEDaS1_'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUlTyT_E_clIiEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE0_cvPFviEEv'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE_cvPFviEEv'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENUliE0_4_FUNEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENUliE_4_FUNEi'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-sig1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZN1XIiLj0EE2FnEvENKUliE0_clEi'\) and '-fabi-version=18' \('_ZZN1XIiLj0EE2FnEvENKUliE_clEi'\) [^\n]*\n} }
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C
new file mode 100644 (file)
index 0000000..22ad15e
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++14 } }
+// { dg-additional-options -fabi-version=18 }
+
+// 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
+
+// ABI 18 uses per-scope per-signature lambda discriminator
+
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E_EOS1_S2_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE_EOS0_S1_:" } }
+// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E_EOS0_RS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E_EvS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE_EvS1_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E_EvRS0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E_EvRS1_RS3_:" } }
+// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E_Z3FoovEUlS1_S3_E0_EvRS0_RS2_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E_EvRS3_RS5_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E_EvRT_RT0_:" } }
index b0f0cb96626750a2f80b4c62ff4d022279c46e97..e232aaceef97a7d8f8da056ed60245b682d57678 100644 (file)
@@ -1656,6 +1656,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_SCOPE_ONLY_DISCRIMINATOR (lambda_expr) = discriminator;
+  LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR (lambda_expr) = discriminator;
 
   tree decl = TYPE_NAME (type);
   determine_visibility (decl);