From patchwork Fri Jan 10 11:18:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Martin X-Patchwork-Id: 104468 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B75AA3858C48 for ; Fri, 10 Jan 2025 11:18:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from a7-11.smtp-out.eu-west-1.amazonses.com (a7-11.smtp-out.eu-west-1.amazonses.com [54.240.7.11]) by sourceware.org (Postfix) with ESMTPS id 842813858D34 for ; Fri, 10 Jan 2025 11:18:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 842813858D34 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=nasilyan.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eu-west-1.amazonses.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 842813858D34 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=54.240.7.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1736507887; cv=none; b=sd6XSp1+Lt9tcE4vdjF8Zvd3zIGdmP44reUs/ee/BvVme+bq7byw5u5h8I0DQrqXz651z20cefTaKNxOC5Ie8lLI18Yw5GZh+Mb6NdpEVnoQkIP6B8QwAZ4sYmOCl+mDQZ34SY8wT3Ch3sa0l6u4ScvJZ6aRy7rsSBzoG9hFIeA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1736507887; c=relaxed/simple; bh=e0+IHq7jsA+X5x0s4229MiDEoqAfE0XEW1bU/xI5Aps=; h=DKIM-Signature:DKIM-Signature:From:To:Subject:Date:Message-ID: MIME-Version; b=IoOMrWv5jd7sPZHOY0Bh5kl9j6NeXAxu5jEU9n3WLWlN95kCtLfDjt8X4gT7zv1yTaMV4/q6SDNW9NzX6YM32cFvqZ6OUw9ncAOj9VYa2cZEnwLkNS+OeO4wD5KbEkNvz9k19bsymKgczqoS4g6RGGJTtRo4jheihQWHsTHhfm0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 842813858D34 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=nasilyan.com header.i=@nasilyan.com header.a=rsa-sha256 header.s=tey23rxsjton5kop5bydp3vc5ylkyjkg header.b=TzgKDdhO; dkim=pass (1024-bit key, unprotected) header.d=amazonses.com header.i=@amazonses.com header.a=rsa-sha256 header.s=uku4taia5b5tsbglxyj6zym32efj7xqv header.b=MzFYdFUG DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=tey23rxsjton5kop5bydp3vc5ylkyjkg; d=nasilyan.com; t=1736507886; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Transfer-Encoding; bh=e0+IHq7jsA+X5x0s4229MiDEoqAfE0XEW1bU/xI5Aps=; b=TzgKDdhOoOvvx7wRznJwazv+2RtAomDCLhIMW7HnWJJfSlg6DMpYRnn/HFS6Riba jHl3I3mT9TKQQft8oyb4qv+KyejUofefU+MKacHinO2gLZFHEEeOpdMcb70Jf5xNmUm 8q0r3FngakqqKEicrDEAa3Z6UA8PHFUnl0+oENCE= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=uku4taia5b5tsbglxyj6zym32efj7xqv; d=amazonses.com; t=1736507886; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Transfer-Encoding:Feedback-ID; bh=e0+IHq7jsA+X5x0s4229MiDEoqAfE0XEW1bU/xI5Aps=; b=MzFYdFUGl8sUjWtE5Le5EipNOxnZIkn/C1mMwaHs7q9BY+T+dDw7Xvdun4TDYITe P0HVcCv2im8nOpVdudizTouUHLXj0qMChlwcSfcJ7nl/4xUkslThHXpGapao7XpSANx wU06XsxVdU14fLC7O/6MYeFCOu2wsMeZ07ooLZ1I= From: Simon Martin To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com Subject: [PATCH] c++: Reject cdtors and conversion operators with a single * as return type [PR118306] Date: Fri, 10 Jan 2025 11:18:06 +0000 Message-ID: <010201944fef89d8-714d6c52-eadb-47d8-a77f-90d2015fa0ae-000000@eu-west-1.amazonses.com> X-Mailer: git-send-email 2.44.0 MIME-Version: 1.0 Feedback-ID: ::1.eu-west-1.sMDMtMBSIJpOhM8kCarpRYeKFuDfm/WoE5+9WtFxb8w=:AmazonSES X-SES-Outgoing: 2025.01.10-54.240.7.11 X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, 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: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org We currently accept the following invalid code (EDG and MSVC do as well) === cut here === struct A { *A (); }; === cut here === The problem is that we end up in grokdeclarator with a cp_declarator of kind cdk_pointer but no type, and we happily go through (if we have a reference instead we eventually error out trying to form a reference to void). This patch makes sure that grokdeclarator errors out when processing a constructor or a conversion operator with no return type specified but also a declarator representing a pointer or a reference type. Successfully tested on x86_64-pc-linux-gnu. OK for GCC 16? PR c++/118306 gcc/cp/ChangeLog: * decl.cc (check_special_function_return_type): Take declarator and location as input. Reject return type specifiers with only a * or &. (grokdeclarator): Update call to check_special_function_return_type. gcc/testsuite/ChangeLog: * g++.dg/parse/constructor4.C: New test. * g++.dg/parse/conv_op2.C: New test. * g++.dg/parse/default_to_int.C: New test. --- gcc/cp/decl.cc | 21 +++++++++--- gcc/testsuite/g++.dg/parse/constructor4.C | 36 +++++++++++++++++++++ gcc/testsuite/g++.dg/parse/conv_op2.C | 8 +++++ gcc/testsuite/g++.dg/parse/default_to_int.C | 33 +++++++++++++++++++ 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/constructor4.C create mode 100644 gcc/testsuite/g++.dg/parse/conv_op2.C create mode 100644 gcc/testsuite/g++.dg/parse/default_to_int.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 5c6a4996a89..b57df261e76 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -101,7 +101,8 @@ static void end_cleanup_fn (void); static tree cp_make_fname_decl (location_t, tree, int); static void initialize_predefined_identifiers (void); static tree check_special_function_return_type - (special_function_kind, tree, tree, int, const location_t*); + (special_function_kind, tree, tree, int, const cp_declarator*, + location_t, const location_t*); static tree push_cp_library_fn (enum tree_code, tree, int); static tree build_cp_library_fn (tree, enum tree_code, tree, int); static void store_parm_decls (tree); @@ -12349,9 +12350,9 @@ smallest_type_location (const cp_decl_specifier_seq *declspecs) return smallest_type_location (type_quals, declspecs->locations); } -/* Check that it's OK to declare a function with the indicated TYPE - and TYPE_QUALS. SFK indicates the kind of special function (if any) - that this function is. OPTYPE is the type given in a conversion +/* Check that it's OK to declare a function at ID_LOC with the indicated TYPE, + TYPE_QUALS and DECLARATOR. SFK indicates the kind of special function (if + any) that this function is. OPTYPE is the type given in a conversion operator declaration, or the class type for a constructor/destructor. Returns the actual return type of the function; that may be different than TYPE if an error occurs, or for certain special functions. */ @@ -12361,8 +12362,19 @@ check_special_function_return_type (special_function_kind sfk, tree type, tree optype, int type_quals, + const cp_declarator *declarator, + location_t id_loc, const location_t* locations) { + /* If TYPE is unspecified, DECLARATOR, if set, should not represent a pointer + or a reference type. */ + if (type == NULL_TREE + && declarator + && (declarator->kind == cdk_pointer + || declarator->kind == cdk_reference)) + error_at (id_loc, "expected unqualified-id before %qs token", + declarator->kind == cdk_pointer ? "*" : "&"); + switch (sfk) { case sfk_constructor: @@ -13089,6 +13101,7 @@ grokdeclarator (const cp_declarator *declarator, type = check_special_function_return_type (sfk, type, ctor_return_type, type_quals, + declarator, id_loc, declspecs->locations); type_quals = TYPE_UNQUALIFIED; } diff --git a/gcc/testsuite/g++.dg/parse/constructor4.C b/gcc/testsuite/g++.dg/parse/constructor4.C new file mode 100644 index 00000000000..7d5a8ecaa97 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/constructor4.C @@ -0,0 +1,36 @@ +// PR c++/118306 +// { dg-do "compile" } + +// Constructors. +struct A { + *A (); // { dg-error "expected unqualified-id" } +}; +struct B { + &B (); // { dg-error "expected unqualified-id|reference to" } +}; +struct C { + *C (const C&); // { dg-error "expected unqualified-id" } +}; +struct D { + &D (const D&); // { dg-error "expected unqualified-id|reference to" } +}; +struct E { + const E(); // { dg-error "expected unqualified-id" } +}; + +// Destructors. +struct F { + * ~F (); // { dg-error "expected unqualified-id" } +}; +struct G { + & ~G (); // { dg-error "expected unqualified-id|reference to" } +}; +struct H { + virtual * ~H (); // { dg-error "expected unqualified-id" } +}; +struct I { + virtual & ~I (); // { dg-error "expected unqualified-id|reference to" } +}; +struct J { + volatile ~J(); // { dg-error "qualifiers are not allowed" } +}; diff --git a/gcc/testsuite/g++.dg/parse/conv_op2.C b/gcc/testsuite/g++.dg/parse/conv_op2.C new file mode 100644 index 00000000000..33477de6274 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/conv_op2.C @@ -0,0 +1,8 @@ +// PR c++/118306 +// { dg-do "compile" } + +struct K { + char operator int(); // { dg-error "return type specified for" } + * operator short(); // { dg-error "expected unqualified-id" } + & operator long(); // { dg-error "expected unqualified-id" } +}; diff --git a/gcc/testsuite/g++.dg/parse/default_to_int.C b/gcc/testsuite/g++.dg/parse/default_to_int.C new file mode 100644 index 00000000000..5c3ec37e007 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/default_to_int.C @@ -0,0 +1,33 @@ +// PR c++/118306 - "Document" various behaviours wrt. defaulting types to int. +// { dg-do "compile" } +// { dg-additional-options "-fpermissive" } + +// Members. +struct K { + * mem1; // { dg-warning "forbids declaration" } + const * mem2; // { dg-warning "forbids declaration" } + & mem3; // { dg-warning "forbids declaration" } + volatile & mem4; // { dg-warning "forbids declaration" } + + void foo (const& permissive_fine, // { dg-warning "forbids declaration" } + volatile* permissive_fine_as_well); // { dg-warning "forbids declaration" } + + * bar () { return 0; } // { dg-warning "forbids declaration" } + const& baz (); // { dg-warning "forbids declaration" } + + void bazz () { + try {} + catch (const *i) {} // { dg-warning "forbids" } + catch (const &i) {} // { dg-warning "forbids" } + } +}; + +// Template parameters. +template // { dg-warning "forbids" } +void baz() {} + +// Functions. +foo(int) { return 42; } // { dg-warning "forbids declaration" } +*bar(int) { return 0; } // { dg-warning "forbids declaration" } +const bazz (int) { return 0; } // { dg-warning "forbids declaration" } +const* bazzz (int) { return 0; } // { dg-warning "forbids declaration" }