On Wed, Jan 27, 2016 at 5:46 AM, H.J. Lu <hjl.to...@gmail.com> wrote:
> On Wed, Jan 27, 2016 at 1:03 AM, Marc Glisse <marc.gli...@inria.fr> wrote:
>> On Wed, 27 Jan 2016, Jakub Jelinek wrote:
>>
>>> On Wed, Jan 27, 2016 at 09:10:14AM +0100, Marc Glisse wrote:
>>>>>
>>>>> Revised:
>>>>>
>>>>> /* Returns true if TYPE is POD of one-byte or less in size for the
>>>>> purpose
>>>>>  of layout and an empty class or an class with empty classes.  */
>>>>>
>>>>> static bool
>>>>> is_empty_record (tree type)
>>>>> {
>>>>> if (type == error_mark_node)
>>>>>   return false;
>>>>>
>>>>> if (!CLASS_TYPE_P (type))
>>>>>   return false;
>>>>>
>>>>> if (CLASSTYPE_NON_LAYOUT_POD_P (type))
>>>>>   return false;
>>>>>
>>>>> gcc_assert (COMPLETE_TYPE_P (type));
>>>>>
>>>>> if (CLASSTYPE_EMPTY_P (type))
>>>>>   return true;
>>>>>
>>>>> if (int_size_in_bytes (type) > 1)
>>>>>   return false;
>>>>
>>>>
>>>> That's completely arbitrary :-(
>>>
>>>
>>> Yeah.  Because (adapted to be compilable with C):
>>> struct A1 {}; struct A2 {};
>>> struct B1 { struct A1 a; struct A2 b; }; struct B2 { struct A1 a; struct
>>> A2 b; };
>>> struct C1 { struct B1 a; struct B2 b; }; struct C2 { struct B1 a; struct
>>> B2 b; };
>>> struct D1 { struct C1 a; struct C2 b; }; struct D2 { struct C1 a; struct
>>> C2 b; };
>>> struct E1 { struct D1 a; struct D2 b; }; struct E2 { struct D1 a; struct
>>> D2 b; };
>>> struct F1 { struct E1 a; struct E2 b; }; struct F2 { struct E1 a; struct
>>> E2 b; };
>>> struct G1 { struct F1 a; struct F2 b; }; struct G2 { struct F1 a; struct
>>> F2 b; };
>>> struct H1 { struct G1 a; struct G2 b; }; struct H2 { struct G1 a; struct
>>> G2 b; };
>>> struct I1 { struct H1 a; struct H2 b; }; struct I2 { struct H1 a; struct
>>> H2 b; };
>>> struct J1 { struct I1 a; struct I2 b; }; struct J2 { struct I1 a; struct
>>> I2 b; };
>>> struct K1 { struct J1 a; struct J2 b; };
>>> int v;
>>> __attribute__((noinline, noclone))
>>> struct K1 foo (int a, struct K1 x, int b)
>>> {
>>>  v = a + b;
>>>  return x;
>>> }
>>> struct K1 k, m;
>>> void
>>> bar (void)
>>> {
>>>  m = foo (1, k, 2);
>>> }
>>> then would have a different calling convention between C and C++,
>>> so where is the argument that we change anything just to make the two
>>> compatible?  Though, of course, those two will never be compatible,
>>> it is enough to add struct L1 { int a; struct K1 b; int c; }; and
>>> that structure has 1024+8 bytes in C++ and 8 bytes in C.
>>
>>
>> I don't know how empty classes are used in C in practice, but it could make
>> sense to have ABI compatibility as long as no empty struct is used as a
>> member of another struct (I also suggested an attribute to let C++ use the
>> same layout as C here: PR63579). But then the usual definition of empty
>> would be sufficient.
>>
>>> As clang generates different code for the above between C and C++, it
>>> clearly special cases for some reason just the most common case.
>>> IMHO it is not worth to change GCC ABI...
>>
>>
>> I was interested in this change because it improves C++, C compatibility was
>> a convenient excuse ;-)
>>
>
> I opened  a clang bug:
>
> https://llvm.org/bugs/show_bug.cgi?id=26337
>
> I propose the following definitions:
>
> i. An empty record is:
>    1. A class without member.  Or
>    2. An array of empty records.  Or
>    3. A class with empty records.
> ii. An empty record type for parameter passing is POD for the purpose of 
> layout
> and
>    1. A class without member.  Or
>    2. A class with empty records.
>
> /* An empty record is:
>    1. A class without member.  Or
>    2. An array of empty records.  Or
>    3. A class with empty records.  */
>
> /* Returns true if TYPE is an empty record or an array of empty records.  */
>
> static bool
> is_empty_record_or_array_of_empty_record (tree type)
> {
>   if (CLASS_TYPE_P (type))
>     {
>       if (CLASSTYPE_EMPTY_P (type))
>         return true;
>
>       tree field;
>
>       for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
>         if (TREE_CODE (field) == FIELD_DECL
>             && !DECL_ARTIFICIAL (field)
>             && !is_empty_record_or_array_of_empty_record (TREE_TYPE (field)))
>           return false;
>       return true;
>     }
>   else if (TREE_CODE (type) == ARRAY_TYPE)
>     return is_empty_record_or_array_of_empty_record (TREE_TYPE (type));
>   return false;
> }
>
> /* Returns true if TYPE is POD for the purpose of layout and
>    1. A class without member.  Or
>    2. A class with empty records.  */
>
> static bool
> is_empty_record_for_parm (tree type)
> {
>   if (type == error_mark_node)
>     return false;
>
>   if (!CLASS_TYPE_P (type))
>     return false;
>
>   if (CLASSTYPE_NON_LAYOUT_POD_P (type))
>     return false;
>
>   gcc_assert (COMPLETE_TYPE_P (type));
>
>   if (CLASSTYPE_EMPTY_P (type))
>     return true;
>
>   tree field;
>
>   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
>     if (TREE_CODE (field) == FIELD_DECL
>         && !DECL_ARTIFICIAL (field)
>         && !is_empty_record_or_array_of_empty_record (TREE_TYPE (field)))
>       return false;
>
>   return true;
> }
>

