On 11/27/23 00:35, waffl3x wrote: > I think this is cleaned up enough to be presentable. Bootstrapped but > not tested but I don't think I changed anything substantial. I am > running tests right now and will report if anything fails. I have not > fixed the problem in tsubst_lambda_expr that we talked about, that will > be first on my list tomorrow. While writing/cleaning up tests I had to > investigate some things, one of which is calling an overloaded > function, where one of the candidates are introduced by a using > declaration, is considered ambiguous. I haven't narrowed down the case > for this yet so I don't know if it's related to xobj member > functions/lambda with xobj parameters or not. I had to pull a few tests > because of it though. > > I did not get as much done as I would have hoped today. This really > just serves as a small progress update. Once again, todo is the issue > you raised in tsubst_lambda_expr, and fixing handling of captures when > a const xobj parameter is deduced in a lamdba call operator. > +#define DECL_IOBJ_MEMBER_FUNC_P(NODE) \ > +#define DECL_XOBJ_MEMBER_FUNC_P(NODE) \ > +#define DECL_OBJECT_MEMBER_FUNC_P(NODE) \ Let's use the full word FUNCTION in these macros for consistency with DECL_STATIC_FUNCTION_P. > @@ -6544,7 +6544,7 @@ add_candidates (tree fns, tree first_arg, const vec *args, > tree fn_first_arg = NULL_TREE; > const vec *fn_args = args; > > - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) > + if (DECL_OBJECT_MEMBER_FUNC_P (fn)) > { > /* Figure out where the object arg comes from. If this > function is a non-static member and we didn't get an Hmm, that this function explicitly pulls out the object argument into first_arg strengthens your earlier argument that we shouldn't bother trying to handle null first_arg. But let's not mess with that in this patch. > + val = handle_arg(TREE_VALUE (parm), Missing space. > /* We know an iobj parameter must be a reference. If our xobj > parameter is a pointer, we know this is not a redeclaration. > This also catches array parameters, those are pointers too. */ > if (TYPE_PTR_P (xobj_param)) > continue; Handling pointers specifically here seems unnecessary, they should be rare and will be handled by the next check for unrelated type. > dealing with a by-value xobj parameter we can procede following "proceed" > /* An operator function must either be a non-static member function > or have at least one parameter of a class, a reference to a class, > an enumeration, or a reference to an enumeration. 13.4.0.6 */ > - if (! methodp || DECL_STATIC_FUNCTION_P (decl)) > + /* This can just be DECL_STATIC_FUNCTION_P (decl) I think? */ > + if ((!methodp && !DECL_XOBJ_MEMBER_FUNC_P (decl)) > + || DECL_STATIC_FUNCTION_P (decl)) No, it also needs to be true for non-members; rather, I think it can just be if (!DECL_OBJECT_FUNCTION_P (decl)) > + if (xobj_param) > + { > + quals = TYPE_UNQUALIFIED; > + if (TYPE_REF_P (xobj_param) > + && !(cp_type_quals (TREE_TYPE (xobj_param)) & TYPE_QUAL_CONST)) > + LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1; > + } I don't think we want to mess with MUTABLE_P here. But then capture_decltype needs to be fixed to refer to the type of the object parameter rather than MUTABLE_P. Actually, I think we can do away with the MUTABLE_P flag entirely. I'm going to push a patch to do that. > - if (!LAMBDA_EXPR_STATIC_P (lambda_expr)) > + if (!LAMBDA_EXPR_STATIC_P (lambda_expr) > + && !DECL_XOBJ_MEMBER_FUNC_P (fco)) This could be if (DECL_IOBJ_MEMBER_FUNCTION_P (fco)) > - if (closure && !DECL_STATIC_FUNCTION_P (t)) > + if (closure && DECL_IOBJ_MEMBER_FUNC_P (t) && !DECL_STATIC_FUNCTION_P (t)) This shouldn't need to still check DECL_STATIC_FUNCTION_P. > + /* We don't touch a lambda's func when it's just trying to create the > + closure type. */ We need to check it somewhere, currently this crashes: template void f() { int i; [=](this T&& self){ return i; }(); // error, unrelated } int main() { f(); } > @@ -3691,18 +3691,7 @@ build_min_non_dep_op_overload (enum tree_code op, > releasing_vec args; > va_start (p, overload); > > - if (TREE_CODE (TREE_TYPE (overload)) == FUNCTION_TYPE) > - { > - fn = overload; > - if (op == ARRAY_REF) > - obj = va_arg (p, tree); > - for (int i = 0; i < nargs; i++) > - { > - tree arg = va_arg (p, tree); > - vec_safe_push (args, arg); > - } > - } Maybe change the test to !DECL_OBJECT_MEMBER_FUNC_P to avoid reordering the cases? > @@ -15402,6 +15450,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, > gcc_checking_assert (TYPE_MAIN_VARIANT (TREE_TYPE (ve)) > == TYPE_MAIN_VARIANT (type)); > SET_DECL_VALUE_EXPR (r, ve); > + if (is_capture_proxy (t)) > + type = TREE_TYPE (ve); That should have close to the same effect as the lambda_proxy_type adjustment I was talking about, since that function basically returns the TREE_TYPE of the COMPONENT_REF. But the underlying problem is that finish_non_static_data_member assumes that 'object' is '*this', for which you can trust the cv-quals; for auto&&, you can't. capture_decltype has the same problem. I'm attaching a patch to address this in both places. Jason