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<tree,
va_gc> *args,
tree fn_first_arg = NULL_TREE;
const vec<tree, va_gc> *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 <class T> void f()
{
int i;
[=](this T&& self){ return i; }(); // error, unrelated
}
int main() { f<int>(); }
@@ -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
commit 520217cc15315fe1cc58dff23c65bb3cdc28dc56
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Nov 29 21:51:36 2023 -0500
wildcard
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 7946f0be77b..e0cb8a1b04f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2265,6 +2265,10 @@ 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)))
+ /* We don't know what the eventual quals will be. This can happen when
+ called from build_capture_proxy for an explicit object lambda. */
+ type = NULL_TREE;
else
{
/* Set the cv qualifiers. */
@@ -11709,6 +11713,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
A<decltype(sizeof(T))>::U doesn't require 'typename'. */
if (instantiation_dependent_uneval_expression_p (expr))
{
+ dependent:
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
@@ -11883,7 +11888,11 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
if (outer_automatic_var_p (STRIP_REFERENCE_REF (expr))
&& current_function_decl
&& LAMBDA_FUNCTION_P (current_function_decl))
- type = capture_decltype (STRIP_REFERENCE_REF (expr));
+ {
+ type = capture_decltype (STRIP_REFERENCE_REF (expr));
+ if (!type)
+ goto dependent;
+ }
else if (error_operand_p (expr))
type = error_mark_node;
else if (expr == current_class_ptr)
@@ -12821,7 +12830,8 @@ capture_decltype (tree decl)
{
int quals = cp_type_quals (type);
tree obtype = TREE_TYPE (DECL_ARGUMENTS (current_function_decl));
- gcc_checking_assert (!WILDCARD_TYPE_P (non_reference (obtype)));
+ if (WILDCARD_TYPE_P (non_reference (obtype)))
+ return NULL_TREE;
if (INDIRECT_TYPE_P (obtype))
quals |= cp_type_quals (TREE_TYPE (obtype));
type = cp_build_qualified_type (type, quals);