Here is the updated patch with new testcases.  OK for trunk?


-- 
H.J.
From 9a3aacb5b95b317a10e65b4ed80d3f490660b171 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.to...@gmail.com>
Date: Wed, 9 Dec 2015 12:48:07 -0800
Subject: [PATCH] Properly pass C++ empty class

Use 0 for empty record size in TARGET_GIMPLIFY_VA_ARG_EXPR.

	PR c++/60336
	PR middle-end/67239
	PR target/68355
	* config/aarch64/aarch64.c (aarch64_gimplify_va_arg_expr): Use 0
	for empty record size.
	* config/mep/mep.c (mep_gimplify_va_arg_expr): Likewise.
	* config/mips/mips.c (mips_std_gimplify_va_arg_expr): Likewise.
	(mips_gimplify_va_arg_expr): Likewise.
	* config/msp430/msp430.c (msp430_gimplify_va_arg_expr): Likewise.
	* config/pa/pa.c (hppa_gimplify_va_arg_expr): Likewise.
	* config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Likewise.
	* config/s390/s390.c (s390_gimplify_va_arg): Likewise.
	* config/sh/sh.c (sh_gimplify_va_arg_expr): Likewise.
	* config/sparc/sparc.c (sparc_gimplify_va_arg): Likewise.
	* config/spu/spu.c (spu_gimplify_va_arg_expr): Likewise.
	* config/stormy16/stormy16.c (xstormy16_gimplify_va_arg_expr):
	Likewise.
	* config/visium/visium.c (visium_gimplify_va_arg): Likewise.
	* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Likewise.
	* config/alpha/alpha.c (alpha_setup_incoming_varargs): Replace
	targetm.calls.function_arg_advance with function_arg_advance.
	(alpha_gimplify_va_arg_1): Use 0 for empty record size.
	* config/microblaze/microblaze.c (microblaze_expand_prologue):
	Replace targetm.calls.function_arg with function_arg.  Replace
	targetm.calls.function_arg_advance with function_arg_advance.
	* config/tilegx/tilegx.c (tilegx_setup_incoming_varargs): Replace
	targetm.calls.function_arg_advance with function_arg_advance.
	(tilegx_gimplify_va_arg_expr): Use 0 for empty record size.
	* config/tilepro/tilepro.c (tilepro_setup_incoming_varargs):
	Replace targetm.calls.function_arg_advance with
	function_arg_advance.
	(tilepro_gimplify_va_arg_expr): Use 0 for empty record size.
