aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.cc
diff options
context:
space:
mode:
authorwaffl3x <waffl3x@protonmail.com>2024-01-07 00:53:32 +0000
committerJason Merrill <jason@redhat.com>2024-01-09 15:59:04 -0500
commit07d09f0af100a9873982fba663800d87bfd73585 (patch)
treec6895f013844012394f132c662211fd1c324591c /gcc/cp/parser.cc
parentf8bf6a69e260a5f1aa0dbf89a6e4bcdf1a24af5d (diff)
downloadgcc-07d09f0af100a9873982fba663800d87bfd73585.zip
gcc-07d09f0af100a9873982fba663800d87bfd73585.tar.gz
gcc-07d09f0af100a9873982fba663800d87bfd73585.tar.bz2
c++: P0847R7 (deducing this) - xobj lambdas. [PR102609]
This implements support for xobj lambdas. There are extensive tests included, but not exhaustive. Dependent lambdas should work and have been tested lightly, but we need more exhaustive tests for them. PR c++/102609 gcc/cp/ChangeLog: PR c++/102609 C++23 P0847R7 (deducing this) - xobj lambdas. * lambda.cc (build_capture_proxy): Don't fold direct object types. * parser.cc (cp_parser_lambda_declarator_opt): Handle xobj lambdas, diagnostics. Comments also updated. * pt.cc (tsubst_function_decl): Handle xobj lambdas. Check object type of xobj lambda call operator, diagnose incorrect types. (tsubst_lambda_expr): Update comment. * semantics.cc (finish_decltype_type): Also consider by-value object parameter qualifications. gcc/testsuite/ChangeLog: PR c++/102609 C++23 P0847R7 (deducing this) - xobj lambdas. * g++.dg/cpp23/explicit-obj-diagnostics8.C: New test. * g++.dg/cpp23/explicit-obj-lambda1.C: New test. * g++.dg/cpp23/explicit-obj-lambda10.C: New test. * g++.dg/cpp23/explicit-obj-lambda11.C: New test. * g++.dg/cpp23/explicit-obj-lambda12.C: New test. * g++.dg/cpp23/explicit-obj-lambda13.C: New test. * g++.dg/cpp23/explicit-obj-lambda2.C: New test. * g++.dg/cpp23/explicit-obj-lambda3.C: New test. * g++.dg/cpp23/explicit-obj-lambda4.C: New test. * g++.dg/cpp23/explicit-obj-lambda5.C: New test. * g++.dg/cpp23/explicit-obj-lambda6.C: New test. * g++.dg/cpp23/explicit-obj-lambda7.C: New test. * g++.dg/cpp23/explicit-obj-lambda8.C: New test. * g++.dg/cpp23/explicit-obj-lambda9.C: New test. Signed-off-by: Waffl3x <waffl3x@protonmail.com>
Diffstat (limited to 'gcc/cp/parser.cc')
-rw-r--r--gcc/cp/parser.cc84
1 files changed, 79 insertions, 5 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index b0c08cf..d71522d 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -11874,8 +11874,12 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
else if (cxx_dialect < cxx23)
omitted_parms_loc = cp_lexer_peek_token (parser->lexer)->location;
- /* In the decl-specifier-seq of the lambda-declarator, each
- decl-specifier shall either be mutable or constexpr. */
+ /* [expr.prim.lambda.general]
+ lambda-specifier:
+ consteval, constexpr, mutable, static
+ [4] A lambda-specifier-seq shall contain at most one of each
+ lambda-specifier and shall not contain both constexpr and consteval.
+ The lambda-specifier-seq shall not contain both mutable and static. */
int declares_class_or_enum;
if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
cp_parser_decl_specifier_seq (parser,
@@ -11890,13 +11894,83 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
"%<-std=gnu++2b%>");
omitted_parms_loc = UNKNOWN_LOCATION;
}
-
- if (lambda_specs.storage_class == sc_mutable)
+ /* Peek at the params, see if we have an xobj parameter. */
+ if (param_list && TREE_PURPOSE (param_list) == this_identifier)
+ {
+ quals = TYPE_UNQUALIFIED;
+ /* We still need grokdeclarator to see that this is an xobj function
+ and finish the rest of the work, don't mutate it. */
+ tree const xobj_param = TREE_VALUE (param_list);
+ tree const param_type = TREE_TYPE (xobj_param);
+ /* [expr.prim.lambda.closure-5]
+ Given a lambda with a lambda-capture, the type of the explicit object
+ parameter, if any, of the lambda's function call operator (possibly
+ instantiated from a function call operator template) shall be either:
+ -- the closure type,
+ -- a class type derived from the closure type, or
+ -- a reference to a possibly cv-qualified such type. */
+ bool const unrelated_with_captures
+ = (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
+ || LAMBDA_EXPR_CAPTURE_LIST (lambda_expr))
+ /* Since a lambda's type is anonymous, we can assume an xobj
+ parameter is unrelated to the closure if it is non-dependent.
+ If it is dependent we handle it at instantiation time. */
+ && !WILDCARD_TYPE_P (non_reference (param_type));
+ if (unrelated_with_captures)
+ {
+ error_at (DECL_SOURCE_LOCATION (xobj_param),
+ "a lambda with captures may not have an explicit object "
+ "parameter of an unrelated type");
+ LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = NULL_TREE;
+ }
+
+ /* [expr.prim.lambda.general-4]
+ If the lambda-declarator contains an explicit object parameter
+ ([dcl.fct]), then no lambda-specifier in the lambda-specifier-seq
+ shall be mutable or static. */
+ if (lambda_specs.storage_class == sc_mutable)
+ {
+ auto_diagnostic_group d;
+ error_at (lambda_specs.locations[ds_storage_class],
+ "%<mutable%> lambda specifier "
+ "with explicit object parameter");
+ /* Tell the user how to do what they probably meant, maybe fixits
+ would be appropriate later? */
+ if (unrelated_with_captures)
+ /* The following hints don't make sense when we already have an
+ unrelated type with captures, don't emit them. */;
+ else if (!TYPE_REF_P (param_type))
+ inform (DECL_SOURCE_LOCATION (xobj_param),
+ "the passed in closure object will not be mutated because "
+ "it is taken by value");
+ else if (TYPE_READONLY (TREE_TYPE (param_type)))
+ inform (DECL_SOURCE_LOCATION (xobj_param),
+ "declare the explicit object parameter as non-const "
+ "reference instead");
+ else
+ inform (DECL_SOURCE_LOCATION (xobj_param),
+ "explicit object parameter is already a mutable "
+ "reference");
+ }
+ else if (lambda_specs.storage_class == sc_static)
+ {
+ auto_diagnostic_group d;
+ error_at (lambda_specs.locations[ds_storage_class],
+ "%<static%> lambda specifier "
+ "with explicit object parameter");
+ inform (DECL_SOURCE_LOCATION (xobj_param),
+ "explicit object parameter declared here");
+ }
+ }
+ else if (lambda_specs.storage_class == sc_mutable)
{
quals = TYPE_UNQUALIFIED;
}
else if (lambda_specs.storage_class == sc_static)
{
+ /* [expr.prim.lambda.general-4]
+ If the lambda-specifier-seq contains static, there shall be no
+ lambda-capture. */
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
|| LAMBDA_EXPR_CAPTURE_LIST (lambda_expr))
error_at (lambda_specs.locations[ds_storage_class],
@@ -12021,7 +12095,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
{
DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
DECL_ARTIFICIAL (fco) = 1;
- if (!LAMBDA_EXPR_STATIC_P (lambda_expr))
+ if (DECL_IOBJ_MEMBER_FUNCTION_P (fco))
/* Give the object parameter a different name. */
DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier;
DECL_SET_LAMBDA_FUNCTION (fco, true);