Commit 28dd0055 by Eric Botcazou Committed by Eric Botcazou

exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on the…

exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on the designated subprogram type and also set...

	* exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on
	the designated subprogram type and also set Is_Dispatch_Table_Entity.
	(Expand_Interface_Thunk): Propagate the convention on the thunk.
	(Set_CPP_Constructors_Old): Set Is_Constructor and Convention_CPP on
	the internal view of the constructors.
	(Set_CPP_Constructors): Likewise.
	* sem_prag.adb (Analyze_Pragma) <Pragma_CPP_Constructor>: Set the
	convention on the function.
	* gcc-interface/gigi.h (is_cplusplus_method): Declare.
	* gcc-interface/decl.c (Has_Thiscall_Convention): New macro.
	(gnat_to_gnu_entity) <E_Subprogram_Type>: Test it to set the `thiscall'
	calling convention
	(get_minimal_subprog_decl): Likewise.
	(is_cplusplus_method): New predicate.
	* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Access>: Issue an
	error on access to C++ constructor or member function.

From-SVN: r189199
parent d4d05b52
2012-07-03 Eric Botcazou <ebotcazou@adacore.com> 2012-07-03 Eric Botcazou <ebotcazou@adacore.com>
* exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on
the designated subprogram type and also set Is_Dispatch_Table_Entity.
(Expand_Interface_Thunk): Propagate the convention on the thunk.
(Set_CPP_Constructors_Old): Set Is_Constructor and Convention_CPP on
the internal view of the constructors.
(Set_CPP_Constructors): Likewise.
* sem_prag.adb (Analyze_Pragma) <Pragma_CPP_Constructor>: Set the
convention on the function.
* gcc-interface/gigi.h (is_cplusplus_method): Declare.
* gcc-interface/decl.c (Has_Thiscall_Convention): New macro.
(gnat_to_gnu_entity) <E_Subprogram_Type>: Test it to set the `thiscall'
calling convention
(get_minimal_subprog_decl): Likewise.
(is_cplusplus_method): New predicate.
* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Access>: Issue an
error on access to C++ constructor or member function.
2012-07-03 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/utils.c (gnat_pushdecl): Set TYPE_CONTEXT for types * gcc-interface/utils.c (gnat_pushdecl): Set TYPE_CONTEXT for types
attached to a TYPE_DECL. attached to a TYPE_DECL.
......
...@@ -803,6 +803,11 @@ package body Exp_Disp is ...@@ -803,6 +803,11 @@ package body Exp_Disp is
Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node); Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node);
Set_Etype (Subp_Typ, Res_Typ); Set_Etype (Subp_Typ, Res_Typ);
Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp)); Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp));
Set_Convention (Subp_Typ, Convention (Subp));
-- Notify gigi that the designated type is a dispatching primitive
Set_Is_Dispatch_Table_Entity (Subp_Typ);
-- Create a new list of parameters which is a copy of the old formal -- Create a new list of parameters which is a copy of the old formal
-- list including the creation of a new set of matching entities. -- list including the creation of a new set of matching entities.
...@@ -1850,6 +1855,7 @@ package body Exp_Disp is ...@@ -1850,6 +1855,7 @@ package body Exp_Disp is
Thunk_Id := Make_Temporary (Loc, 'T'); Thunk_Id := Make_Temporary (Loc, 'T');
Set_Is_Thunk (Thunk_Id); Set_Is_Thunk (Thunk_Id);
Set_Convention (Thunk_Id, Convention (Prim));
-- Procedure case -- Procedure case
...@@ -8468,8 +8474,9 @@ package body Exp_Disp is ...@@ -8468,8 +8474,9 @@ package body Exp_Disp is
Set_Init_Proc (Typ, Init); Set_Init_Proc (Typ, Init);
Set_Is_Imported (Init); Set_Is_Imported (Init);
Set_Is_Constructor (Init);
Set_Interface_Name (Init, Interface_Name (E)); Set_Interface_Name (Init, Interface_Name (E));
Set_Convention (Init, Convention_C); Set_Convention (Init, Convention_CPP);
Set_Is_Public (Init); Set_Is_Public (Init);
Set_Has_Completion (Init); Set_Has_Completion (Init);
end if; end if;
...@@ -8562,8 +8569,9 @@ package body Exp_Disp is ...@@ -8562,8 +8569,9 @@ package body Exp_Disp is
Parameter_Specifications => Parms)); Parameter_Specifications => Parms));
Set_Is_Imported (Constructor_Id); Set_Is_Imported (Constructor_Id);
Set_Is_Constructor (Constructor_Id);
Set_Interface_Name (Constructor_Id, Interface_Name (E)); Set_Interface_Name (Constructor_Id, Interface_Name (E));
Set_Convention (Constructor_Id, Convention_C); Set_Convention (Constructor_Id, Convention_CPP);
Set_Is_Public (Constructor_Id); Set_Is_Public (Constructor_Id);
Set_Has_Completion (Constructor_Id); Set_Has_Completion (Constructor_Id);
......
...@@ -50,19 +50,23 @@ ...@@ -50,19 +50,23 @@
#include "ada-tree.h" #include "ada-tree.h"
#include "gigi.h" #include "gigi.h"
/* Convention_Stdcall should be processed in a specific way on 32 bits /* "stdcall" and "thiscall" conventions should be processed in a specific way
Windows targets only. The macro below is a helper to avoid having to on 32-bit x86/Windows only. The macros below are helpers to avoid having
check for a Windows specific attribute throughout this unit. */ to check for a Windows specific attribute throughout this unit. */
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
#ifdef TARGET_64BIT #ifdef TARGET_64BIT
#define Has_Stdcall_Convention(E) \ #define Has_Stdcall_Convention(E) \
(!TARGET_64BIT && Convention (E) == Convention_Stdcall) (!TARGET_64BIT && Convention (E) == Convention_Stdcall)
#define Has_Thiscall_Convention(E) \
(!TARGET_64BIT && is_cplusplus_method (E))
#else #else
#define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall) #define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall)
#define Has_Thiscall_Convention(E) (is_cplusplus_method (E))
#endif #endif
#else #else
#define Has_Stdcall_Convention(E) 0 #define Has_Stdcall_Convention(E) 0
#define Has_Thiscall_Convention(E) 0
#endif #endif
/* Stack realignment is necessary for functions with foreign conventions when /* Stack realignment is necessary for functions with foreign conventions when
...@@ -4413,6 +4417,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) ...@@ -4413,6 +4417,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
(&attr_list, ATTR_MACHINE_ATTRIBUTE, (&attr_list, ATTR_MACHINE_ATTRIBUTE,
get_identifier ("stdcall"), NULL_TREE, get_identifier ("stdcall"), NULL_TREE,
gnat_entity); gnat_entity);
else if (Has_Thiscall_Convention (gnat_entity))
prepend_one_attribute_to
(&attr_list, ATTR_MACHINE_ATTRIBUTE,
get_identifier ("thiscall"), NULL_TREE,
gnat_entity);
/* 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 in subprogram, do so. Note that this applies to task entry points in
...@@ -5276,6 +5285,10 @@ get_minimal_subprog_decl (Entity_Id gnat_entity) ...@@ -5276,6 +5285,10 @@ get_minimal_subprog_decl (Entity_Id gnat_entity)
prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE, prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE,
get_identifier ("stdcall"), NULL_TREE, get_identifier ("stdcall"), NULL_TREE,
gnat_entity); gnat_entity);
else if (Has_Thiscall_Convention (gnat_entity))
prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE,
get_identifier ("thiscall"), NULL_TREE,
gnat_entity);
if (No (Interface_Name (gnat_entity)) && gnu_ext_name == gnu_entity_name) if (No (Interface_Name (gnat_entity)) && gnu_ext_name == gnu_entity_name)
gnu_ext_name = NULL_TREE; gnu_ext_name = NULL_TREE;
...@@ -5285,6 +5298,39 @@ get_minimal_subprog_decl (Entity_Id gnat_entity) ...@@ -5285,6 +5298,39 @@ get_minimal_subprog_decl (Entity_Id gnat_entity)
false, true, true, true, attr_list, gnat_entity); false, true, true, true, attr_list, gnat_entity);
} }
/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY is
a C++ imported method or equivalent.
We use the predicate on 32-bit x86/Windows to find out whether we need to
use the "thiscall" calling convention for GNAT_ENTITY. This convention is
used for C++ methods (functions with METHOD_TYPE) by the back-end. */
bool
is_cplusplus_method (Entity_Id gnat_entity)
{
if (Convention (gnat_entity) != Convention_CPP)
return False;
/* This is the main case: C++ method imported as a primitive operation. */
if (Is_Dispatching_Operation (gnat_entity))
return True;
/* A thunk needs to be handled like its associated primitive operation. */
if (Is_Subprogram (gnat_entity) && Is_Thunk (gnat_entity))
return True;
/* C++ classes with no virtual functions can be imported as limited
record types, but we need to return true for the constructors. */
if (Is_Constructor (gnat_entity))
return True;
/* This is set on the E_Subprogram_Type built for a dispatching call. */
if (Is_Dispatch_Table_Entity (gnat_entity))
return True;
return False;
}
/* Finalize the processing of From_With_Type incomplete types. */ /* Finalize the processing of From_With_Type incomplete types. */
void void
......
...@@ -116,6 +116,10 @@ extern tree get_unpadded_type (Entity_Id gnat_entity); ...@@ -116,6 +116,10 @@ extern tree get_unpadded_type (Entity_Id gnat_entity);
alias is already present, in which case it is returned instead. */ alias is already present, in which case it is returned instead. */
extern tree get_minimal_subprog_decl (Entity_Id gnat_entity); extern tree get_minimal_subprog_decl (Entity_Id gnat_entity);
/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY is
a C++ imported method or equivalent. */
extern bool is_cplusplus_method (Entity_Id gnat_entity);
/* Create a record type that contains a SIZE bytes long field of TYPE with a /* Create a record type that contains a SIZE bytes long field of TYPE with a
starting bit position so that it is aligned to ALIGN bits, and leaving at starting bit position so that it is aligned to ALIGN bits, and leaving at
least ROOM bytes free before the field. BASE_ALIGN is the alignment the least ROOM bytes free before the field. BASE_ALIGN is the alignment the
......
...@@ -1424,6 +1424,15 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) ...@@ -1424,6 +1424,15 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
TREE_NO_TRAMPOLINE (gnu_expr) = TREE_CONSTANT (gnu_expr) = 1; TREE_NO_TRAMPOLINE (gnu_expr) = TREE_CONSTANT (gnu_expr) = 1;
} }
/* For 'Access, issue an error message if the prefix is a C++ method
since it can use a special calling convention on some platforms,
which cannot be propagated to the access type. */
else if (attribute == Attr_Access
&& Nkind (Prefix (gnat_node)) == N_Identifier
&& is_cplusplus_method (Entity (Prefix (gnat_node))))
post_error ("access to C++ constructor or member function not allowed",
gnat_node);
/* For other address attributes applied to a nested function, /* For other address attributes applied to a nested function,
find an inner ADDR_EXPR and annotate it so that we can issue find an inner ADDR_EXPR and annotate it so that we can issue
a useful warning with -Wtrampolines. */ a useful warning with -Wtrampolines. */
......
...@@ -7865,6 +7865,7 @@ package body Sem_Prag is ...@@ -7865,6 +7865,7 @@ package body Sem_Prag is
Set_Has_Completion (Def_Id); Set_Has_Completion (Def_Id);
Set_Is_Constructor (Def_Id); Set_Is_Constructor (Def_Id);
Set_Convention (Def_Id, Convention_CPP);
-- Imported C++ constructors are not dispatching primitives -- Imported C++ constructors are not dispatching primitives
-- because in C++ they don't have a dispatch table slot. -- because in C++ they don't have a dispatch table slot.
......
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