---
 gcc/config/aarch64/aarch64.c       |  3 ++-
 gcc/config/alpha/alpha.c           |  6 +++---
 gcc/config/mep/mep.c               |  3 ++-
 gcc/config/microblaze/microblaze.c | 11 +++++------
 gcc/config/mips/mips.c             |  6 ++++--
 gcc/config/msp430/msp430.c         |  3 ++-
 gcc/config/pa/pa.c                 |  3 ++-
 gcc/config/rs6000/rs6000.c         |  3 ++-
 gcc/config/s390/s390.c             |  3 ++-
 gcc/config/sh/sh.c                 |  3 ++-
 gcc/config/sparc/sparc.c           |  3 ++-
 gcc/config/spu/spu.c               |  3 ++-
 gcc/config/stormy16/stormy16.c     |  6 ++++--
 gcc/config/tilegx/tilegx.c         |  7 ++++---
 gcc/config/tilepro/tilepro.c       |  7 ++++---
 gcc/config/visium/visium.c         |  3 ++-
 gcc/config/xtensa/xtensa.c         |  3 ++-
 17 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index df3dec0..43fd394 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9605,7 +9605,8 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 
   stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist),
 		  f_stack, NULL_TREE);
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   align = aarch64_function_arg_alignment (mode, type) / BITS_PER_UNIT;
 
   dw_align = false;
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index e023d3b..c3c0513 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -6117,8 +6117,7 @@ alpha_setup_incoming_varargs (cumulative_args_t pcum, machine_mode mode,
   CUMULATIVE_ARGS cum = *get_cumulative_args (pcum);
 
   /* Skip the current argument.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&cum), mode, type,
-				      true);
+  function_arg_advance (pack_cumulative_args (&cum), mode, type, true);
 
 #if TARGET_ABI_OPEN_VMS
   /* For VMS, we allocate space for all 6 arg registers plus a count.
@@ -6304,7 +6303,8 @@ alpha_gimplify_va_arg_1 (tree type, tree base, tree offset,
   gimple_seq_add_seq (pre_p, internal_post);
 
   /* Update the offset field.  */
-  type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
+  bool empty_record = type && type_is_empty_record_p (type);
+  type_size = empty_record ? 0 : TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
   if (type_size == NULL || TREE_OVERFLOW (type_size))
     t = size_zero_node;
   else
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index 9c4cd86..f63ad57 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -3525,7 +3525,8 @@ mep_gimplify_va_arg_expr (tree valist, tree type,
 
   ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type);
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0);
 
   if (by_reference)
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index baff67a..e144ff1 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -2798,8 +2798,8 @@ microblaze_expand_prologue (void)
 	  passed_mode = Pmode;
 	}
 
-      entry_parm = targetm.calls.function_arg (args_so_far, passed_mode,
-					       passed_type, true);
+      entry_parm = function_arg (args_so_far, passed_mode, passed_type,
+				 true);
 
       if (entry_parm)
 	{
@@ -2819,8 +2819,7 @@ microblaze_expand_prologue (void)
 	  break;
 	}
 
-      targetm.calls.function_arg_advance (args_so_far, passed_mode,
-					  passed_type, true);
+      function_arg_advance (args_so_far, passed_mode, passed_type, true);
 
       next_arg = TREE_CHAIN (cur_arg);
       if (next_arg == 0)
@@ -2834,8 +2833,8 @@ microblaze_expand_prologue (void)
 
   /* Split parallel insn into a sequence of insns.  */
 
-  next_arg_reg = targetm.calls.function_arg (args_so_far, VOIDmode,
-					     void_type_node, true);
+  next_arg_reg = function_arg (args_so_far, VOIDmode, void_type_node,
+			       true);
   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
     {
       rtvec adjust = XVEC (next_arg_reg, 0);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 890e947..d9d0c59 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -6308,7 +6308,8 @@ mips_std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
     }
 
   /* Compute the rounded size of the type.  */
-  type_size = size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  type_size = empty_record ? 0 : size_in_bytes (type);
   rounded_size = round_up (type_size, align);
 
   /* Reduce rounded_size so it's sharable with the postqueue.  */
@@ -6397,7 +6398,8 @@ mips_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 
       ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
 		     NULL_TREE);
-      size = int_size_in_bytes (type);
+      bool empty_record = type && type_is_empty_record_p (type);
+      size = empty_record ? 0 : int_size_in_bytes (type);
 
       if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
 	  && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 182ca59..6b1d5ca 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1451,7 +1451,8 @@ msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
     }
 
   /* Compute the rounded size of the type.  */
-  type_size = size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  type_size = empty_record ? 0 : size_in_bytes (type);
   rounded_size = round_up (type_size, align);
 
   /* Reduce rounded_size so it's sharable with the postqueue.  */
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 8b1c832..104dc88 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -6342,7 +6342,8 @@ hppa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 	  type = ptr;
 	  ptr = build_pointer_type (type);
 	}
