diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2018-05-25 09:03:29 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2018-05-25 09:03:29 +0000 |
commit | 0d0cd28165d05981eadc966224dca77b87111b62 (patch) | |
tree | b393260c4976c48845d0913b4bfd2057209f9bfb | |
parent | 28e3372094a60b1d7fb9d076a29b050761e5692a (diff) | |
download | gcc-0d0cd28165d05981eadc966224dca77b87111b62.zip gcc-0d0cd28165d05981eadc966224dca77b87111b62.tar.gz gcc-0d0cd28165d05981eadc966224dca77b87111b62.tar.bz2 |
[Ada] Support for C99 and C++ standard boolean types
This change the type Interfaces.C.Extensions.bool to be fully compatible
with the C99 and C++ standard boolean types by making it a fully-fledged
boolean type with convention C.
The following C+Ada program must compile quietly in LTO mode:
bool b;
struct S {};
bool foo (struct S *s) { return true; }
pragma Ada_2005;
pragma Style_Checks (Off);
with Interfaces.C; use Interfaces.C;
with Interfaces.C.Extensions;
package t_c is
b : aliased Extensions.bool; -- t.c:3
pragma Import (C, b, "b");
type S is record
null;
end record;
pragma Convention (C_Pass_By_Copy, S); -- t.c:5
function foo (the_s : access S) return Extensions.bool; -- t.c:7
pragma Import (C, foo, "foo");
end t_c;
with t_c; use t_c;
procedure P_C is
Dummy : aliased S;
begin
b := foo (Dummy'Access);
end;
2018-05-25 Eric Botcazou <ebotcazou@adacore.com>
gcc/ada/
* freeze.adb (Freeze_Enumeration_Type): Do not give integer size to a
boolean type with convention C.
* libgnat/i-cexten.ads (bool): Change to boolean with convention C.
* gcc-interface/decl.c (gnat_to_gnu_entity): Add new local variable
FOREIGN and use it throughout the function.
<E_Enumeration_Type>: Set precision 1 on boolean types with foreign
convention.
<E_Enumeration_Subtype>: Likewise for subtypes.
<E_Record_Type>: Force the size of a storage unit on empty classes.
* gcc-interface/utils.c (make_type_from_size) <BOOLEAN_TYPE>: Skip
boolean types with precision 1 if the size is the expected one.
From-SVN: r260721
-rw-r--r-- | gcc/ada/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/ada/freeze.adb | 11 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 37 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 8 | ||||
-rw-r--r-- | gcc/ada/libgnat/i-cexten.ads | 3 |
5 files changed, 60 insertions, 13 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3f183c3..838c445 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,17 @@ +2018-05-25 Eric Botcazou <ebotcazou@adacore.com> + + * freeze.adb (Freeze_Enumeration_Type): Do not give integer size to a + boolean type with convention C. + * libgnat/i-cexten.ads (bool): Change to boolean with convention C. + * gcc-interface/decl.c (gnat_to_gnu_entity): Add new local variable + FOREIGN and use it throughout the function. + <E_Enumeration_Type>: Set precision 1 on boolean types with foreign + convention. + <E_Enumeration_Subtype>: Likewise for subtypes. + <E_Record_Type>: Force the size of a storage unit on empty classes. + * gcc-interface/utils.c (make_type_from_size) <BOOLEAN_TYPE>: Skip + boolean types with precision 1 if the size is the expected one. + 2018-05-25 Arnaud Charlet <charlet@adacore.com> * pprint.adb (Expression_Name): Do not print non ASCII characters. diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index a275619..72b8f95 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -6877,12 +6877,15 @@ package body Freeze is procedure Freeze_Enumeration_Type (Typ : Entity_Id) is begin -- By default, if no size clause is present, an enumeration type with - -- Convention C is assumed to interface to a C enum, and has integer - -- size. This applies to types. For subtypes, verify that its base - -- type has no size clause either. Treat other foreign conventions - -- in the same way, and also make sure alignment is set right. + -- Convention C is assumed to interface to a C enum and has integer + -- size, except for a boolean type because it is assumed to interface + -- to _Bool introduced in C99. This applies to types. For subtypes, + -- verify that its base type has no size clause either. Treat other + -- foreign conventions in the same way, and also make sure alignment + -- is set right. if Has_Foreign_Convention (Typ) + and then not Is_Boolean_Type (Typ) and then not Has_Size_Clause (Typ) and then not Has_Size_Clause (Base_Type (Typ)) and then Esize (Typ) < Standard_Integer_Size diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index a63cc18..738211f 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -282,6 +282,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* True if this entity is to be considered as imported. */ const bool imported_p = (Is_Imported (gnat_entity) && No (Address_Clause (gnat_entity))); + /* True if this entity has a foreign convention. */ + const bool foreign = Has_Foreign_Convention (gnat_entity); /* For a type, contains the equivalent GNAT node to be used in gigi. */ Entity_Id gnat_equiv_type = Empty; /* Temporary used to walk the GNAT tree. */ @@ -658,8 +660,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) } /* Get the type after elaborating the renamed object. */ - if (Has_Foreign_Convention (gnat_entity) - && Is_Descendant_Of_Address (Underlying_Type (gnat_type))) + if (foreign && Is_Descendant_Of_Address (Underlying_Type (gnat_type))) gnu_type = ptr_type_node; else { @@ -1594,6 +1595,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) tree gnu_list = NULL_TREE; Entity_Id gnat_literal; + /* Boolean types with foreign convention have precision 1. */ + if (is_boolean && foreign) + esize = 1; + gnu_type = make_node (is_boolean ? BOOLEAN_TYPE : ENUMERAL_TYPE); TYPE_PRECISION (gnu_type) = esize; TYPE_UNSIGNED (gnu_type) = is_unsigned; @@ -1774,6 +1779,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) && Is_Bit_Packed_Array (Original_Array_Type (gnat_entity))) esize = UI_To_Int (RM_Size (gnat_entity)); + /* Boolean types with foreign convention have precision 1. */ + if (Is_Boolean_Type (gnat_entity) && foreign) + { + gnu_type = make_node (BOOLEAN_TYPE); + TYPE_PRECISION (gnu_type) = 1; + TYPE_UNSIGNED (gnu_type) = 1; + set_min_and_max_values_for_integral_type (gnu_type, 1, UNSIGNED); + layout_type (gnu_type); + } /* First subtypes of Character are treated as Character; otherwise this should be an unsigned type if the base type is unsigned or if the lower bound is constant and non-negative or if the type @@ -1783,7 +1797,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) conversions to it and gives more leeway to the optimizer; but this means that we will need to explicitly test for this case when we change the representation based on the RM size. */ - if (kind == E_Enumeration_Subtype + else if (kind == E_Enumeration_Subtype && No (First_Literal (Etype (gnat_entity))) && Esize (gnat_entity) == RM_Size (gnat_entity) && esize == CHAR_TYPE_SIZE @@ -1808,8 +1822,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) gnat_entity, "U", definition, true, debug_info_p)); - TYPE_BIASED_REPRESENTATION_P (gnu_type) - = Has_Biased_Representation (gnat_entity); + if (TREE_CODE (gnu_type) == INTEGER_TYPE) + TYPE_BIASED_REPRESENTATION_P (gnu_type) + = Has_Biased_Representation (gnat_entity); /* Do the same processing for Character subtypes as for types. */ if (TYPE_STRING_FLAG (TREE_TYPE (gnu_type))) @@ -3300,6 +3315,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) all_rep ? NULL_TREE : bitsize_zero_node, NULL); + /* Empty classes have the size of a storage unit in C++. */ + if (TYPE_SIZE (gnu_type) == bitsize_zero_node + && Convention (gnat_entity) == Convention_CPP) + { + TYPE_SIZE (gnu_type) = bitsize_unit_node; + TYPE_SIZE_UNIT (gnu_type) = size_one_node; + compute_record_mode (gnu_type); + } + /* If there are entities in the chain corresponding to components that we did not elaborate, ensure we elaborate their types if they are Itypes. */ @@ -3966,8 +3990,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* If we should request stack realignment for a foreign convention subprogram, do so. Note that this applies to task entry points in particular. */ - if (FOREIGN_FORCE_REALIGN_STACK - && Has_Foreign_Convention (gnat_entity)) + if (FOREIGN_FORCE_REALIGN_STACK && foreign) prepend_one_attribute (&attr_list, ATTR_MACHINE_ATTRIBUTE, get_identifier ("force_align_arg_pointer"), NULL_TREE, diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index eb2c257..cc25973 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -1133,9 +1133,15 @@ make_type_from_size (tree type, tree size_tree, bool for_biased) switch (TREE_CODE (type)) { + case BOOLEAN_TYPE: + /* Do not mess with boolean types that have foreign convention. */ + if (TYPE_PRECISION (type) == 1 && TYPE_SIZE (type) == size_tree) + break; + + /* ... fall through ... */ + case INTEGER_TYPE: case ENUMERAL_TYPE: - case BOOLEAN_TYPE: biased_p = (TREE_CODE (type) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)); diff --git a/gcc/ada/libgnat/i-cexten.ads b/gcc/ada/libgnat/i-cexten.ads index 8e770b5..d643b95 100644 --- a/gcc/ada/libgnat/i-cexten.ads +++ b/gcc/ada/libgnat/i-cexten.ads @@ -56,7 +56,8 @@ package Interfaces.C.Extensions is -- C bool - subtype bool is plain_char; + type bool is new Boolean; + pragma Convention (C, bool); -- 64-bit integer types |