From patchwork Fri Sep 8 14:56:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 811644 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-461730-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="iPSLaFAy"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xpgQF2tBzz9s81 for ; Sat, 9 Sep 2017 00:56:51 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=kEO4ejjeQ0aSi8TFPmHf2hCF9BvY1xqSU7gob4aDBscA1Z JlXeKDbFLSj5bBekC7NIM3KwxwQy0roBW8qV68ti/dhRzozymHDP6oSN6LUF5l5v wLNNZNXWrQJiY/evvn4+jLTdQTCseRWoKNrFtNqwFPdwLc4qahPN3GFcRTylU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=2XFSyCFq9dB5OHYedkD3/9xlGoE=; b=iPSLaFAyyDrH/5buA4IN amtXMvOzu7i85R5rXTndLYRoHvPK3/lxHyoI7Qs8HhAaCH71zb+iii/STsQOZLUW XZJo86GdBPFWQkA8uU1z6DCSx3Lf9vAkwvZb/d4ZanbUKMBYkYPCo1ncmEDibM9S 6gUj1+hkWRc4reZfxBJYzuc= Received: (qmail 10961 invoked by alias); 8 Sep 2017 14:56:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 10204 invoked by uid 89); 8 Sep 2017 14:56:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.2 spammy= X-HELO: mail-it0-f53.google.com Received: from mail-it0-f53.google.com (HELO mail-it0-f53.google.com) (209.85.214.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 08 Sep 2017 14:56:40 +0000 Received: by mail-it0-f53.google.com with SMTP id o200so2901495itg.0 for ; Fri, 08 Sep 2017 07:56:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=ywOKC/cDWdOKSDKX3jU/ULjdYka/2kZ/CRncC3jRsDI=; b=srabXljeIno90fycdfLhEJhmChsoY08Nn/ItZXUYa7aHOYBvutRFOdFLWpwTD1/TAL Jjc084k552o+dc1tD962RdIyF9O9bC8k7O9GzlhIZGISk1YhGEsReeBg49AUhdP16Am9 14Hb0U79iI0LmiJJjt+gGNjQOFSaW9wIHJ6bb078S/rWhRIjXhs/Oh6X2wkuBRAMun9k I1V6PBefY7oavDPntUiHZwnJwvaDUp5AKMh9KUdUwIq2JRPgE3sFzmppToxOwYYQevHc +tBv4EHZV21Z0DFxcaOmhOkOhx0Z6PP+0YK/4yx6bkmXKaAxebnnU7xxVQ1T/H94Lw7R 0WSg== X-Gm-Message-State: AHPjjUjRW1IJx1eUk7ZEIzIsrrlCn1oBWL4E7qRSkuKZWXFof+oGPppg Ti8maHEtgnRRwFixCoJdOigZgFf2+tiq5To= X-Google-Smtp-Source: AOwi7QA+dQexPqxZcEruXji6MnjZ5+7ddwNQB1fSu8eu6WBhlFBNzowZP2xyOjlSTnlIIJk/ou6rSQ83IwVW6byUMpI= X-Received: by 10.36.200.132 with SMTP id w126mr1357951itf.101.1504882598876; Fri, 08 Sep 2017 07:56:38 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.181.23 with HTTP; Fri, 8 Sep 2017 07:56:18 -0700 (PDT) From: Jason Merrill Date: Fri, 8 Sep 2017 16:56:18 +0200 Message-ID: Subject: RFA (langhook): PATCH for c++/70029, ICE in verify_type with ref-qualifier To: gcc-patches List X-IsSubscribed: yes The issue here is that the C++ front end represents the ref-qualifier as a variant but includes it in the canonical type, because at the language level the types are distinct. Note that this is also true of language-independent qualifiers like "const", so this doesn't seem like an unreasonable thing for the front end to do. But as a result, when build_type_attribute_qual_variant builds a distinct type copy of the ref-qualified type, it is now its own main variant, while the canonical type is still a variant of another type, and verify_type doesn't like that. This patch introduces a langhook to mimic for language-dependent qualifiers the b_t_a_q_v behavior for cv-qualifiers, i.e. strip them before making the copy and reintroduce them afterward. Tested x86_64-pc-linux-gnu. OK for trunk? commit 50a71bc8cbf3d17f0039f531b96e64f348b83549 Author: Jason Merrill Date: Fri Sep 8 00:09:46 2017 +0200 PR c++/70029 - ICE with ref-qualifier and -flto gcc/ * langhooks.h (struct lang_hooks_for_types): Add copy_lang_qualifiers. * attribs.c (build_type_attribute_qual_variant): Use it. * langhooks-def.h (LANG_HOOKS_COPY_LANG_QUALIFIERS): Default to NULL. (LANG_HOOKS_FOR_TYPES_INITIALIZER): Use it. * tree.c (verify_type): Re-enable TYPE_CANONICAL main variant check. gcc/cp/ * tree.c (cxx_copy_lang_qualifiers): New. * cp-tree.h: Declare it. * cp-objcp-common.h: Define LANG_HOOKS_COPY_LANG_QUALIFIERS. diff --git a/gcc/attribs.c b/gcc/attribs.c index faa0649..b8f58a7 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -959,8 +959,9 @@ build_decl_attribute_variant (tree ddecl, tree attribute) Record such modified types already made so we don't make duplicates. */ tree -build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) +build_type_attribute_qual_variant (tree otype, tree attribute, int quals) { + tree ttype = otype; if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) { tree ntype; @@ -983,6 +984,11 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) } ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED); + if (lang_hooks.types.copy_lang_qualifiers + && otype != TYPE_MAIN_VARIANT (otype)) + ttype = (lang_hooks.types.copy_lang_qualifiers + (ttype, TYPE_MAIN_VARIANT (otype))); + ntype = build_distinct_type_copy (ttype); TYPE_ATTRIBUTES (ntype) = attribute; @@ -1000,6 +1006,9 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); ttype = build_qualified_type (ntype, quals); + if (lang_hooks.types.copy_lang_qualifiers + && otype != TYPE_MAIN_VARIANT (otype)) + ttype = lang_hooks.types.copy_lang_qualifiers (ttype, otype); } else if (TYPE_QUALS (ttype) != quals) ttype = build_qualified_type (ttype, quals); diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 10fcdf3..3e4cc9c 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -99,6 +99,8 @@ extern void cp_register_dumps (gcc::dump_manager *); #define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE cxx_builtin_function_ext_scope #undef LANG_HOOKS_TYPE_HASH_EQ #define LANG_HOOKS_TYPE_HASH_EQ cxx_type_hash_eq +#undef LANG_HOOKS_COPY_LANG_QUALIFIERS +#define LANG_HOOKS_COPY_LANG_QUALIFIERS cxx_copy_lang_qualifiers #undef LANG_HOOKS_MISSING_NORETURN_OK_P #define LANG_HOOKS_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p #undef LANG_HOOKS_BLOCK_MAY_FALLTHRU diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a0e31d3..a57de33 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6963,6 +6963,7 @@ extern tree convert_bitfield_to_declared_type (tree); extern tree cp_save_expr (tree); extern bool cast_valid_in_integral_constant_expression_p (tree); extern bool cxx_type_hash_eq (const_tree, const_tree); +extern tree cxx_copy_lang_qualifiers (const_tree, const_tree); extern void cxx_print_statistics (void); extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 12c31fb..f387f38 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -4626,6 +4626,21 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb) TYPE_RAISES_EXCEPTIONS (typeb), ce_exact); } +/* Copy the language-specific type variant modifiers from TYPEB to TYPEA. For + C++, these are the exception-specifier and ref-qualifier. */ + +tree +cxx_copy_lang_qualifiers (const_tree typea, const_tree typeb) +{ + tree type = CONST_CAST_TREE (typea); + if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) + { + type = build_exception_variant (type, TYPE_RAISES_EXCEPTIONS (typeb)); + type = build_ref_qualified_type (type, type_memfn_rqual (typeb)); + } + return type; +} + /* Apply FUNC to all language-specific sub-trees of TP in a pre-order traversal. Called from walk_tree. */ diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index ea2006c..61b081b 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -186,6 +186,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree); lhd_omp_firstprivatize_type_sizes #define LANG_HOOKS_OMP_MAPPABLE_TYPE lhd_omp_mappable_type #define LANG_HOOKS_TYPE_HASH_EQ NULL +#define LANG_HOOKS_COPY_LANG_QUALIFIERS NULL #define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL #define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL #define LANG_HOOKS_GET_TYPE_BIAS NULL @@ -211,6 +212,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree); LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \ LANG_HOOKS_OMP_MAPPABLE_TYPE, \ LANG_HOOKS_TYPE_HASH_EQ, \ + LANG_HOOKS_COPY_LANG_QUALIFIERS, \ LANG_HOOKS_GET_ARRAY_DESCR_INFO, \ LANG_HOOKS_GET_SUBRANGE_BOUNDS, \ LANG_HOOKS_GET_TYPE_BIAS, \ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 88f6f71..b0c9829 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -123,6 +123,10 @@ struct lang_hooks_for_types FUNCTION_TYPE or METHOD_TYPE. */ bool (*type_hash_eq) (const_tree, const_tree); + /* If non-NULL, return TYPE1 with any language-specific modifiers copied from + TYPE2. */ + tree (*copy_lang_qualifiers) (const_tree, const_tree); + /* Return TRUE if TYPE uses a hidden descriptor and fills in information for the debugger about the array bounds, strides, etc. */ bool (*get_array_descr_info) (const_tree, struct array_descr_info *); diff --git a/gcc/testsuite/g++.dg/lto/pr70029_0.C b/gcc/testsuite/g++.dg/lto/pr70029_0.C new file mode 100644 index 0000000..9c8c31c --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr70029_0.C @@ -0,0 +1,10 @@ +// PR c++/70029 +// { dg-lto-do assemble } + +struct A +{ + A(); + int foo() && __attribute__ ((__warn_unused_result__)) { return 0; } +}; + +A a; diff --git a/gcc/tree.c b/gcc/tree.c index 7a70eb7..721330a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -13220,9 +13220,7 @@ verify_type (const_tree t) debug_tree (ct); error_found = true; } - /* FIXME: this is violated by the C++ FE as discussed in PR70029, when - FUNCTION_*_QUALIFIED flags are set. */ - if (0 && TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct) + if (TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct) { error ("TYPE_CANONICAL of main variant is not main variant"); debug_tree (ct);