https://gcc.gnu.org/g:2047aa4ce2ed9976fb36e984b43864fcd6f3a65d

commit r16-970-g2047aa4ce2ed9976fb36e984b43864fcd6f3a65d
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu May 29 12:36:23 2025 -0400

    c++: xobj lambda 'this' capture [PR113563]
    
    Various places were still making assumptions that we could get to the 'this'
    capture through current_class_ref in a lambda op(), which is incorrect for
    an explicit object op().
    
            PR c++/113563
    
    gcc/cp/ChangeLog:
    
            * lambda.cc (build_capture_proxy): Check pointerness of the
            member, not the proxy type.
            (lambda_expr_this_capture): Don't assume current_class_ref.
            (nonlambda_method_basetype): Likewise.
            * semantics.cc (finish_non_static_data_member): Don't assume
            TREE_TYPE (object) is set.
            (finish_this_expr): Check current_class_type for lambda,
            not current_class_ref.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp23/explicit-obj-lambda16.C: New test.

Diff:
---
 gcc/cp/lambda.cc                                   | 12 +++----
 gcc/cp/semantics.cc                                | 17 ++++------
 gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C | 39 ++++++++++++++++++++++
 3 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index a2bed9fb36aa..34c7defb6049 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -442,7 +442,7 @@ build_capture_proxy (tree member, tree init)
 
   type = lambda_proxy_type (object);
 
-  if (name == this_identifier && !INDIRECT_TYPE_P (type))
+  if (name == this_identifier && !INDIRECT_TYPE_P (TREE_TYPE (member)))
     {
       type = build_pointer_type (type);
       type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
@@ -921,8 +921,9 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
   else
     {
       /* To make sure that current_class_ref is for the lambda.  */
-      gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
-                 == LAMBDA_EXPR_CLOSURE (lambda));
+      gcc_assert (!current_class_ref
+                 || (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+                     == LAMBDA_EXPR_CLOSURE (lambda)));
 
       result = this_capture;
 
@@ -1037,12 +1038,9 @@ current_nonlambda_function (void)
 tree
 nonlambda_method_basetype (void)
 {
-  if (!current_class_ref)
-    return NULL_TREE;
-
   tree type = current_class_type;
   if (!type || !LAMBDA_TYPE_P (type))
-    return type;
+    return current_class_ref ? type : NULL_TREE;
 
   while (true)
     {
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 241f2730878b..1279d78b1868 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2770,7 +2770,7 @@ finish_non_static_data_member (tree decl, tree object, 
tree qualifying_scope,
       else if (PACK_EXPANSION_P (type))
        /* Don't bother trying to represent this.  */
        type = NULL_TREE;
-      else if (WILDCARD_TYPE_P (TREE_TYPE (object)))
+      else if (!TREE_TYPE (object) || WILDCARD_TYPE_P (TREE_TYPE (object)))
        /* We don't know what the eventual quals will be, so punt until
           instantiation time.
 
@@ -3605,16 +3605,11 @@ finish_this_expr (void)
 {
   tree result = NULL_TREE;
 
-  if (current_class_ptr)
-    {
-      tree type = TREE_TYPE (current_class_ref);
-
-      /* In a lambda expression, 'this' refers to the captured 'this'.  */
-      if (LAMBDA_TYPE_P (type))
-        result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type), true);
-      else
-        result = current_class_ptr;
-    }
+  if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+    result = (lambda_expr_this_capture
+             (CLASSTYPE_LAMBDA_EXPR (current_class_type), /*add*/true));
+  else if (current_class_ptr)
+    result = current_class_ptr;
 
   if (result)
     /* The keyword 'this' is a prvalue expression.  */
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C
new file mode 100644
index 000000000000..69936388969c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C
@@ -0,0 +1,39 @@
+// PR c++/113563
+// { dg-do compile { target c++23 } }
+
+struct S {
+  int x_;
+  void f() {
+    [this](this auto) {
+      this->x_ = 42;
+      return this;
+    }();
+  }
+};
+
+struct R {
+  int x;
+
+  auto foo() {
+    return [*this](this auto &self) {
+      this->x = 4;
+    };
+  }
+};
+
+
+struct A
+{
+    int n;
+    void fun()
+    {
+        auto _ = [&](this auto self) { return n; };
+    }
+};
+
+struct B {
+  int i = 42;
+  int foo() {
+    return [this](this auto &&self) { auto p = &i; return *p; }();
+  }
+};

Reply via email to