From patchwork Thu Aug 31 06:46:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: waffl3x X-Patchwork-Id: 137233 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c792:0:b0:3f2:4152:657d with SMTP id b18csp61611vqu; Wed, 30 Aug 2023 23:48:05 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHX3uj9tsBGYTImRkL15sEqkQHBodvctkT4Yvfj944U2b6n+Ylw4QX+lV7H2zOSPrAxUV9t X-Received: by 2002:aa7:cf09:0:b0:522:3d36:ff27 with SMTP id a9-20020aa7cf09000000b005223d36ff27mr3474273edy.31.1693464485054; Wed, 30 Aug 2023 23:48:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693464485; cv=none; d=google.com; s=arc-20160816; b=T2/x7jxlhxsQkd3lExBmrawJq9tAhxPSThThVR9ZvzaOwTrbUPdcEeRrDDFiclkgep pHvK5FYHvPgETIMwfblMTRtBXjWfrFiU1C4eOMgcftM0MzlGabheBRHnw10tnr3o8OZL 6O+WWvN1PDi0/lWzDlpB3kafMfULAVl+60DIUTALCL8RK30b8lPtMHmzKYVRsn7LZjnG iSbHTpZyVuOVRbT9YUVpcyFKZPmqsorbDK3/SOrZ3721JG18dprGb9R+cTc/3omfmnVI rjkDmJFQpoOQbBJbcwkdDvQt3q/Nk6lolKpo05M5kx81hI/V3JRvE5Ir0ef5GLguElDb aL+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:mime-version :feedback-id:message-id:subject:cc:to:date:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=HMntVZMxgX1/bi9GBKOCEtHNs4bFBpajKnS/6f5Ac+g=; fh=0p8yKbnNQv1vJpVykT5ewNhirQsYfOUF6tpVwgDjENs=; b=w6ABB3OQ+MDTMgK296bn/IeIf0hhL1HwzbwuPxTeDClFEVlKgLSomXKo83rWmvZWqg 3c4TnTQ1mN9R0HRKtEFJf5wqfdd+iQkN1clWYkfQC+bXtXYX+cREnzISKXgNHMkQqK76 TlrbT4U8HnnuPxZ4cfaeVSNeqHEyCxs8sIzYUwhqwsC16dOOigxT5anoBXka1z/r18l/ RPZhzWHbYROzxe6IDviYBugW/f1Vbf15o9FFDJWWiRKjxY0L1vpGUItASpH51tzBLT9m Lwg1ckLqwCIBEWyDKKjgIzkiy2J43eYACi0+EZ/7kF2i9ttZBi0JBDH8olnqw2xePv2J UmGQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Sh4jGKxh; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id d6-20020aa7ce06000000b0052a3cffeeecsi591399edv.599.2023.08.30.23.48.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Aug 2023 23:48:05 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Sh4jGKxh; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BE5DD3858418 for ; Thu, 31 Aug 2023 06:48:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BE5DD3858418 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693464483; bh=HMntVZMxgX1/bi9GBKOCEtHNs4bFBpajKnS/6f5Ac+g=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=Sh4jGKxh4K3qlJScmqowoStLL6mCa+8Y68iZA3pzIly7HLO4WcmW2/5KjGA4Rn1jU Rlb55IA0DbAYtYXzpGGRCZCTvq3L6JMFWPo8g9h4dbt86PiFii2yU5ICRtCXxtvzr7 RrCr69ugwWV13HT8XjWOMcSIjUE/HH0+Y8yOTFH8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-4318.protonmail.ch (mail-4318.protonmail.ch [185.70.43.18]) by sourceware.org (Postfix) with ESMTPS id DA15B3858D20 for ; Thu, 31 Aug 2023 06:47:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DA15B3858D20 Date: Thu, 31 Aug 2023 06:46:58 +0000 To: waffl3x Cc: "gcc-patches@gcc.gnu.org" Subject: [PATCH 2/2] c++: Extended diagnostics for P0847R7 (Deducing This) [PR102609] Message-ID: <1xDDGk_jeMvdx0yPQAJHLLCzkYYCTdAk2f11ONoe0TAT4MBfhz7MeJnVZcuTwFFR7_CtGNiknplSXIjf8sjogjaYbJNmgXh9M60EC7-DgN0=@protonmail.com> Feedback-ID: 14591686:user:proton MIME-Version: 1.0 X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: waffl3x via Gcc-patches From: waffl3x Reply-To: waffl3x Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775726215822138189 X-GMAIL-MSGID: 1775726215822138189 Tested and Bootstrapped and tested on x86_64-linux with no regressions. There's a few test cases that are not properly diagnosed yet, but everything that is known to fail is marked as xfail. When I tested the new tests I got 390 expected passes and 64 expected failures. Alright, I have a flight to catch, hopefully my patch is at least satisfactory. There's a few thing's I'm not totally happy with so I will be happy to address any criticism as soon as I am able. Thanks again to everyone who helped me prepare this, I probably would have given up otherwise. From d82a34432364b391abde44a23ceacb3c398a519d Mon Sep 17 00:00:00 2001 From: Waffl3x Date: Thu, 31 Aug 2023 02:13:52 -0400 Subject: [PATCH 2/2] P0847R7 (deducing this) Extended diagnostics gcc/cp/ChangeLog: * cp-tree.h (TFF_XOBJ_FUNC): new flag to identify that an explicit object member function's parameters are being printed * decl.cc (grokdeclarator): diagnose type declarations using 'this', diagnose function declarations using this (grokparms): diagnose an explicit object parameter with a default argument * error.cc (dump_function_decl): prevent explicit object member functions from being pretty printed with 'static', communicate to dump_parameters that the current function is an explicit object member function (dump_parameters): pretty print the explicit object parameter with a leading 'this' (function_category): support reporting that the current context is within an explicit object member function * parser.cc (cp_parser_decl_specifier_seq): diagnose uses of 'this' when it is not the first specifier of a decl-specifier-seq (cp_parser_parameter_declaration_list): diagnose when an explicit object parameter is not the first parameter * semantics.cc (finish_this_expr): diagnose when 'this' is used in the body of an explicit object member function gcc/testsuite/ChangeLog: * g++.dg/cpp23/explicit-object-param-ill-formed1.C: New test. * g++.dg/cpp23/explicit-object-param-ill-formed2.C: New test. * g++.dg/cpp23/explicit-object-param-ill-formed3.C: New test. * g++.dg/cpp23/explicit-object-param-ill-formed4.C: New test. * g++.dg/cpp23/explicit-object-param-ill-formed5.C: New test. * g++.dg/cpp23/explicit-object-param-ill-formed6.C: New test. * g++.dg/cpp23/explicit-object-param-no-cxx23.C: New test. Signed-off-by: Waffl3x --- gcc/cp/cp-tree.h | 5 +- gcc/cp/decl.cc | 71 +++++++++ gcc/cp/error.cc | 12 +- gcc/cp/parser.cc | 62 ++++++++ gcc/cp/semantics.cc | 24 ++- .../cpp23/explicit-object-param-ill-formed1.C | 141 ++++++++++++++++++ .../cpp23/explicit-object-param-ill-formed2.C | 25 ++++ .../cpp23/explicit-object-param-ill-formed3.C | 102 +++++++++++++ .../cpp23/explicit-object-param-ill-formed4.C | 42 ++++++ .../cpp23/explicit-object-param-ill-formed5.C | 9 ++ .../cpp23/explicit-object-param-ill-formed6.C | 22 +++ .../cpp23/explicit-object-param-no-cxx23.C | 7 + 12 files changed, 517 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed1.C create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed2.C create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed3.C create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed4.C create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed5.C create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed6.C create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-object-param-no-cxx23.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3aca23da105..325d0fb3ca0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6111,7 +6111,9 @@ enum auto_deduction_context identical to their defaults. TFF_NO_TEMPLATE_BINDINGS: do not print information about the template arguments for a function template specialization. - TFF_POINTER: we are printing a pointer type. */ + TFF_POINTER: we are printing a pointer type. + TFF_XOBJ_FUNC: we are printing an explicit object member function's + parameters */ #define TFF_PLAIN_IDENTIFIER (0) #define TFF_SCOPE (1) @@ -6129,6 +6131,7 @@ enum auto_deduction_context #define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS (1 << 12) #define TFF_NO_TEMPLATE_BINDINGS (1 << 13) #define TFF_POINTER (1 << 14) +#define TFF_XOBJ_FUNC (1 << 15) /* These constants can be used as bit flags to control strip_typedefs. diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index a6d0cfb0ecc..da9235ced30 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -13080,6 +13080,67 @@ grokdeclarator (const cp_declarator *declarator, tree xobj_parm = get_xobj_parm (declarator->u.function.parameters); is_xobj_member_function = xobj_parm; + if (!xobj_parm) + /* early escape */; + else if (decl_context == TYPENAME) + { + bool ptr_type = true; + if (!declarator->declarator) + { + error_at (DECL_SOURCE_LOCATION (xobj_parm), + "a function type cannot " + "have an explicit object parameter"); + ptr_type = false; + } + else if (declarator->declarator->kind == cdk_pointer) + error_at (DECL_SOURCE_LOCATION (xobj_parm), + "a function pointer type cannot " + "have an explicit object parameter"); + else if (declarator->declarator->kind == cdk_ptrmem) + error_at (DECL_SOURCE_LOCATION (xobj_parm), + "a member function pointer type " + "cannot have an explicit object parameter"); + + if (ptr_type) + inform (DECL_SOURCE_LOCATION (xobj_parm), + "the type of a pointer to explicit object member " + "function is a regular pointer to function type"); + else + inform (DECL_SOURCE_LOCATION (xobj_parm), + "the type of an explicit object " + "member function is a regular function type"); + /* ideally we can synthesize the correct syntax + and display it, perhaps it can be added later */ + } + /* I am unsure if this is the best way of determining this + but I don't like it either way, it should be improved on*/ + else if (decl_context == NORMAL + && (in_namespace + || !declarator->declarator->u.id.qualifying_scope)) + error_at (DECL_SOURCE_LOCATION (xobj_parm), + "a free function cannot have " + "an explicit object parameter"); + else /* if (xobj_parm) */ + { + if (virtualp) + { + error_at (declspecs->locations[ds_virtual], + "an explicit object member function cannot be " + "%"); + inform (DECL_SOURCE_LOCATION (xobj_parm), + "explicit object parameter declared here"); + virtualp = false; + } + else if (staticp >= 2) + { + error_at (declspecs->locations[ds_storage_class], + "an explicit object member function cannot be " + "%"); + inform (DECL_SOURCE_LOCATION (xobj_parm), + "explicit object parameter declared here"); + } + } + tree arg_types; int funcdecl_p; @@ -15156,6 +15217,11 @@ grokparms (tree parmlist, tree *parms) tree parm; int any_error = 0; + /* If any parm other than the first is an xobj parm, it should have + been diagnosed already, so don't bother diagnosing a default argument + on any other parms */ + bool first_parm = true; + for (parm = parmlist; parm != NULL_TREE; parm = TREE_CHAIN (parm)) { tree type = NULL_TREE; @@ -15170,6 +15236,11 @@ grokparms (tree parmlist, tree *parms) any_error = 1; continue; } + if (first_parm && !any_error && DECL_PARM_XOBJ_FLAG (decl) && init) + error_at (DECL_SOURCE_LOCATION (decl), + "an explicit object parameter " + "may not have a default argument"); + first_parm = false; type = TREE_TYPE (decl); if (VOID_TYPE_P (type)) diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc index 8a5219a68a1..09466edf87e 100644 --- a/gcc/cp/error.cc +++ b/gcc/cp/error.cc @@ -1790,7 +1790,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) if (flags & TFF_DECL_SPECIFIERS) { - if (DECL_STATIC_FUNCTION_P (t)) + if (DECL_STATIC_FUNCTION_P (t) && !DECL_IS_XOBJ_MEMBER_FUNC (t)) pp_cxx_ws_string (pp, "static"); else if (DECL_VIRTUAL_P (t)) pp_cxx_ws_string (pp, "virtual"); @@ -1835,7 +1835,9 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) if (!(flags & TFF_NO_FUNCTION_ARGUMENTS)) { - dump_parameters (pp, parmtypes, flags); + dump_parameters (pp, parmtypes, + DECL_IS_XOBJ_MEMBER_FUNC (t) ? TFF_XOBJ_FUNC | flags + : flags); if (TREE_CODE (fntype) == METHOD_TYPE) { @@ -1914,6 +1916,8 @@ dump_parameters (cxx_pretty_printer *pp, tree parmtypes, int flags) for (first = 1; parmtypes != void_list_node; parmtypes = TREE_CHAIN (parmtypes)) { + if (first && flags & TFF_XOBJ_FUNC) + pp_string (pp, "this "); if (!first) pp_separate_with_comma (pp); first = 0; @@ -3683,7 +3687,9 @@ function_category (tree fn) if (DECL_LANG_SPECIFIC (STRIP_TEMPLATE (fn)) && DECL_FUNCTION_MEMBER_P (fn)) { - if (DECL_STATIC_FUNCTION_P (fn)) + if (DECL_IS_XOBJ_MEMBER_FUNC (fn)) + return G_("In explicit object member function %qD"); + else if (DECL_STATIC_FUNCTION_P (fn)) return _("In static member function %qD"); else if (DECL_COPY_CONSTRUCTOR_P (fn)) return _("In copy constructor %qD"); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index ed5dcbde3ed..2bd276435df 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -15803,6 +15803,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* Assume no class or enumeration type is declared. */ *declares_class_or_enum = 0; + cp_token *first_non_attribute = NULL; /* Keep reading specifiers until there are no more to read. */ while (true) { @@ -15875,6 +15876,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser, decl_specs->locations[ds_attribute] = token->location; continue; } + /* to properly place fixit diagnostic for xobj parm specifier */ + if (!first_non_attribute) + first_non_attribute = token; /* Special case for xobj parm, doesn't really belong up here (it applies to parm decls and those are mostly handled below the following specifiers) but I intend to refactor this function @@ -15883,6 +15887,27 @@ cp_parser_decl_specifier_seq (cp_parser* parser, if (token->keyword == RID_THIS) { cp_lexer_consume_token (parser->lexer); + if (token != first_non_attribute) + { + /* let set_and_check_decl_spec_loc + report the diagnostic for duplicates */ + if (decl_specs->locations[ds_this] == 0) + { + gcc_rich_location richloc (token->location); + /* we can do better than this, it doesn't show a full + rewrite when there are keywords between it and the start + 'f(const this S s)' for example, but it will properly + rewrite 'f(S this & s)' + Also fails to give a proper diagnostic + for 'f(S& this s)' this case*/ + richloc.add_fixit_insert_before + (first_non_attribute->location, "this "); + richloc.add_fixit_remove (); + error_at (&richloc, + "% must be the first specifier " + "in a parameter declaration"); + } + } set_and_check_decl_spec_loc (decl_specs, ds_this, token); continue; } @@ -24833,6 +24858,10 @@ cp_parser_parameter_declaration_list (cp_parser* parser, = parser->in_unbraced_linkage_specification_p; parser->in_unbraced_linkage_specification_p = false; + /* Check if anything but the first parm is declared as an xobj parm. + I want to come back and refactor this with a better solution later. */ + cp_parameter_declarator *first_parm = nullptr; + /* Look for more parameters. */ while (true) { @@ -24845,6 +24874,39 @@ cp_parser_parameter_declaration_list (cp_parser* parser, = cp_parser_parameter_declaration (parser, flags, /*template_parm_p=*/false, &parenthesized_p); + if (!first_parm) + first_parm = parameter; + /* this has to go here (as opposed to grokdeclarator) + to emit the best possible diagnostics */ + if (parameter && first_parm != parameter + && parameter->decl_specifiers.locations[ds_this] != 0) + { + gcc_rich_location bad_this + (parameter->decl_specifiers.locations[ds_this]); + /* this is unneccesary if the order of fixit/inform/error + does not matter, but I am under the impression that it does */ + auto emit_error = [&bad_this]() + { + error_at (&bad_this, + "Only the first parameter of a member function " + "can be declared as an explicit object parameter"); + }; + if (first_parm->decl_specifiers.locations[ds_this] == 0) + { + /* We should probably check if the type of the first parm would + be sane as an xobj parm before making this suggestion */ + /* I couldn't figure out how to get this quite the way I wanted. + It should definitely be improved on */ + bad_this.add_fixit_insert_before (first_parm->loc, "this "); + emit_error (); + } + else + { + emit_error (); + inform (first_parm->loc, + "Valid explicit object parameter declared here"); + } + } /* We don't know yet if the enclosing context is unavailable or deprecated, so wait and deal with it in grokparms if appropriate. */ diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index e810bc41fc8..23480dd0ecf 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3063,7 +3063,29 @@ finish_this_expr (void) return rvalue (result); tree fn = current_nonlambda_function (); - if (fn && DECL_STATIC_FUNCTION_P (fn)) + if (fn && DECL_IS_XOBJ_MEMBER_FUNC (fn)) + { + /* I want to move this to an earlier + function to have access to the full expr */ + tree xobj_parm = FUNCTION_DECL_CHECK (fn)->function_decl.arguments; + tree parm_name = DECL_MINIMAL_CHECK (xobj_parm)->decl_minimal.name; + if (parm_name) + { + error ("% is unavailable for explicit object member " + "functions"); + inform (DECL_SOURCE_LOCATION (xobj_parm), + "use explicit object parameter %qD instead", + parm_name); + } + else + { + error ("% is unavailable for explicit object member " + "functions"); + inform (DECL_SOURCE_LOCATION (xobj_parm), + "name and use the explicit object parameter instead"); + } + } + else if (fn && DECL_STATIC_FUNCTION_P (fn)) error ("% is unavailable for static member functions"); else if (fn && processing_contract_condition && DECL_CONSTRUCTOR_P (fn)) error ("invalid use of % before it is valid"); diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed1.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed1.C new file mode 100644 index 00000000000..d9924ced21a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed1.C @@ -0,0 +1,141 @@ +// P0847R7 +// { dg-do compile { target c++23 } } + +// I want to do better than what these currently are, but where the code is currently makes it impossible +// they should at least be grouped or something + +// should at least note to apply qualifiers to the explicit object parameter instead (fixit should be possible) + +struct S { + void f_value_0(this S) const; // { dg-error "cannot have cv-qualifier" } + void f_value_1(this S) volatile; // { dg-error "cannot have cv-qualifier" } + void f_value_2(this S) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_value_3(this S) &; // { dg-error "cannot have ref-qualifier" } + void f_value_4(this S) &&; // { dg-error "cannot have ref-qualifier" } + void f_value_5(this S) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_value_6(this S) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_value_7(this S) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_value_8(this S) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_value_9(this S) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_value_A(this S) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_ref_0(this S&) const; // { dg-error "cannot have cv-qualifier" } + void f_ref_1(this S&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_ref_2(this S&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_ref_3(this S&) &; // { dg-error "cannot have ref-qualifier" } + void f_ref_4(this S&) &&; // { dg-error "cannot have ref-qualifier" } + void f_ref_5(this S&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_ref_6(this S&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_ref_7(this S&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_ref_8(this S&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_ref_9(this S&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_ref_A(this S&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_refref_0(this S&&) const; // { dg-error "cannot have cv-qualifier" } + void f_refref_1(this S&&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_refref_2(this S&&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_refref_3(this S&&) &; // { dg-error "cannot have ref-qualifier" } + void f_refref_4(this S&&) &&; // { dg-error "cannot have ref-qualifier" } + void f_refref_5(this S&&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_refref_6(this S&&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_refref_7(this S&&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_refref_8(this S&&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_refref_9(this S&&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_refref_A(this S&&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_cref_0(this S const&) const; // { dg-error "cannot have cv-qualifier" } + void f_cref_1(this S const&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_cref_2(this S const&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_cref_3(this S const&) &; // { dg-error "cannot have ref-qualifier" } + void f_cref_4(this S const&) &&; // { dg-error "cannot have ref-qualifier" } + void f_cref_5(this S const&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cref_6(this S const&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cref_7(this S const&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cref_8(this S const&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cref_9(this S const&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cref_A(this S const&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_crefref_0(this S const&&) const; // { dg-error "cannot have cv-qualifier" } + void f_crefref_1(this S const&&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_crefref_2(this S const&&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_crefref_3(this S const&&) &; // { dg-error "cannot have ref-qualifier" } + void f_crefref_4(this S const&&) &&; // { dg-error "cannot have ref-qualifier" } + void f_crefref_5(this S const&&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_crefref_6(this S const&&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_crefref_7(this S const&&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_crefref_8(this S const&&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_crefref_9(this S const&&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_crefref_A(this S const&&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_vref_0(this S volatile&) const; // { dg-error "cannot have cv-qualifier" } + void f_vref_1(this S volatile&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_vref_2(this S volatile&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_vref_3(this S volatile&) &; // { dg-error "cannot have ref-qualifier" } + void f_vref_4(this S volatile&) &&; // { dg-error "cannot have ref-qualifier" } + void f_vref_5(this S volatile&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vref_6(this S volatile&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vref_7(this S volatile&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vref_8(this S volatile&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vref_9(this S volatile&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vref_A(this S volatile&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_vrefref_0(this S volatile&&) const; // { dg-error "cannot have cv-qualifier" } + void f_vrefref_1(this S volatile&&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_vrefref_2(this S volatile&&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_vrefref_3(this S volatile&&) &; // { dg-error "cannot have ref-qualifier" } + void f_vrefref_4(this S volatile&&) &&; // { dg-error "cannot have ref-qualifier" } + void f_vrefref_5(this S volatile&&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vrefref_6(this S volatile&&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vrefref_7(this S volatile&&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vrefref_8(this S volatile&&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vrefref_9(this S volatile&&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_vrefref_A(this S volatile&&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_cvref_0(this S const volatile&) const; // { dg-error "cannot have cv-qualifier" } + void f_cvref_1(this S const volatile&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_cvref_2(this S const volatile&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_cvref_3(this S const volatile&) &; // { dg-error "cannot have ref-qualifier" } + void f_cvref_4(this S const volatile&) &&; // { dg-error "cannot have ref-qualifier" } + void f_cvref_5(this S const volatile&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvref_6(this S const volatile&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvref_7(this S const volatile&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvref_8(this S const volatile&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvref_9(this S const volatile&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvref_A(this S const volatile&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void f_cvrefref_0(this S const volatile&&) const; // { dg-error "cannot have cv-qualifier" } + void f_cvrefref_1(this S const volatile&&) volatile; // { dg-error "cannot have cv-qualifier" } + void f_cvrefref_2(this S const volatile&&) const volatile; // { dg-error "cannot have cv-qualifier" } + void f_cvrefref_3(this S const volatile&&) &; // { dg-error "cannot have ref-qualifier" } + void f_cvrefref_4(this S const volatile&&) &&; // { dg-error "cannot have ref-qualifier" } + void f_cvrefref_5(this S const volatile&&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvrefref_6(this S const volatile&&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvrefref_7(this S const volatile&&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvrefref_8(this S const volatile&&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvrefref_9(this S const volatile&&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void f_cvrefref_A(this S const volatile&&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + template void d_templ_0(this Self&&) const; // { dg-error "cannot have cv-qualifier" } + template void d_templ_1(this Self&&) volatile; // { dg-error "cannot have cv-qualifier" } + template void d_templ_2(this Self&&) const volatile; // { dg-error "cannot have cv-qualifier" } + template void d_templ_3(this Self&&) &; // { dg-error "cannot have ref-qualifier" } + template void d_templ_4(this Self&&) &&; // { dg-error "cannot have ref-qualifier" } + template void d_templ_5(this Self&&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + template void d_templ_6(this Self&&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + template void d_templ_7(this Self&&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + template void d_templ_8(this Self&&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + template void d_templ_9(this Self&&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + template void d_templ_A(this Self&&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + + void d_auto_0(this auto&&) const; // { dg-error "cannot have cv-qualifier" } + void d_auto_1(this auto&&) volatile; // { dg-error "cannot have cv-qualifier" } + void d_auto_2(this auto&&) const volatile; // { dg-error "cannot have cv-qualifier" } + void d_auto_3(this auto&&) &; // { dg-error "cannot have ref-qualifier" } + void d_auto_4(this auto&&) &&; // { dg-error "cannot have ref-qualifier" } + void d_auto_5(this auto&&) const &; // { dg-error "cannot have (ref|cv)-qualifier" } + void d_auto_6(this auto&&) const &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void d_auto_7(this auto&&) volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void d_auto_8(this auto&&) volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } + void d_auto_9(this auto&&) const volatile &; // { dg-error "cannot have (ref|cv)-qualifier" } + void d_auto_A(this auto&&) const volatile &&; // { dg-error "cannot have (ref|cv)-qualifier" } +}; \ No newline at end of file diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed2.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed2.C new file mode 100644 index 00000000000..f55c43cc374 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed2.C @@ -0,0 +1,25 @@ +// P0847R7 +// { dg-do compile { target c++23 } } + +// diagnose some incorrect uses of 'this' keyword in declarations and definitions + +using func_type = void(this int); // { dg-line func_type_line } +// { dg-error "a function type cannot have an explicit object parameter" "" { target *-*-* } func_type_line } +// { dg-note "the type of an explicit object member function is a regular function type" "" { target *-*-* } func_type_line } + +using func_ptr_type = void(*)(this int); // { dg-line func_ptr_type_line } +// { dg-error "a function pointer type cannot have an explicit object parameter" "" { target *-*-* } func_ptr_type_line } +// { dg-note "the type of a pointer to explicit object member function is a regular pointer to function type" "" { target *-*-* } func_ptr_type_line } + +struct S { + static void f(this S) {} // { dg-line static_member_func_line } +}; +// { dg-error "an explicit object member function cannot be 'static'" "" { target *-*-* } static_member_func_line } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } static_member_func_line } + +using mem_func_type = void (S::*)(this S&); // { dg-line mem_func_type_line } +// { dg-error "a member function pointer type cannot have an explicit object parameter" "" { target *-*-* } mem_func_type_line } +// { dg-note "the type of a pointer to explicit object member function is a regular pointer to function type" "" { target *-*-* } mem_func_type_line } + +void f(this int); // { dg-error "a free function cannot have an explicit object parameter" } +void f(this int) {} // { dg-error "a free function cannot have an explicit object parameter" } \ No newline at end of file diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed3.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed3.C new file mode 100644 index 00000000000..8fca102d0f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed3.C @@ -0,0 +1,102 @@ +// P0847R7 +// { dg-do compile { target c++23 } } +// { dg-additional-options -Woverloaded-virtual } + +// invalid specifiers + +struct B { + virtual void f0() {} // { dg-line line_base_f0 } + virtual void f1() {} // { dg-line line_base_f1 } + virtual void f2() {} // { dg-line line_base_f2 } + virtual void f3() {} // { dg-line line_base_f3 } + virtual void f4() {} // { dg-line line_base_f4 } + virtual void f5() {} // { dg-line line_base_f5 } + virtual void f6() {} // { dg-line line_base_f6 } + virtual void f7() {} // { dg-line line_base_f7 } + virtual ~B() {} +}; + +struct S : B { + virtual void f0(this S&) {} // { dg-line line_f0 } + virtual void f1(this S&) override {} // { dg-line line_f1 } + virtual void f2(this S&) final {} // { dg-line line_f2 } + virtual void f3(this S&) override final {} // { dg-line line_f3 } + void f4(this S&) {} // { dg-line line_f4 } + void f5(this S&) override {} // { dg-line line_f5 } + void f6(this S&) final {} // { dg-line line_f6 } + void f7(this S&) override final {} // { dg-line line_f7 } +}; + +struct S1 { + virtual void f0(this S&) {} // { dg-line line_S1_f0 } + virtual void f1(this S&) override {} // { dg-line line_S1_f1 } + virtual void f2(this S&) final {} // { dg-line line_S1_f2 } + virtual void f3(this S&) override final {} // { dg-line line_S1_f3 } + void f4(this S&) {} + void f5(this S&) override {} // { dg-line line_S1_f5 } + void f6(this S&) final {} // { dg-line line_S1_f6 } + void f7(this S&) override final {} // { dg-line line_S1_f7 } +}; + +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_f0 } +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_f1 } +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_f2 } +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_f3 } + +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_f0 } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_f1 } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_f2 } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_f3 } + +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_S1_f0 } +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_S1_f1 } +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_S1_f2 } +// { dg-error "an explicit object member function cannot be 'virtual'" "" { target *-*-* } line_S1_f3 } + +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_S1_f0 } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_S1_f1 } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_S1_f2 } +// { dg-note "explicit object parameter declared here" "" { target *-*-* } line_S1_f3 } + +// { dg-bogus "an explicit object member function cannot be 'virtual'" "Surely this will never happen, but this test is here just in case it does" { target *-*-* } line_f4 } + +// I want to change the diagnostics below, the tests are check for the current error, and should be changed if the error is changed +// (the following diagnostic should still take lower priority and thus be suppressed) + +// { dg-bogus "marked 'override', but does not override" "previous error should silence diagnostics about virt-specifiers (not implemented yet)" { xfail *-*-* } line_f1 } +// { dg-bogus "marked 'final', but is not virtual" "previous error should silence diagnostics about virt-specifiers (not implemented yet)" { xfail *-*-* } line_f2 } +// { dg-bogus "marked '(override|final)'" "previous error should silence diagnostics about virt-specifiers (not implemented yet)" { xfail *-*-* } line_f3 } + +// { dg-bogus "marked 'override', but does not override" "previous error should silence diagnostics about virt-specifiers (not implemented yet)" { xfail *-*-* } line_S1_f1 } +// { dg-bogus "marked 'final', but is not virtual" "previous error should silence diagnostics about virt-specifiers (not implemented yet)" { xfail *-*-* } line_S1_f2 } +// { dg-bogus "marked '(override|final)'" "previous error should silence diagnostics about virt-specifiers (not implemented yet)" { xfail *-*-* } line_S1_f3 } + +// { dg-error "marked 'override', but does not override" "" { target *-*-* } line_f5 } +// { dg-error "marked 'final', but is not virtual" "" { target *-*-* } line_f6 } +// { dg-error "marked '(override|final)'" "" { target *-*-* } line_f7 } + +// { dg-error "marked 'override', but does not override" "" { target *-*-* } line_S1_f5 } +// { dg-error "marked 'final', but is not virtual" "" { target *-*-* } line_S1_f6 } +// { dg-error "marked '(override|final)'" "" { target *-*-* } line_S1_f7 } + +// for now, these all stay active, I want to discuss with others on whether the warnings should be suppressed by other errors (I think they should be) + +// { dg-warning "was hidden" "" { target *-*-* } line_base_f0 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f1 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f2 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f3 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f4 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f5 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f6 } +// { dg-warning "was hidden" "" { target *-*-* } line_base_f7 } + +// { dg-note "by '" "" { target *-*-* } line_f0 } +// { dg-note "by '" "" { target *-*-* } line_f1 } +// { dg-note "by '" "" { target *-*-* } line_f2 } +// { dg-note "by '" "" { target *-*-* } line_f3 } +// { dg-note "by '" "" { target *-*-* } line_f4 } +// { dg-note "by '" "" { target *-*-* } line_f5 } +// { dg-note "by '" "" { target *-*-* } line_f6 } +// { dg-note "by '" "" { target *-*-* } line_f7 } + + diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed4.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed4.C new file mode 100644 index 00000000000..735d5932317 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed4.C @@ -0,0 +1,42 @@ +// P0847R7 +// { dg-do compile { target c++23 } } + +// redeclarations + +struct S { + void f0(this S&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f0(); // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f1(this S const&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f1() const; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f2(this S volatile&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f2() volatile; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f3(this S const volatile&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f3() const volatile; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f4(this S&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f4() &; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f5(this S&&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f5() &&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f6(this S const&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f6() const&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f7(this S const&&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f7() const&&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f8(this S volatile&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f8() volatile&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void f9(this S volatile&&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void f9() volatile&&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void fA(this S const volatile&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void fA() const volatile&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } + + void fB(this S const volatile&&); // { dg-note "previous declaration" "detecting redeclarations not implemented yet" { xfail *-*-* } } + void fB() const volatile&&; // { dg-error "cannot be overloaded with" "detecting redeclarations not implemented yet" { xfail *-*-* } } +}; \ No newline at end of file diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed5.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed5.C new file mode 100644 index 00000000000..0c64da3b671 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed5.C @@ -0,0 +1,9 @@ +// P0847R7 +// { dg-do compile { target c++23 } } + +struct S { + void f0(this S = {}) {} // { dg-error "an explicit object parameter may not have a default argument" } + void f1(this S); +}; + +void S::f1(this S = {}) {} // { dg-error "an explicit object parameter may not have a default argument" } diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed6.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed6.C new file mode 100644 index 00000000000..df53617a002 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-ill-formed6.C @@ -0,0 +1,22 @@ +// P0847R7 +// { dg-do compile { target c++23 } } + +// using 'this' in body disabled + +// { dg-message "In explicit object member function" "" { target *-*-* } 0 } + +struct S0 { + int _n; + void f(this S0& s) { // { dg-note "use explicit object parameter 's' instead" } + this->_n = 10; // { dg-error "'this' is unavailable for explicit object member functions" } + // solely for suppressing a potential warning + static_cast(s); + } +}; + +struct S1 { + int _n; + void f(this S1&) { // { dg-note "name and use the explicit object parameter instead" } + this->_n = 10; // { dg-error "'this' is unavailable for explicit object member functions" } + } +}; \ No newline at end of file diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-object-param-no-cxx23.C b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-no-cxx23.C new file mode 100644 index 00000000000..7f56b61c50a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-object-param-no-cxx23.C @@ -0,0 +1,7 @@ +// P0847R7 +// { dg-do compile { target c++20_down } } + +struct S { + void f(this S); // { dg-error "explicit object parameter requires" } + void g(this S self); // { dg-error "explicit object parameter requires" } +}; \ No newline at end of file -- 2.41.0