Commit 0d0cd281 by Eric Botcazou Committed by Pierre-Marie de Rodat

[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
parent 28e33720
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> 2018-05-25 Arnaud Charlet <charlet@adacore.com>
* pprint.adb (Expression_Name): Do not print non ASCII characters. * pprint.adb (Expression_Name): Do not print non ASCII characters.
......
...@@ -6877,12 +6877,15 @@ package body Freeze is ...@@ -6877,12 +6877,15 @@ package body Freeze is
procedure Freeze_Enumeration_Type (Typ : Entity_Id) is procedure Freeze_Enumeration_Type (Typ : Entity_Id) is
begin begin
-- By default, if no size clause is present, an enumeration type with -- 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 -- Convention C is assumed to interface to a C enum and has integer
-- size. This applies to types. For subtypes, verify that its base -- size, except for a boolean type because it is assumed to interface
-- type has no size clause either. Treat other foreign conventions -- to _Bool introduced in C99. This applies to types. For subtypes,
-- in the same way, and also make sure alignment is set right. -- 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) 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 (Typ)
and then not Has_Size_Clause (Base_Type (Typ)) and then not Has_Size_Clause (Base_Type (Typ))
and then Esize (Typ) < Standard_Integer_Size and then Esize (Typ) < Standard_Integer_Size
......
...@@ -282,6 +282,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -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. */ /* True if this entity is to be considered as imported. */
const bool imported_p const bool imported_p
= (Is_Imported (gnat_entity) && No (Address_Clause (gnat_entity))); = (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. */ /* For a type, contains the equivalent GNAT node to be used in gigi. */
Entity_Id gnat_equiv_type = Empty; Entity_Id gnat_equiv_type = Empty;
/* Temporary used to walk the GNAT tree. */ /* Temporary used to walk the GNAT tree. */
...@@ -658,8 +660,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -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. */ /* Get the type after elaborating the renamed object. */
if (Has_Foreign_Convention (gnat_entity) if (foreign && Is_Descendant_Of_Address (Underlying_Type (gnat_type)))
&& Is_Descendant_Of_Address (Underlying_Type (gnat_type)))
gnu_type = ptr_type_node; gnu_type = ptr_type_node;
else else
{ {
...@@ -1594,6 +1595,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -1594,6 +1595,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
tree gnu_list = NULL_TREE; tree gnu_list = NULL_TREE;
Entity_Id gnat_literal; 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); gnu_type = make_node (is_boolean ? BOOLEAN_TYPE : ENUMERAL_TYPE);
TYPE_PRECISION (gnu_type) = esize; TYPE_PRECISION (gnu_type) = esize;
TYPE_UNSIGNED (gnu_type) = is_unsigned; TYPE_UNSIGNED (gnu_type) = is_unsigned;
...@@ -1774,6 +1779,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -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))) && Is_Bit_Packed_Array (Original_Array_Type (gnat_entity)))
esize = UI_To_Int (RM_Size (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 /* First subtypes of Character are treated as Character; otherwise
this should be an unsigned type if the base type is unsigned or 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 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) ...@@ -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 conversions to it and gives more leeway to the optimizer; but
this means that we will need to explicitly test for this case this means that we will need to explicitly test for this case
when we change the representation based on the RM size. */ 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))) && No (First_Literal (Etype (gnat_entity)))
&& Esize (gnat_entity) == RM_Size (gnat_entity) && Esize (gnat_entity) == RM_Size (gnat_entity)
&& esize == CHAR_TYPE_SIZE && esize == CHAR_TYPE_SIZE
...@@ -1808,8 +1822,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -1808,8 +1822,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnat_entity, "U", definition, true, gnat_entity, "U", definition, true,
debug_info_p)); debug_info_p));
TYPE_BIASED_REPRESENTATION_P (gnu_type) if (TREE_CODE (gnu_type) == INTEGER_TYPE)
= Has_Biased_Representation (gnat_entity); TYPE_BIASED_REPRESENTATION_P (gnu_type)
= Has_Biased_Representation (gnat_entity);
/* Do the same processing for Character subtypes as for types. */ /* Do the same processing for Character subtypes as for types. */
if (TYPE_STRING_FLAG (TREE_TYPE (gnu_type))) 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) ...@@ -3300,6 +3315,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
all_rep ? NULL_TREE : bitsize_zero_node, all_rep ? NULL_TREE : bitsize_zero_node,
NULL); 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 /* If there are entities in the chain corresponding to components
that we did not elaborate, ensure we elaborate their types if that we did not elaborate, ensure we elaborate their types if
they are Itypes. */ they are Itypes. */
...@@ -3966,8 +3990,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -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 /* If we should request stack realignment for a foreign convention
subprogram, do so. Note that this applies to task entry points subprogram, do so. Note that this applies to task entry points
in particular. */ in particular. */
if (FOREIGN_FORCE_REALIGN_STACK if (FOREIGN_FORCE_REALIGN_STACK && foreign)
&& Has_Foreign_Convention (gnat_entity))
prepend_one_attribute prepend_one_attribute
(&attr_list, ATTR_MACHINE_ATTRIBUTE, (&attr_list, ATTR_MACHINE_ATTRIBUTE,
get_identifier ("force_align_arg_pointer"), NULL_TREE, get_identifier ("force_align_arg_pointer"), NULL_TREE,
......
...@@ -1133,9 +1133,15 @@ make_type_from_size (tree type, tree size_tree, bool for_biased) ...@@ -1133,9 +1133,15 @@ make_type_from_size (tree type, tree size_tree, bool for_biased)
switch (TREE_CODE (type)) 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 INTEGER_TYPE:
case ENUMERAL_TYPE: case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
biased_p = (TREE_CODE (type) == INTEGER_TYPE biased_p = (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_BIASED_REPRESENTATION_P (type)); && TYPE_BIASED_REPRESENTATION_P (type));
......
...@@ -56,7 +56,8 @@ package Interfaces.C.Extensions is ...@@ -56,7 +56,8 @@ package Interfaces.C.Extensions is
-- C bool -- C bool
subtype bool is plain_char; type bool is new Boolean;
pragma Convention (C, bool);
-- 64-bit integer types -- 64-bit integer types
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment