OSDN Git Service

* exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on
[pf3gnuchains/gcc-fork.git] / gcc / ada / gcc-interface / decl.c
index 1fae317..c8b49e7 100644 (file)
 #define Has_Stdcall_Convention(E) \
   (!TARGET_64BIT && Convention (E) == Convention_Stdcall)
 #define Has_Thiscall_Convention(E) \
-  (!TARGET_64BIT && gnat_first_param_is_class (E))
+  (!TARGET_64BIT && is_cplusplus_method (E))
 #else
 #define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall)
-#define Has_Thiscall_Convention(E) (gnat_first_param_is_class (E))
+#define Has_Thiscall_Convention(E) (is_cplusplus_method (E))
 #endif
 #else
 #define Has_Stdcall_Convention(E) 0
@@ -124,8 +124,8 @@ typedef struct variant_desc_d {
   /* The value of the qualifier.  */
   tree qual;
 
-  /* The record associated with this variant.  */
-  tree record;
+  /* The type of the variant after transformation.  */
+  tree new_type;
 } variant_desc;
 
 DEF_VEC_O(variant_desc);
@@ -144,7 +144,6 @@ enum alias_set_op
 
 static void relate_alias_sets (tree, tree, enum alias_set_op);
 
-static bool gnat_first_param_is_class (Entity_Id) ATTRIBUTE_UNUSED;
 static bool allocatable_size_p (tree, bool);
 static void prepend_one_attribute_to (struct attrib **,
                                      enum attr_type, tree, tree, Node_Id);
@@ -3327,11 +3326,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                      {
                        tree old_variant = v->type;
                        tree new_variant = make_node (RECORD_TYPE);
+                       tree suffix
+                         = concat_name (DECL_NAME (gnu_variant_part),
+                                        IDENTIFIER_POINTER
+                                        (DECL_NAME (v->field)));
                        TYPE_NAME (new_variant)
-                         = DECL_NAME (TYPE_NAME (old_variant));
+                         = concat_name (TYPE_NAME (gnu_type),
+                                        IDENTIFIER_POINTER (suffix));
                        copy_and_substitute_in_size (new_variant, old_variant,
                                                     gnu_subst_list);
-                       v->record = new_variant;
+                       v->new_type = new_variant;
                      }
                }
              else
@@ -3435,7 +3439,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                            if (selected_variant)
                              gnu_cont_type = gnu_type;
                            else
-                             gnu_cont_type = v->record;
+                             gnu_cont_type = v->new_type;
                          }
                        else
                          /* The front-end may pass us "ghost" components if
@@ -5352,58 +5356,34 @@ rest_of_type_decl_compilation_no_defer (tree decl)
     }
 }
 
-/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY has
-   a first parameter with a class or equivalent type.
+/* 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
-   the one set for C++ methods (functions with METHOD_TYPE) by the back-end.
-   Now in Ada primitive operations are regular subprograms (e.g. you can have
-   common pointers to both) so we cannot compute an equivalent of METHOD_TYPE
-   and so we set the calling convention in an uniform way.  */
+   used for C++ methods (functions with METHOD_TYPE) by the back-end.  */
 
-static bool
-gnat_first_param_is_class (Entity_Id gnat_entity)
+bool
+is_cplusplus_method (Entity_Id gnat_entity)
 {
-  Entity_Id gnat_param = First_Formal_With_Extras (gnat_entity);
-  Entity_Id gnat_type;
-  Node_Id node;
-
-  if (No (gnat_param))
-    return false;
+  if (Convention (gnat_entity) != Convention_CPP)
+    return False;
 
-  gnat_type = Underlying_Type (Etype (gnat_param));
+  /* This is the main case: C++ method imported as a primitive operation.  */
+  if (Is_Dispatching_Operation (gnat_entity))
+    return True;
 
-  /* This is the main case.  Note that we must return the same value for
-     regular tagged types and CW types since dispatching calls have a CW
-     type on the caller side and a tagged type on the callee side.  */
-  if (Is_Tagged_Type (gnat_type))
+  /* 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_CPP_Class (gnat_type))
-    return True;
-
-  /* The language-level "protected" calling convention doesn't distinguish
-     tagged protected types from non-tagged protected types (e.g. you can
-     have common pointers to both) so we must use a single low-level calling
-     convention for it.  Since tagged protected types can be derived from
-     simple limited interfaces, we need to pick the calling convention of
-     the latters.  */
-  if (Is_Protected_Record_Type (gnat_type))
+  if (Is_Constructor (gnat_entity))
     return True;
 
-  /* If this is the special E_Subprogram_Type built for the declaration of
-     an access to protected subprogram type, the first parameter will have
-     type Address, but we must return true to be consistent with above.  */
-  if (Is_Itype (gnat_entity)
-      && Present (node = Associated_Node_For_Itype (gnat_entity))
-      && Nkind (node) == N_Full_Type_Declaration
-      && Ekind (Defining_Identifier (node)) == E_Access_Subprogram_Type
-      && Present (node = Original_Access_Type (Defining_Identifier (node)))
-      && (Ekind (node) == E_Access_Protected_Subprogram_Type
-         || Ekind (node) == E_Anonymous_Access_Protected_Subprogram_Type))
+  /* This is set on the E_Subprogram_Type built for a dispatching call.  */
+  if (Is_Dispatch_Table_Entity (gnat_entity))
     return True;
 
   return False;
@@ -8190,7 +8170,7 @@ build_variant_list (tree qual_union_type, VEC(subst_pair,heap) *subst_list,
          v->type = variant_type;
          v->field = gnu_field;
          v->qual = qual;
-         v->record = NULL_TREE;
+         v->new_type = NULL_TREE;
 
          /* Recurse on the variant subpart of the variant, if any.  */
          variant_subpart = get_variant_part (variant_type);
@@ -8963,7 +8943,9 @@ create_variant_part_from (tree old_variant_part,
 
   /* First create the type of the variant part from that of the old one.  */
   new_union_type = make_node (QUAL_UNION_TYPE);
-  TYPE_NAME (new_union_type) = DECL_NAME (TYPE_NAME (old_union_type));
+  TYPE_NAME (new_union_type)
+    = concat_name (TYPE_NAME (record_type),
+                  IDENTIFIER_POINTER (DECL_NAME (old_variant_part)));
 
   /* If the position of the variant part is constant, subtract it from the
      size of the type of the parent to get the new size.  This manual CSE
@@ -8997,7 +8979,7 @@ create_variant_part_from (tree old_variant_part,
        continue;
 
       /* Retrieve the list of fields already added to the new variant.  */
-      new_variant = v->record;
+      new_variant = v->new_type;
       field_list = TYPE_FIELDS (new_variant);
 
       /* If the old variant had a variant subpart, we need to create a new