OSDN Git Service

* exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Jul 2012 08:29:04 +0000 (08:29 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Jul 2012 08:29:04 +0000 (08:29 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@189200 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/exp_disp.adb
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/gigi.h
gcc/ada/gcc-interface/trans.c
gcc/ada/sem_prag.adb

index 1e84e74..f511a7f 100644 (file)
@@ -1,5 +1,24 @@
 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
        attached to a TYPE_DECL.
 
index e065538..12cfbdc 100644 (file)
@@ -803,6 +803,11 @@ package body Exp_Disp is
       Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node);
       Set_Etype          (Subp_Typ, Res_Typ);
       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
       --  list including the creation of a new set of matching entities.
@@ -1842,6 +1847,7 @@ package body Exp_Disp is
 
       Thunk_Id := Make_Temporary (Loc, 'T');
       Set_Is_Thunk (Thunk_Id);
+      Set_Convention (Thunk_Id, Convention (Prim));
 
       --  Procedure case
 
@@ -8460,8 +8466,9 @@ package body Exp_Disp is
 
                Set_Init_Proc (Typ, Init);
                Set_Is_Imported    (Init);
+               Set_Is_Constructor (Init);
                Set_Interface_Name (Init, Interface_Name (E));
-               Set_Convention     (Init, Convention_C);
+               Set_Convention     (Init, Convention_CPP);
                Set_Is_Public      (Init);
                Set_Has_Completion (Init);
             end if;
@@ -8554,8 +8561,9 @@ package body Exp_Disp is
                   Parameter_Specifications => Parms));
 
             Set_Is_Imported    (Constructor_Id);
+            Set_Is_Constructor (Constructor_Id);
             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_Has_Completion (Constructor_Id);
 
index 2215ac8..c8b49e7 100644 (file)
 #include "ada-tree.h"
 #include "gigi.h"
 
-/* Convention_Stdcall should be processed in a specific way on 32 bits
-   Windows targets only.  The macro below is a helper to avoid having to
-   check for a Windows specific attribute throughout this unit.  */
+/* "stdcall" and "thiscall" conventions should be processed in a specific way
+   on 32-bit x86/Windows only.  The macros below are helpers to avoid having
+   to check for a Windows specific attribute throughout this unit.  */
 
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 #ifdef TARGET_64BIT
 #define Has_Stdcall_Convention(E) \
   (!TARGET_64BIT && Convention (E) == Convention_Stdcall)
+#define Has_Thiscall_Convention(E) \
+  (!TARGET_64BIT && is_cplusplus_method (E))
 #else
 #define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall)
+#define Has_Thiscall_Convention(E) (is_cplusplus_method (E))
 #endif
 #else
 #define Has_Stdcall_Convention(E) 0
+#define Has_Thiscall_Convention(E) 0
 #endif
 
 /* Stack realignment is necessary for functions with foreign conventions when
@@ -4415,6 +4419,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
            (&attr_list, ATTR_MACHINE_ATTRIBUTE,
             get_identifier ("stdcall"), NULL_TREE,
             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
           subprogram, do so.  Note that this applies to task entry points in
@@ -5295,6 +5304,10 @@ get_minimal_subprog_decl (Entity_Id gnat_entity)
     prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE,
                              get_identifier ("stdcall"), NULL_TREE,
                              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)
     gnu_ext_name = NULL_TREE;
@@ -5343,6 +5356,39 @@ rest_of_type_decl_compilation_no_defer (tree decl)
     }
 }
 
+/* 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.  */
 
 void
index 9550b4a..5a766b4 100644 (file)
@@ -123,6 +123,10 @@ extern tree get_unpadded_type (Entity_Id gnat_entity);
    alias is already present, in which case it is returned instead.  */
 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
     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
index 1c9da73..ba07832 100644 (file)
@@ -1395,6 +1395,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;
        }
 
+      /* 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,
         find an inner ADDR_EXPR and annotate it so that we can issue
         a useful warning with -Wtrampolines.  */
index e175a72..d7d5229 100644 (file)
@@ -7785,6 +7785,7 @@ package body Sem_Prag is
 
                Set_Has_Completion (Def_Id);
                Set_Is_Constructor (Def_Id);
+               Set_Convention (Def_Id, Convention_CPP);
 
                --  Imported C++ constructors are not dispatching primitives
                --  because in C++ they don't have a dispatch table slot.