-      size = int_size_in_bytes (type);
+      bool empty_record = type && type_is_empty_record_p (type);
+      size = empty_record ? 0 : int_size_in_bytes (type);
       valist_type = TREE_TYPE (valist);
 
       /* Args grow down.  Not handled by generic routines.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7b9201a..bca478a 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -12074,7 +12074,8 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
   sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist),
 		f_sav, NULL_TREE);
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   rsize = (size + 3) / 4;
   align = 1;
 
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3be64de..b2de2f0 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -11630,7 +11630,8 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
   valist = unshare_expr (valist);
   ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
 
   s390_check_type_for_vector_abi (type, true, false);
 
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 0b18ce5..3977f12 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -8765,7 +8765,8 @@ sh_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   if (pass_by_ref)
     type = build_pointer_type (type);
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
   pptr_type_node = build_pointer_type (ptr_type_node);
 
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 71609f2..3dae250 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -7412,7 +7412,8 @@ sparc_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
   else
     {
       indirect = false;
-      size = int_size_in_bytes (type);
+      bool empty_record = type && type_is_empty_record_p (type);
+      size = empty_record ? 0 : int_size_in_bytes (type);
       rsize = ROUND_UP (size, UNITS_PER_WORD);
       align = 0;
 
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 401c295..cafcd86 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -4028,7 +4028,8 @@ spu_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
 					   false);
   if (pass_by_reference_p)
     type = build_pointer_type (type);
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
 
   /* build conditional expression to calculate addr. The expression
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 50af15b..631bb63 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1337,8 +1337,10 @@ xstormy16_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   count = build3 (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count,
 		  NULL_TREE);
 
+  bool empty_record = type && type_is_empty_record_p (type);
   must_stack = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
-  size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD);
+  size_tree = round_up (empty_record ? integer_zero_node : size_in_bytes (type),
+			UNITS_PER_WORD);
   gimplify_expr (&size_tree, pre_p, NULL, is_gimple_val, fb_rvalue);
 
   size_of_reg_args = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD;
@@ -1374,7 +1376,7 @@ xstormy16_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   /* Arguments larger than a word might need to skip over some
      registers, since arguments are either passed entirely in
      registers or entirely on the stack.  */
-  size = PUSH_ROUNDING (int_size_in_bytes (type));
+  size = PUSH_ROUNDING (empty_record ? 0 : int_size_in_bytes (type));
   if (size > 2 || size < 0 || must_stack)
     {
       tree r, u;
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 06c832c..3c7fe2b 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -396,8 +396,8 @@ tilegx_setup_incoming_varargs (cumulative_args_t cum,
   /* The caller has advanced CUM up to, but not beyond, the last named
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
-				      mode, type, true);
+  function_arg_advance (pack_cumulative_args (&local_cum), mode, type,
+			true);
   first_reg = local_cum;
 
   if (local_cum < TILEGX_NUM_ARG_REGS)
@@ -473,7 +473,8 @@ tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   if (pass_by_reference_p)
     type = build_pointer_type (type);
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
 
   /* If the alignment of the type is greater than the default for a
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index 628cd04..d1d00cf 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -348,8 +348,8 @@ tilepro_setup_incoming_varargs (cumulative_args_t cum,
   /* The caller has advanced CUM up to, but not beyond, the last named
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
-  targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum),
-				      mode, type, true);
+  function_arg_advance (pack_cumulative_args (&local_cum), mode, type,
+			true);
   first_reg = local_cum;
 
   if (local_cum < TILEPRO_NUM_ARG_REGS)
@@ -421,7 +421,8 @@ tilepro_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
   if (pass_by_reference_p)
     type = build_pointer_type (type);
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
 
   /* If the alignment of the type is greater than the default for a
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index 7881b0e..d225a6d 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -1529,7 +1529,8 @@ visium_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
       return build_va_arg_indirect_ref (t);
     }
 
-  size = int_size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  size = empty_record ? 0 : int_size_in_bytes (type);
   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
   f_ovfl = TYPE_FIELDS (va_list_type_node);
   f_gbase = TREE_CHAIN (f_ovfl);
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 64d089b..a725a8b 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -3161,7 +3161,8 @@ xtensa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist),
 		f_ndx, NULL_TREE);
 
-  type_size = size_in_bytes (type);
+  bool empty_record = type && type_is_empty_record_p (type);
+  type_size = empty_record ? 0 : size_in_bytes (type);
   va_size = round_up (type_size, UNITS_PER_WORD);
   gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
 
-- 
2.5.0

Reply via email to