From patchwork Tue May 28 07:44:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 1106131 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-501747-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=adacore.com 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 45Cm854zG6z9s3Z for ; Tue, 28 May 2019 17:44:29 +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:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=g65hJsmI7Tfg0kNo 6cNue43L8fn7KEhpr2IYsIA/it6fg5BMaQC0bERbP65hrSPyMjQ02dPQ/ALS9wcD q+sdoH5RXRcFaAF8/YvFDKWhFfeXPVIv7N92GMqdklhxLFCcLkYIe+qVK75uTERF R0w4TZH0yO9SxnyFc5ZWXgKAMng= 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:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=kQNoU4VoLlBwp7UK+WtYKv JLKJs=; b=YDUDNKUu7Y43EHP+4QE+ehzttPv7hm0pEYwYfkxciAQhGUIcC70KmW frshSEys3KSUBFM8I1RVreG0DFr+edkzo0c57GhTtf710aAS0jRRoyAAs0zsGRgt /0Xl0j+pUv04JnQIDbHVvGJ8dHel55aMO7s2tAoje1HVtBC42EOmA= Received: (qmail 97706 invoked by alias); 28 May 2019 07:44:21 -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 97698 invoked by uid 89); 28 May 2019 07:44:21 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-6.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=031, 063 X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 28 May 2019 07:44:19 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 8EC9F81386 for ; Tue, 28 May 2019 09:44:17 +0200 (CEST) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id K7A8MdE8_zl6 for ; Tue, 28 May 2019 09:44:17 +0200 (CEST) Received: from polaris.localnet (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id 64A6281354 for ; Tue, 28 May 2019 09:44:17 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [Ada] Fix crash on extension with variable size and representation clause Date: Tue, 28 May 2019 09:44:15 +0200 Message-ID: <2748056.V8E78CCTFA@polaris> MIME-Version: 1.0 The compiler segfaults on the extension of a tagged record type with variable size subject to a partial representation clause, which is quite pathological. Tested on x86_64-suse-linux, applied on the mainline and 9 branch. 2019-05-28 Eric Botcazou * gcc-interface/decl.c (components_to_record): Set a name on the created for the REP part, if any. * gcc-interface/utils.c (finish_record_type): Only take the maximum when merging sizes for a variant part at offset 0. (merge_sizes): Rename has_rep parameter into max. 2019-05-28 Eric Botcazou * gnat.dg/specs/discr5.ads: New test. Index: gcc-interface/decl.c =================================================================== --- gcc-interface/decl.c (revision 271679) +++ gcc-interface/decl.c (working copy) @@ -8162,6 +8162,8 @@ components_to_record (Node_Id gnat_compo gnu_field_list = gnu_rep_list; else { + TYPE_NAME (gnu_rep_type) + = create_concat_name (gnat_record_type, "REP"); TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type) = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type); finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info); Index: gcc-interface/utils.c =================================================================== --- gcc-interface/utils.c (revision 271680) +++ gcc-interface/utils.c (working copy) @@ -1863,6 +1863,9 @@ finish_record_type (tree record_type, tr else this_ada_size = this_size; + const bool variant_part = (TREE_CODE (type) == QUAL_UNION_TYPE); + const bool variant_part_at_zero = variant_part && integer_zerop (pos); + /* Clear DECL_BIT_FIELD for the cases layout_decl does not handle. */ if (DECL_BIT_FIELD (field) && operand_equal_p (this_size, TYPE_SIZE (type), 0)) @@ -1904,9 +1907,7 @@ finish_record_type (tree record_type, tr /* Clear DECL_BIT_FIELD_TYPE for a variant part at offset 0, it's simply not supported by the DECL_BIT_FIELD_REPRESENTATIVE machinery because the variant part is always the last field in the list. */ - if (DECL_INTERNAL_P (field) - && TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE - && integer_zerop (pos)) + if (variant_part_at_zero) DECL_BIT_FIELD_TYPE (field) = NULL_TREE; /* If we still have DECL_BIT_FIELD set at this point, we know that the @@ -1941,18 +1942,18 @@ finish_record_type (tree record_type, tr case RECORD_TYPE: /* Since we know here that all fields are sorted in order of increasing bit position, the size of the record is one - higher than the ending bit of the last field processed - unless we have a rep clause, since in that case we might - have a field outside a QUAL_UNION_TYPE that has a higher ending - position. So use a MAX in that case. Also, if this field is a - QUAL_UNION_TYPE, we need to take into account the previous size in - the case of empty variants. */ + higher than the ending bit of the last field processed, + unless we have a variant part at offset 0, since in this + case we might have a field outside the variant part that + has a higher ending position; so use a MAX in this case. + Also, if this field is a QUAL_UNION_TYPE, we need to take + into account the previous size in the case of empty variants. */ ada_size - = merge_sizes (ada_size, pos, this_ada_size, - TREE_CODE (type) == QUAL_UNION_TYPE, rep_level > 0); + = merge_sizes (ada_size, pos, this_ada_size, variant_part, + variant_part_at_zero); size - = merge_sizes (size, pos, this_size, - TREE_CODE (type) == QUAL_UNION_TYPE, rep_level > 0); + = merge_sizes (size, pos, this_size, variant_part, + variant_part_at_zero); break; default: @@ -2233,13 +2234,12 @@ rest_of_record_type_compilation (tree re /* Utility function of above to merge LAST_SIZE, the previous size of a record with FIRST_BIT and SIZE that describe a field. SPECIAL is true if this represents a QUAL_UNION_TYPE in which case we must look for COND_EXPRs and - replace a value of zero with the old size. If HAS_REP is true, we take the + replace a value of zero with the old size. If MAX is true, we take the MAX of the end position of this field with LAST_SIZE. In all other cases, we use FIRST_BIT plus SIZE. Return an expression for the size. */ static tree -merge_sizes (tree last_size, tree first_bit, tree size, bool special, - bool has_rep) +merge_sizes (tree last_size, tree first_bit, tree size, bool special, bool max) { tree type = TREE_TYPE (last_size); tree new_size; @@ -2247,7 +2247,7 @@ merge_sizes (tree last_size, tree first_ if (!special || TREE_CODE (size) != COND_EXPR) { new_size = size_binop (PLUS_EXPR, first_bit, size); - if (has_rep) + if (max) new_size = size_binop (MAX_EXPR, last_size, new_size); } @@ -2256,11 +2256,11 @@ merge_sizes (tree last_size, tree first_ integer_zerop (TREE_OPERAND (size, 1)) ? last_size : merge_sizes (last_size, first_bit, TREE_OPERAND (size, 1), - 1, has_rep), + 1, max), integer_zerop (TREE_OPERAND (size, 2)) ? last_size : merge_sizes (last_size, first_bit, TREE_OPERAND (size, 2), - 1, has_rep)); + 1, max)); /* We don't need any NON_VALUE_EXPRs and they can confuse us (especially when fed through SUBSTITUTE_IN_EXPR) into thinking that a constant