OKAY, I figured out SOMETHING, I think this should be fine. As noted in
the comments, this might be a better way of handling the static lambda
case too. This is still a nasty hack so it should probably be done
differently, but I question if making a whole new fntype node in
tsubst_lambda_expr makes sense. On the other hand, maybe there will be
problems if a lambda is already instantiated? I'm not sure, mutating
things this way makes me uneasy though.

I don't like that pt.cc feels like it has a ton of hidden mutations,
it's really hard to follow through it. Would you agree it's in need for
cleanup or am I just not experienced enough in this area yet?

I still have to write good tests for this case and move the error
handling for unrelated object types into here, but my gut tells me this
issue should be fixed now.

Regarding the error handling, I just had a thought about it, I have a
hunch it definitely needs to go in tsubst_template_decl or
tsubst_function_decl. There might need to be more changes to determine
the actual type of the lambda in there, but everything else I've done
changes the implicit object argument to be treated more like a regular
argument, doing error handling for the object type in
tsubst_lambda_expr would be inconsistent with that.

Also, before I forget, you were totally right about just using
dependent_type_p in cp_parser_lambda_declarator_opt. It really is just
that simple.

The code below is not necessarily final, but I wanted to get your
thoughts about doing it this way given my concerns written above. Now
that this problem is out of the way, or at least almost out of the way,
I hopefully can get a version pushed out today.

Alex

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 86c95b278ba..ea2db5c0c9d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -14407,14 +14407,20 @@ tsubst_function_decl (tree t, tree args, 
tsubst_flags_t complain,
       gen_tmpl = NULL_TREE;
       argvec = NULL_TREE;
     }
-
+  /* We hack TYPE_METHOD_BASETYPE onto xobj member functions in
+     tsubst_lambda_expr to get the proper closure type here.  */
   tree closure = (lambda_fntype ? TYPE_METHOD_BASETYPE (lambda_fntype)
                   : NULL_TREE);
   tree ctx = closure ? closure : DECL_CONTEXT (t);
   bool member = ctx && TYPE_P (ctx);
 
   /* If this is a static lambda, remove the 'this' pointer added in
-     tsubst_lambda_expr now that we know the closure type.  */
+     tsubst_lambda_expr now that we know the closure type.
+     I suspect that we can just carry this information down in
+     TYPE_METHOD_BASETYPE without building the full method type in
+     tsubst_lambda_expr.  This wouldn't be ideal but neither is this.
+     Since that field isn't used for anything for static or xobj member
+     functions, it should be fine to do that.  */
   if (lambda_fntype && DECL_STATIC_FUNCTION_P (t))
     lambda_fntype = static_fn_type (lambda_fntype);
 
@@ -14490,12 +14496,12 @@ tsubst_function_decl (tree t, tree args, 
tsubst_flags_t complain,
     DECL_NAME (r) = make_conv_op_name (TREE_TYPE (type));
 
   tree parms = DECL_ARGUMENTS (t);
-  if (closure && !DECL_STATIC_FUNCTION_P (t))
+  if (closure && DECL_IOBJ_MEMBER_FUNC_P (t))
     parms = DECL_CHAIN (parms);
   parms = tsubst (parms, args, complain, t);
   for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
     DECL_CONTEXT (parm) = r;
-  if (closure && !DECL_STATIC_FUNCTION_P (t))
+  if (closure && DECL_IOBJ_MEMBER_FUNC_P (t))
     {
       tree tparm = build_this_parm (r, closure, type_memfn_quals (type));
       DECL_NAME (tparm) = closure_identifier;
@@ -19491,9 +19497,16 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
       cp_evaluated ev;
 
       /* Fix the type of 'this'.  */
-      fntype = build_memfn_type (fntype, type,
-                                type_memfn_quals (fntype),
-                                type_memfn_rqual (fntype));
+      if (DECL_IOBJ_MEMBER_FUNC_P (oldfn))
+       fntype = build_memfn_type (fntype, type,
+                                  type_memfn_quals (fntype),
+                                  type_memfn_rqual (fntype));
+      /* We don't use this field anywhere else for xobj member functions, and
+        we need a way to pass this information down.  Theres some really
+        convoluted stuff going on unfortunately, and I can only begin to
+        unravel it all.   */
+      if (DECL_XOBJ_MEMBER_FUNC_P (oldfn))
+       TYPE_METHOD_BASETYPE (fntype) = type;
       tree inst = (oldtmpl
                    ? tsubst_template_decl (oldtmpl, args, complain,
                                            fntype, tparms)

Reply via email to