Commit 50477551 by Eric Botcazou Committed by Pierre-Marie de Rodat

[Ada] Complete implementation of RM C.6(19) clause

This ensures that the compiler fully implements the C.6(19) clause of
the Ada Reference Manual and gives a warning when the clause does change
the passing mechanism of the affected parameter.

2018-12-11  Eric Botcazou  <ebotcazou@adacore.com>

gcc/ada/

	* fe.h (Is_Atomic_Object): Declare.
	(Is_Volatile_Object): Likewise.
	* gcc-interface/trans.c (atomic_or_volatile_copy_required_p):
	New.
	(Call_to_gnu): Generate a copy for an actual parameter passed by
	reference if the conditions set forth by RM C.6(19) are met and
	specificially deal with an atomic actual parameter.

gcc/testsuite/

	* gnat.dg/atomic11.adb, gnat.dg/atomic11_pkg1.ads,
	gnat.dg/atomic11_pkg2.ads: New testcase.

From-SVN: r266993
parent f3e0577c
2018-12-11 Eric Botcazou <ebotcazou@adacore.com>
* fe.h (Is_Atomic_Object): Declare.
(Is_Volatile_Object): Likewise.
* gcc-interface/trans.c (atomic_or_volatile_copy_required_p):
New.
(Call_to_gnu): Generate a copy for an actual parameter passed by
reference if the conditions set forth by RM C.6(19) are met and
specificially deal with an atomic actual parameter.
2018-12-11 Piotr Trojanek <trojanek@adacore.com>
* sem_util.adb (Is_Subprogram_Stub_Without_Prior_Declaration):
......
......@@ -281,13 +281,17 @@ extern Boolean Is_OK_Static_Subtype (Entity_Id);
#define Defining_Entity sem_util__defining_entity
#define First_Actual sem_util__first_actual
#define Next_Actual sem_util__next_actual
#define Is_Atomic_Object sem_util__is_atomic_object
#define Is_Variable_Size_Record sem_util__is_variable_size_record
#define Is_Volatile_Object sem_util__is_volatile_object
#define Requires_Transient_Scope sem_util__requires_transient_scope
extern Entity_Id Defining_Entity (Node_Id);
extern Node_Id First_Actual (Node_Id);
extern Node_Id Next_Actual (Node_Id);
extern Boolean Is_Atomic_Object (Node_Id);
extern Boolean Is_Variable_Size_Record (Entity_Id Id);
extern Boolean Is_Volatile_Object (Node_Id);
extern Boolean Requires_Transient_Scope (Entity_Id);
/* sinfo: */
......
......@@ -4936,6 +4936,35 @@ create_init_temporary (const char *prefix, tree gnu_init, tree *gnu_init_stmt,
return gnu_temp;
}
/* Return whether ACTUAL parameter corresponding to FORMAL_TYPE must be passed
by copy in a call as per RM C.6(19). Note that we use the same predicates
as in the front-end for RM C.6(12) because it's purely a legality issue. */
static bool
atomic_or_volatile_copy_required_p (Node_Id actual, Entity_Id formal_type)
{
/* We should not have a scalar type here because such a type is passed
by copy. But the Interlocked routines in System.Aux_DEC force some
of the their scalar parameters to be passed by reference so we need
to preserve that if we do not want to break the interface. */
if (Is_Scalar_Type (formal_type))
return false;
if (Is_Atomic_Object (actual) && !Is_Atomic (formal_type))
{
post_error ("?atomic actual passed by copy (RM C.6(19))", actual);
return true;
}
if (Is_Volatile_Object (actual) && !Is_Volatile (formal_type))
{
post_error ("?volatile actual passed by copy (RM C.6(19))", actual);
return true;
}
return false;
}
/* Subroutine of gnat_to_gnu to translate gnat_node, either an N_Function_Call
or an N_Procedure_Call_Statement, to a GCC tree, which is returned.
GNU_RESULT_TYPE_P is a pointer to where we should place the result type.
......@@ -5150,13 +5179,18 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
= build_compound_expr (TREE_TYPE (gnu_name), init, gnu_name);
}
/* If we are passing a non-addressable parameter by reference, pass the
address of a copy. In the In Out or Out case, set up to copy back
out after the call. */
/* If we are passing a non-addressable actual parameter by reference,
pass the address of a copy and, in the In Out or Out case, set up
to copy back after the call. We also need to do that if the actual
parameter is atomic or volatile but the formal parameter is not. */
if (is_by_ref_formal_parm
&& (gnu_name_type = gnat_to_gnu_type (Etype (gnat_name)))
&& !addressable_p (gnu_name, gnu_name_type))
&& (!addressable_p (gnu_name, gnu_name_type)
|| (Comes_From_Source (gnat_node)
&& atomic_or_volatile_copy_required_p (gnat_actual,
gnat_formal_type))))
{
const bool atomic_p = atomic_access_required_p (gnat_actual, &sync);
tree gnu_orig = gnu_name, gnu_temp, gnu_stmt;
/* Do not issue warnings for CONSTRUCTORs since this is not a copy
......@@ -5236,6 +5270,8 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
}
/* Create an explicit temporary holding the copy. */
if (atomic_p)
gnu_name = build_atomic_load (gnu_name, sync);
gnu_temp
= create_init_temporary ("A", gnu_name, &gnu_stmt, gnat_actual);
......@@ -5256,8 +5292,13 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
(TREE_OPERAND (TREE_OPERAND (gnu_orig, 1), 1)))
gnu_orig = TREE_OPERAND (gnu_orig, 2);
if (atomic_p)
gnu_stmt
= build_atomic_store (gnu_orig, gnu_temp, sync);
else
gnu_stmt
= build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_orig, gnu_temp);
= build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_orig,
gnu_temp);
set_expr_location_from_node (gnu_stmt, gnat_node);
append_to_statement_list (gnu_stmt, &gnu_after_list);
......
2018-12-11 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/atomic11.adb, gnat.dg/atomic11_pkg1.ads,
gnat.dg/atomic11_pkg2.ads: New testcase.
2018-12-11 Ed Schonberg <schonberg@adacore.com>
* gnat.dg/aspect1.adb, gnat.dg/aspect1_horizontal.adb,
......
-- { dg-do compile }
with Atomic11_Pkg1; use Atomic11_Pkg1;
procedure Atomic11 is
R1 : Rec1;
pragma Atomic (R1);
R2 : Rec2;
pragma Volatile (R2);
begin
R1.I := 0;
Proc1 (R1); -- { dg-warning "atomic actual passed by copy" }
R2.A(1) := 0;
Proc1 (R1); -- { dg-warning "atomic actual passed by copy" }
Proc2 (R2); -- { dg-warning "volatile actual passed by copy" }
end;
with Atomic11_Pkg2;
package Atomic11_Pkg1 is
type Rec1 is record
I : Integer;
end record;
procedure Proc1 (R : Rec1);
pragma Import (C, Proc1);
type Arr is array (Positive range <>) of Integer;
type Rec2 is record
A : Arr (1 .. Atomic11_Pkg2.Max);
end record;
procedure Proc2 (R : Rec2);
end Atomic11_Pkg1;
package Atomic11_Pkg2 is
function Max return Positive;
end Atomic11_Pkg2;
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