https://gcc.gnu.org/g:8caf67eea7e1b29a4437f07d13c300d9fdb04827

commit r15-7519-g8caf67eea7e1b29a4437f07d13c300d9fdb04827
Author: Nathaniel Shead <nathanielosh...@gmail.com>
Date:   Fri Jan 31 23:01:15 2025 +1100

    c++: Clear lambda scope for unattached member template lambdas
    
    In r15-7202 we made lambdas between a template parameter scope and a
    class/function/initializer be considered TU-local, in lieu of working
    out how to mangle them to the succeeding declaration.
    
    I neglected to clear any existing mangling on the template declaration
    however; this means that such lambdas can occasionally get a lambda
    scope, and will in general inherit the lambda scope of their
    instantiation context (whatever that might be).
    
    This patch ensures that the scope is cleared on the template declaration
    as well.
    
    gcc/cp/ChangeLog:
    
            * lambda.cc (record_lambda_scope): Clear mangling scope for
            otherwise unattached lambdas in class member templates.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp2a/lambda-uneval22.C: Add check that the primary
            specialisation of the lambda is TU-local.
    
    Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>

Diff:
---
 gcc/cp/lambda.cc                             | 11 +++++++++++
 gcc/testsuite/g++.dg/cpp2a/lambda-uneval22.C |  3 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index c612f4fe1ad0..09898f6746ca 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -1572,6 +1572,17 @@ record_lambda_scope (tree lambda)
        }
     }
 
+  /* An otherwise unattached class-scope lambda in a member template
+     should not have a mangling scope, as the mangling scope will not
+     correctly inherit on instantiation.  */
+  tree ctx = TYPE_CONTEXT (closure);
+  if (scope
+      && ctx
+      && CLASS_TYPE_P (ctx)
+      && ctx == TREE_TYPE (scope)
+      && current_template_depth > template_class_depth (ctx))
+    scope = NULL_TREE;
+
   LAMBDA_EXPR_EXTRA_SCOPE (lambda) = scope;
   if (scope)
     maybe_key_decl (scope, TYPE_NAME (closure));
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval22.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval22.C
index 9c0e8128f108..1a25a0255fc1 100644
--- a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval22.C
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval22.C
@@ -5,7 +5,7 @@ struct S {
   using T = decltype([]{ return I; });
 
   template <int I>
-  decltype([]{ return I; }) f() { return {}; }
+  decltype([]{ return I; }) f();  // { dg-error "declared using local type" }
 };
 
 void a(S::T<0>*);  // { dg-error "declared using local type" }
@@ -18,4 +18,5 @@ int main() {
   b(nullptr);
   c(nullptr);
   d(nullptr);
+  S{}.f<2>()();
 }

Reply via email to