From patchwork Tue Nov 9 11:59:38 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 70535 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id D8143B7080 for ; Tue, 9 Nov 2010 23:01:01 +1100 (EST) Received: (qmail 19846 invoked by alias); 9 Nov 2010 12:00:50 -0000 Received: (qmail 19670 invoked by uid 22791); 9 Nov 2010 12:00:46 -0000 X-SWARE-Spam-Status: No, hits=0.8 required=5.0 tests=AWL, BAYES_00, KAM_STOCKTIP X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 09 Nov 2010 12:00:37 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id C673ECB0242 for ; Tue, 9 Nov 2010 13:00:34 +0100 (CET) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id weKVliR1+T46 for ; Tue, 9 Nov 2010 13:00:34 +0100 (CET) Received: from [192.168.1.2] (bon31-9-83-155-120-49.fbx.proxad.net [83.155.120.49]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 7497ECB020C for ; Tue, 9 Nov 2010 13:00:34 +0100 (CET) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [Ada] Fix ICE on constant with tagged type Date: Tue, 9 Nov 2010 12:59:38 +0100 User-Agent: KMail/1.9.9 MIME-Version: 1.0 Message-Id: <201011091259.38623.ebotcazou@adacore.com> 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 This is an ICE raised when compiling Adasockets 1.8.8, a regression present on the mainline. The gimplifier is trying to create a temporary with a type for which it isn't allowed to do so; such a temporary must always be created by gigi for this kind of type. It turns out that no temporary is needed if the trees are fully simplified. But they aren't because the constant folder doesn't fold constructors with type_contains_placeholder_p types. However, the problematic type doesn't contain PLACEHOLDER_EXPRs in its structure, it only contains a component whose type is a pointer type to a type_contains_placeholder_p type. This appears to be an old thinko in type_contains_placeholder_1: it reads /* Return true if any part of the computation of TYPE involves a PLACEHOLDER_EXPR. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field positions. */ static bool type_contains_placeholder_1 (const_tree type) { /* If the size contains a placeholder or the parent type (component type in the case of arrays) type involves a placeholder, this type does. */ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type)) || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type)) || (TREE_TYPE (type) != 0 && type_contains_placeholder_p (TREE_TYPE (type)))) return true; but TREE_TYPE (type) is the pointed-to type for POINTER_TYPE_P types. The attached patch makes it so that type_contains_placeholder_p returns false for POINTER_TYPE_P types. This works fine, except for what we call "fat pointer types" in Ada, which are not only used to represent pointers but also unconstrained arrays types themselves; the latters do contain PLACEHOLDERs. So the patch forces type_contains_placeholder_p to return true for them. Tested on i586-suse-linux, applied on the mainline. This only affects Ada. 2010-11-09 Eric Botcazou * tree.h (contains_placeholder_p): Fix comment. (type_contains_placeholder_p): Adjust comment. * tree.c (contains_placeholder_p): Fix comment. (type_contains_placeholder_1): Do not recurse on pointed-to types and adjust comment. (type_contains_placeholder_p): Add comment. ada/ * gcc-interface/decl.c (finish_fat_pointer_type): New function. (gnat_to_gnu_entity) : Use it to build the fat pointer type. : Likewise. 2010-11-09 Eric Botcazou * gnat.dg/specs/static_initializer5.ads: New test. * gnat.dg/specs/static_initializer5_pkg.ads: New helper. Index: tree.c =================================================================== --- tree.c (revision 166445) +++ tree.c (working copy) @@ -2795,8 +2795,8 @@ process_call_operands (tree t) TREE_READONLY (t) = read_only; } -/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size - or offset that depends on a field within a record. */ +/* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a + size or offset that depends on a field within a record. */ bool contains_placeholder_p (const_tree exp) @@ -2882,9 +2882,9 @@ contains_placeholder_p (const_tree exp) return 0; } -/* Return true if any part of the computation of TYPE involves a - PLACEHOLDER_EXPR. This includes size, bounds, qualifiers - (for QUAL_UNION_TYPE) and field positions. */ +/* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR + directly. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and + field positions. */ static bool type_contains_placeholder_1 (const_tree type) @@ -2893,7 +2893,8 @@ type_contains_placeholder_1 (const_tree the case of arrays) type involves a placeholder, this type does. */ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type)) || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type)) - || (TREE_TYPE (type) != 0 + || (!POINTER_TYPE_P (type) + && TREE_TYPE (type) && type_contains_placeholder_p (TREE_TYPE (type)))) return true; @@ -2921,8 +2922,8 @@ type_contains_placeholder_1 (const_tree || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type))); case ARRAY_TYPE: - /* We're already checked the component type (TREE_TYPE), so just check - the index type. */ + /* We have already checked the component type above, so just check the + domain type. */ return type_contains_placeholder_p (TYPE_DOMAIN (type)); case RECORD_TYPE: @@ -2947,6 +2948,8 @@ type_contains_placeholder_1 (const_tree } } +/* Wrapper around above function used to cache its result. */ + bool type_contains_placeholder_p (tree type) { Index: tree.h =================================================================== --- tree.h (revision 166445) +++ tree.h (working copy) @@ -4588,11 +4588,8 @@ extern tree skip_simple_arithmetic (tree enum tree_node_structure_enum tree_node_structure (const_tree); -/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size - or offset that depends on a field within a record. - - Note that we only allow such expressions within simple arithmetic - or a COND_EXPR. */ +/* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a + size or offset that depends on a field within a record. */ extern bool contains_placeholder_p (const_tree); @@ -4602,9 +4599,9 @@ extern bool contains_placeholder_p (cons #define CONTAINS_PLACEHOLDER_P(EXP) \ ((EXP) != 0 && ! TREE_CONSTANT (EXP) && contains_placeholder_p (EXP)) -/* Return 1 if any part of the computation of TYPE involves a PLACEHOLDER_EXPR. - This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field - positions. */ +/* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR + directly. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and + field positions. */ extern bool type_contains_placeholder_p (tree); Index: ada/gcc-interface/decl.c =================================================================== --- ada/gcc-interface/decl.c (revision 166445) +++ ada/gcc-interface/decl.c (working copy) @@ -177,6 +177,7 @@ static tree create_variant_part_from (tr tree, VEC(subst_pair,heap) *); static void copy_and_substitute_in_size (tree, tree, VEC(subst_pair,heap) *); static void rest_of_type_decl_compilation_no_defer (tree); +static void finish_fat_pointer_type (tree, tree); /* The relevant constituents of a subprogram binding to a GCC builtin. Used to pass around calls performing profile compatibilty checks. */ @@ -188,7 +189,6 @@ typedef struct { } intrin_binding_t; static bool intrin_profiles_compatible_p (intrin_binding_t *); - /* Given GNAT_ENTITY, a GNAT defining identifier node, which denotes some Ada entity, return the equivalent GCC tree for that entity (a ..._DECL node) @@ -1915,23 +1915,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entit /* Build the fat pointer type. Use a "void *" object instead of a pointer to the array type since we don't have the array type yet (it will reference the fat pointer via the bounds). */ - tem = chainon (chainon (NULL_TREE, - create_field_decl (get_identifier ("P_ARRAY"), - ptr_void_type_node, - gnu_fat_type, NULL_TREE, - NULL_TREE, 0, 0)), - create_field_decl (get_identifier ("P_BOUNDS"), - gnu_ptr_template, - gnu_fat_type, NULL_TREE, - NULL_TREE, 0, 0)); - - /* Make sure we can put this into a register. */ - TYPE_ALIGN (gnu_fat_type) = MIN (BIGGEST_ALIGNMENT, 2 * POINTER_SIZE); - - /* Do not emit debug info for this record type since the types of its - fields are still incomplete at this point. */ - finish_record_type (gnu_fat_type, tem, 0, false); - TYPE_FAT_POINTER_P (gnu_fat_type) = 1; + tem + = create_field_decl (get_identifier ("P_ARRAY"), ptr_void_type_node, + gnu_fat_type, NULL_TREE, NULL_TREE, 0, 0); + TREE_CHAIN (tem) + = create_field_decl (get_identifier ("P_BOUNDS"), gnu_ptr_template, + gnu_fat_type, NULL_TREE, NULL_TREE, 0, 0); + finish_fat_pointer_type (gnu_fat_type, tem); /* Build a reference to the template from a PLACEHOLDER_EXPR that is the fat pointer. This will be used to access the individual @@ -3587,15 +3577,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit = create_field_decl (get_identifier ("P_BOUNDS"), gnu_ptr_template, gnu_type, NULL_TREE, NULL_TREE, 0, 0); - - /* Make sure we can place this into a register. */ - TYPE_ALIGN (gnu_type) - = MIN (BIGGEST_ALIGNMENT, 2 * POINTER_SIZE); - TYPE_FAT_POINTER_P (gnu_type) = 1; - - /* Do not emit debug info for this record type since the types - of its fields are incomplete. */ - finish_record_type (gnu_type, fields, 0, false); + finish_fat_pointer_type (gnu_type, fields); TYPE_OBJECT_RECORD_TYPE (gnu_desig_type) = make_node (RECORD_TYPE); @@ -5125,6 +5107,28 @@ rest_of_type_decl_compilation_no_defer ( } } +/* Given a record type RECORD_TYPE and a list of FIELD_DECL nodes FIELD_LIST, + finish constructing the record type as a fat pointer type. */ + +static void +finish_fat_pointer_type (tree record_type, tree field_list) +{ + /* Make sure we can put it into a register. */ + TYPE_ALIGN (record_type) = MIN (BIGGEST_ALIGNMENT, 2 * POINTER_SIZE); + + /* Show what it really is. */ + TYPE_FAT_POINTER_P (record_type) = 1; + + /* Do not emit debug info for it since the types of its fields may still be + incomplete at this point. */ + finish_record_type (record_type, field_list, 0, false); + + /* Force type_contains_placeholder_p to return true on it. Although the + PLACEHOLDER_EXPRs are referenced only indirectly, this isn't a pointer + type but the representation of the unconstrained array. */ + TYPE_CONTAINS_PLACEHOLDER_INTERNAL (record_type) = 2; +} + /* Finalize any From_With_Type incomplete types. We do this after processing our compilation unit and after processing its spec, if this is a body. */