]> gcc.gnu.org Git - gcc.git/commitdiff
Pass empty class parameters like C.
authorJason Merrill <jason@redhat.com>
Wed, 13 Apr 2016 20:11:20 +0000 (16:11 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 13 Apr 2016 20:11:20 +0000 (16:11 -0400)
* call.c (pass_as_empty_struct, empty_class_arg): New.
(type_passed_as, build_x_va_arg): Use pass_as_empty_struct.
(build_call_a): Use empty_class_arg.
* cp-tree.h (CPTI_EMPTY_STRUCT, empty_struct_type): New.
* decl.c (cxx_init_decl_processing): Create empty_struct_type.

From-SVN: r234959

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c

index 837a58c338f1a4e014fbf3ecdd7cd536753f58d4..28541bc7857ee33b2498860835d8e0ade4a43052 100644 (file)
@@ -1,3 +1,12 @@
+2016-04-13  Jason Merrill  <jason@redhat.com>
+
+       Pass empty class parameters like C.
+       * call.c (pass_as_empty_struct, empty_class_arg): New.
+       (type_passed_as, build_x_va_arg): Use pass_as_empty_struct.
+       (build_call_a): Use empty_class_arg.
+       * cp-tree.h (CPTI_EMPTY_STRUCT, empty_struct_type): New.
+       * decl.c (cxx_init_decl_processing): Create empty_struct_type.
+
 2016-04-13  Jason Merrill  <jason@redhat.com>
 
        PR c++/70627
index ed234904a63de40d13e0a087f0929ca60c1b3dc9..84b62436da3aa460c52d6d929b93636b8939df69 100644 (file)
@@ -214,6 +214,8 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
                            tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
+static bool pass_as_empty_struct (tree type);
+static tree empty_class_arg (tree);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
    NAME can take many forms...  */
@@ -383,12 +385,11 @@ build_call_a (tree function, int n, tree *argarray)
     for (i = 0; i < n; i++)
       {
        tree arg = CALL_EXPR_ARG (function, i);
-       if (is_empty_class (TREE_TYPE (arg))
-           && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+       tree type = TREE_TYPE (arg);
+       if (is_really_empty_class (type)
+           && ! TREE_ADDRESSABLE (type))
          {
-           tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
-           arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
-           CALL_EXPR_ARG (function, i) = arg;
+           CALL_EXPR_ARG (function, i) = empty_class_arg (arg);
          }
       }
 
@@ -6872,6 +6873,14 @@ build_x_va_arg (source_location loc, tree expr, tree type)
       expr = build_va_arg (loc, expr, ref);
       return convert_from_reference (expr);
     }
+  else if (is_really_empty_class (type) && !TREE_ADDRESSABLE (type))
+    {
+      /* Do the reverse of empty_class_arg.  */
+      tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
+      expr = build_va_arg (loc, expr, etype);
+      tree ec = build0 (EMPTY_CLASS_EXPR, type);
+      return build2 (COMPOUND_EXPR, type, expr, ec);
+    }
 
   return build_va_arg (loc, expr, type);
 }
@@ -6968,6 +6977,34 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum,
   return arg;
 }
 
+/* Return true iff TYPE should be passed and returned as a size 0 type rather
+   than its normal size, for compatibility with C.  */
+
+static bool
+pass_as_empty_struct (tree type)
+{
+  return (abi_version_at_least (10)
+         && type != error_mark_node
+         && COMPLETE_TYPE_P (type)
+         && !TREE_ADDRESSABLE (type)
+         && is_really_empty_class (type));
+}
+
+/* Adjust the value VAL of empty class type TYPE for argument passing.
+   Keep this synced with build_x_va_arg.  */
+
+static tree
+empty_class_arg (tree val)
+{
+  /* Don't pass empty class objects by value.  This is useful
+     for tags in STL, which are used to control overload resolution.
+     We don't need to handle other cases of copying empty classes.  */
+  tree type = TREE_TYPE (val);
+  tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
+  tree empty = build0 (EMPTY_CLASS_EXPR, etype);
+  return build2 (COMPOUND_EXPR, etype, val, empty);
+}
+
 /* Returns the type which will really be used for passing an argument of
    type TYPE.  */
 
@@ -6986,6 +7023,8 @@ type_passed_as (tree type)
           && COMPLETE_TYPE_P (type)
           && tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
     type = integer_type_node;
+  else if (pass_as_empty_struct (type))
+    type = empty_struct_type;
 
   return type;
 }
index a3cd834a1055745bc65127534ec3d308cad81ac5..faea452531c66504b3cbe99cb62196d35fde4c2a 100644 (file)
@@ -1150,6 +1150,8 @@ enum cp_tree_index
     CPTI_NULLPTR,
     CPTI_NULLPTR_TYPE,
 
+    CPTI_EMPTY_STRUCT,
+
     CPTI_MAX
 };
 
@@ -1185,6 +1187,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 #define current_aggr                   cp_global_trees[CPTI_AGGR_TAG]
 #define nullptr_node                   cp_global_trees[CPTI_NULLPTR]
 #define nullptr_type_node              cp_global_trees[CPTI_NULLPTR_TYPE]
+#define empty_struct_type              cp_global_trees[CPTI_EMPTY_STRUCT]
 
 /* We cache these tree nodes so as to call get_identifier less
    frequently.  */
index 380bc79ea53292266ded6e6225315136159a7b0d..5ca426bbd03c32b7157d8a223131d57d7133a169 100644 (file)
@@ -4180,6 +4180,10 @@ cxx_init_decl_processing (void)
     nullptr_node = build_int_cst (nullptr_type_node, 0);
   }
 
+  empty_struct_type = make_node (RECORD_TYPE);
+  finish_builtin_struct (empty_struct_type, "__empty_struct",
+                        NULL_TREE, NULL_TREE);
+
   abort_fndecl
     = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
                            ECF_NORETURN | ECF_NOTHROW);
This page took 0.079056 seconds and 5 git commands to generate.