public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw
@ 2020-04-26  9:17 sbence92 at gmail dot com
  2020-04-26 15:15 ` [Bug target/94770] " jakub at gcc dot gnu.org
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: sbence92 at gmail dot com @ 2020-04-26  9:17 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

            Bug ID: 94770
           Summary: class with empty base passed incorrectly with
                    -std=c++17 on mingw
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: sbence92 at gmail dot com
  Target Milestone: ---

Created attachment 48376
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48376&action=edit
preprocessed failing tests

Similar to Bug #94383, Bug #94704 and Bug #94706 the below tests fail with gcc
10 (ead1c27a530) with mingw host and target (also with gcc 9.3 taken from
msys2).

FAIL: tmpdir-g++.dg-struct-layout-1/t032 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t033 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t034 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t051 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t055 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t056 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t058 cp_compat_x_tst.o-cp_compat_y_tst.o
execute
FAIL: tmpdir-g++.dg-struct-layout-1/t059 cp_compat_x_tst.o-cp_compat_y_tst.o
execute


tmpdir-g++-dg-struct-layout-1-t032-01.exe
fail 30.71

tmpdir-g++-dg-struct-layout-1-t033-01.exe
fail 385.71

tmpdir-g++-dg-struct-layout-1-t034-01.exe
fail 798.71

tmpdir-g++-dg-struct-layout-1-t051-01.exe
fail 1817.71

tmpdir-g++-dg-struct-layout-1-t055-01.exe
fail 2002.71

tmpdir-g++-dg-struct-layout-1-t056-01.exe
fail 2200.71

tmpdir-g++-dg-struct-layout-1-t058-01.exe
fail 2604.71

tmpdir-g++-dg-struct-layout-1-t059-01.exe
fail 2828.71

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
@ 2020-04-26 15:15 ` jakub at gcc dot gnu.org
  2020-04-26 20:44 ` sbence92 at gmail dot com
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-26 15:15 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Does
gcc/testsuite/g++/g++.dg-struct-layout-1/t032_test.h
in build directory contain
T(30,struct{}a[1];,)
?  Failure 71 suggests different parameter passing on something like:
void foo (int, ...);
struct empty_base {};
struct S : public empty_base { struct{}a[1]; };
S s, a[5];

void
bar ()
{
  foo (1, 1.0, s, 2LL, a[2], a[2]);
}
but my cross-compiler generates the same code with -std=c++14 and -std=c++17
here.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
  2020-04-26 15:15 ` [Bug target/94770] " jakub at gcc dot gnu.org
@ 2020-04-26 20:44 ` sbence92 at gmail dot com
  2020-04-26 20:45 ` sbence92 at gmail dot com
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: sbence92 at gmail dot com @ 2020-04-26 20:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #2 from Bence Szabó <sbence92 at gmail dot com> ---
Yes there's a T(30,struct{}a[1];,) in t032.
Indeed the fail happens on a variadic function (void check30va(int i, ...)).

I dig in some more and it turns out all the tests listed crash. I've attached
the formated preprocessed source for t032.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
  2020-04-26 15:15 ` [Bug target/94770] " jakub at gcc dot gnu.org
  2020-04-26 20:44 ` sbence92 at gmail dot com
@ 2020-04-26 20:45 ` sbence92 at gmail dot com
  2020-04-26 21:26 ` sbence92 at gmail dot com
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: sbence92 at gmail dot com @ 2020-04-26 20:45 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #3 from Bence Szabó <sbence92 at gmail dot com> ---
Created attachment 48379
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48379&action=edit
t032

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (2 preceding siblings ...)
  2020-04-26 20:45 ` sbence92 at gmail dot com
@ 2020-04-26 21:26 ` sbence92 at gmail dot com
  2020-04-26 21:28 ` jakub at gcc dot gnu.org
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: sbence92 at gmail dot com @ 2020-04-26 21:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #4 from Bence Szabó <sbence92 at gmail dot com> ---
As a remark for 'same code with -std=c++14 and -std=c++17 here', I can confirm,
the example you provided also produces same assembly for me in c++14 and c++17.
Also compiling t032 with only c++14 or only c++17 still results in a failing
test case (30.71) and then a crash. Maybe this is not the same abi problem?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (3 preceding siblings ...)
  2020-04-26 21:26 ` sbence92 at gmail dot com
@ 2020-04-26 21:28 ` jakub at gcc dot gnu.org
  2020-04-27  7:50 ` sbence92 at gmail dot com
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-26 21:28 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Bence Szabó from comment #4)
> As a remark for 'same code with -std=c++14 and -std=c++17 here', I can
> confirm, the example you provided also produces same assembly for me in
> c++14 and c++17.
> Also compiling t032 with only c++14 or only c++17 still results in a failing
> test case (30.71) and then a crash. Maybe this is not the same abi problem?

Ah, then it is not c++14 vs. c++17 ABI incompatibility, but some bug in va_arg
passing of such classes for mingw.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (4 preceding siblings ...)
  2020-04-26 21:28 ` jakub at gcc dot gnu.org
@ 2020-04-27  7:50 ` sbence92 at gmail dot com
  2020-04-27  9:51 ` jakub at gcc dot gnu.org
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: sbence92 at gmail dot com @ 2020-04-27  7:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #6 from Bence Szabó <sbence92 at gmail dot com> ---
> Ah, then it is not c++14 vs. c++17 ABI incompatibility, but some bug in
> va_arg passing of such classes for mingw.

It seems so. In t032 I got rid of the crashing tests (30, 56, 77, 80, 89, 100,
117, 134, 162, 171, 174, 191, 250 all of them are the second variadic test
case) and the rest of the tests pass in t032. Same in t059: 2998, 2828 crash on
2nd variadic test the rest passes.

Sorry for misleading bug report, I saw the same test cases fail as the
mentioned reports, didn't know the reason is so different.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (5 preceding siblings ...)
  2020-04-27  7:50 ` sbence92 at gmail dot com
@ 2020-04-27  9:51 ` jakub at gcc dot gnu.org
  2020-04-27 10:49 ` redi at gcc dot gnu.org
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-27  9:51 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, does:
struct empty_base {};
struct S : public empty_base { struct{}a[1]; };
S s, a[5];

__attribute__((noipa)) void
foo (int x, ...)
{
  __builtin_va_list ap;
  __builtin_va_start (ap, x);
  if (x != 1 && x != 2)
    __builtin_abort ();
  if (__builtin_va_arg (ap, double) != 1.0)
    __builtin_abort ();
  if (x == 1)
    __builtin_va_arg (ap, S);
  if (__builtin_va_arg (ap, long long) != 2LL)
    __builtin_abort ();
  if (x == 1)
    {
      __builtin_va_arg (ap, S);
      __builtin_va_arg (ap, S);
    }
  __builtin_va_end (ap);
}

int
main ()
{
  foo (1, 1.0, s, 2LL, a[2], a[2]);
  foo (2, 1.0, 2LL);
}

FAIL too?  Seems the va_arg (sp, S); don't do anything, i.e. not to expect the
empty class with empty base to be passed at all, but on the caller side it
makes a change:
The first arg is passed in %ecx, second in both %xmm1 and %rdx it seems, and
2LL is passed in %r9 in the first call to foo and in $r8 in the second one.

Now, the question is what MSCV or other compilers do (e.g. clang), if they
match what GCC does on the caller side, or on the va_arg side (guess one needs
to sed -i -e 's/__builtin_//g;s/__attribute__((noipa)) //' in the testcase, and
add #include <cstdarg> and #include <cstdlib>.  

Seems even empty bases aren't needed, as struct S { struct{}a[1]; }; is treated
the same, or even just struct S {};

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (6 preceding siblings ...)
  2020-04-27  9:51 ` jakub at gcc dot gnu.org
@ 2020-04-27 10:49 ` redi at gcc dot gnu.org
  2020-04-27 10:50 ` redi at gcc dot gnu.org
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: redi at gcc dot gnu.org @ 2020-04-27 10:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #8 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The third __builtin_abort() is called:

  if (__builtin_va_arg (ap, long long) != 2LL)
    __builtin_abort ();

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (7 preceding siblings ...)
  2020-04-27 10:49 ` redi at gcc dot gnu.org
@ 2020-04-27 10:50 ` redi at gcc dot gnu.org
  2020-04-27 11:04 ` jakub at gcc dot gnu.org
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: redi at gcc dot gnu.org @ 2020-04-27 10:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> ---
At least, when using:
gcc version 9.2.1 20190827 (Fedora MinGW 9.2.1-1.fc31) (GCC) 
and executing with Wine.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (8 preceding siblings ...)
  2020-04-27 10:50 ` redi at gcc dot gnu.org
@ 2020-04-27 11:04 ` jakub at gcc dot gnu.org
  2020-04-27 11:41 ` jakub at gcc dot gnu.org
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-27 11:04 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #9)
> At least, when using:
> gcc version 9.2.1 20190827 (Fedora MinGW 9.2.1-1.fc31) (GCC) 
> and executing with Wine.

Yeah, I can clearly see it in the assembly that it must ICE, the big question
is what is the right ABI, if the empty structures are not passed at all (like
e.g. in the x86-64 clarified psABI), or if they are passed as clearly is what
happens in the caller.
On the va_arg side, for the MS ABI va_list seems to be a pointer and thus it
defers to the standard middle-end handling where it see a TYPE_EMPTY_P? struct
and uses 0 size instead of the actual one.
Now, not sure if we can tweak the *RECORD_EMPTY_P* target hook, because it
marks types rather than their uses, and in sources where both x86-64 psABI and
msabi are used together, we want TYPE_EMPTY_P being set for the former and
perhaps not? for the latter.
Of course, the backend coiuld check for the MSABI and TYPE_EMPTY_P type and
don't defer to the middle-end in that case and handle it differently.
BTW, when I tried clang++ (10.0.0 trunk 374035 version) with -target
x86_64-w64-mingw32, it seems it matches g++ on the caller side and does
something on the callee side, but I bet MSVC is the ABI etalon on this target,
right?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (9 preceding siblings ...)
  2020-04-27 11:04 ` jakub at gcc dot gnu.org
@ 2020-04-27 11:41 ` jakub at gcc dot gnu.org
  2020-04-27 11:48 ` jakub at gcc dot gnu.org
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-27 11:41 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mpolacek at gcc dot gnu.org

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I've tried to unconditionally return false; from ix86_is_empty_record and that
then keeps pretty much same ABI on the caller side and changes the va_arg
handling to do the needed adjustments.
Which might mean this is a regression since r255066.  Though, the big question
still is what the msabi wants.  And if it wants to pass these empty classes as
their padding, then we probably need to make sure the middle-end doesn't use
TYPE_EMPTY_P at all, but instead it uses a new target hook to which it would
pass the type and some way how to identify what ABI it cares about (say NULL
for the current function's ABI and a fndecl if it is calling some other
function and wants that other function's ABI), and the hook would then either
return TYPE_EMPTY_P for non-msabi, or false for msabi.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (10 preceding siblings ...)
  2020-04-27 11:41 ` jakub at gcc dot gnu.org
@ 2020-04-27 11:48 ` jakub at gcc dot gnu.org
  2020-04-27 12:27 ` jakub at gcc dot gnu.org
  2020-05-09 19:37 ` sbence92 at gmail dot com
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-27 11:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Another interesting test is:
struct S {};
void foo (int, int, int, int, int, int, int, int, int, S, S, S, S, int);
void baz (int, int, int, int, int, int, int, int, int, int);

int
bar ()
{
  foo (1, 2, 3, 4, 5, 6, 7, 8, 9, S {}, S {}, S {}, S {}, 10);
  baz (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  return 0;
}

The question is, is 10 passed in the same stack slot to both foo and baz or
not?
In current GCC it is, with the unconditional return false; in
ix86_is_empty_record it is not, and with that clang++10 snapshot it is not
either.
So, what does MSVC do here?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (11 preceding siblings ...)
  2020-04-27 11:48 ` jakub at gcc dot gnu.org
@ 2020-04-27 12:27 ` jakub at gcc dot gnu.org
  2020-05-09 19:37 ` sbence92 at gmail dot com
  13 siblings, 0 replies; 15+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-04-27 12:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #13 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Completely untested WIP patch:
--- gcc/config/i386/i386.c.jj   2020-04-27 13:50:39.529692389 +0200
+++ gcc/config/i386/i386.c      2020-04-27 14:03:12.479322957 +0200
@@ -16550,6 +16550,23 @@ ix86_is_empty_record (const_tree type)
   return default_is_empty_record (type);
 }

+/* Implement TARGET_EMPTY_TYPE_P.  */
+
+static bool
+ix86_empty_type_p (const_tree fntype, const_tree type)
+{
+  if (!TYPE_EMPTY_P (type))
+    return false;
+  if (fntype)
+    {
+      if (ix86_function_type_abi (fntype) == MS_ABI)
+       return false;
+    }
+  else if (ix86_cfun_abi () == MS_ABI)
+    return false;
+  return true;
+}
+
 /* Implement TARGET_WARN_PARAMETER_PASSING_ABI.  */

 static void
@@ -23470,6 +23487,8 @@ ix86_run_selftests (void)

 #undef TARGET_EMPTY_RECORD_P
 #define TARGET_EMPTY_RECORD_P ix86_is_empty_record
+#undef TARGET_EMPTY_TYPE_P
+#define TARGET_EMPTY_TYPE_P ix86_empty_type_p

 #undef TARGET_WARN_PARAMETER_PASSING_ABI
 #define TARGET_WARN_PARAMETER_PASSING_ABI ix86_warn_parameter_passing_abi
--- gcc/function.c.jj   2020-04-16 10:15:06.841126753 +0200
+++ gcc/function.c      2020-04-27 14:21:27.669799119 +0200
@@ -2102,7 +2102,7 @@ aggregate_value_p (const_tree exp, const
   if (TREE_ADDRESSABLE (type))
     return 1;

-  if (TYPE_EMPTY_P (type))
+  if (targetm.calls.empty_type_p (fntype, type))
     return 0;

   if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
@@ -3095,7 +3095,8 @@ assign_parm_setup_block (struct assign_p
        move_block_from_reg (REGNO (entry_parm), mem,
                             size_stored / UNITS_PER_WORD);
     }
-  else if (data->stack_parm == 0 && !TYPE_EMPTY_P (data->arg.type))
+  else if (data->stack_parm == 0
+          && !targetm.calls.empty_type_p (NULL_TREE, data->arg.type))
     {
       push_to_sequence2 (all->first_conversion_insn,
all->last_conversion_insn);
       emit_block_move (stack_parm, data->entry_parm, GEN_INT (size),
@@ -3496,7 +3497,7 @@ assign_parm_setup_stack (struct assign_p
       dest = validize_mem (copy_rtx (data->stack_parm));
       src = validize_mem (copy_rtx (data->entry_parm));

-      if (TYPE_EMPTY_P (data->arg.type))
+      if (targetm.calls.empty_type_p (NULL_TREE, data->arg.type))
        /* Empty types don't really need to be copied.  */;
       else if (MEM_P (src))
        {
@@ -3657,7 +3658,7 @@ assign_parms (tree fndecl)
             passing area, have non-zero size and have address taken,
             force creation of a stack slot so that they have distinct
             address from other parameters.  */
-         if (TYPE_EMPTY_P (data.arg.type)
+         if (targetm.calls.empty_type_p (NULL_TREE, data.arg.type)
              && TREE_ADDRESSABLE (parm)
              && data.entry_parm == data.stack_parm
              && MEM_P (data.entry_parm)
--- gcc/targhooks.h.jj  2020-01-12 11:54:36.939405473 +0100
+++ gcc/targhooks.h     2020-04-27 13:57:13.113741631 +0200
@@ -246,6 +246,7 @@ extern unsigned int default_dwarf_poly_i
                                                            int *);
 extern machine_mode default_dwarf_frame_reg_mode (int);
 extern fixed_size_mode default_get_reg_raw_mode (int);
+extern bool default_empty_type_p (const_tree, const_tree);
 extern bool default_keep_leaf_when_profiled ();

 extern void *default_get_pch_validity (size_t *);
--- gcc/targhooks.c.jj  2020-01-21 09:14:07.566267369 +0100
+++ gcc/targhooks.c     2020-04-27 14:07:27.228481737 +0200
@@ -1945,6 +1945,12 @@ default_get_reg_raw_mode (int regno)
   return as_a <fixed_size_mode> (reg_raw_mode[regno]);
 }

+bool
+default_empty_type_p (const_tree, const_tree type)
+{
+  return TYPE_EMPTY_P (type);
+}
+
 /* Return true if a leaf function should stay leaf even with profiling
    enabled.  */

@@ -2190,7 +2196,7 @@ std_gimplify_va_arg_expr (tree valist, t
   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
      requires greater alignment, we must perform dynamic alignment.  */
   if (boundary > align
-      && !TYPE_EMPTY_P (type)
+      && !targetm.calls.empty_type_p (NULL_TREE, type)
       && !integer_zerop (TYPE_SIZE (type)))
     {
       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
--- gcc/calls.c.jj      2020-04-27 09:10:50.593968911 +0200
+++ gcc/calls.c 2020-04-27 14:12:14.046156465 +0200
@@ -146,12 +146,13 @@ static unsigned HOST_WIDE_INT stored_arg
 static int stack_arg_under_construction;

 static void precompute_register_parameters (int, struct arg_data *, int *);
-static int store_one_arg (struct arg_data *, rtx, int, int, int);
+static int store_one_arg (const_tree, struct arg_data *, rtx, int, int, int);
 static void store_unaligned_arguments_into_pseudos (struct arg_data *, int);
 static int finalize_must_preallocate (int, int, struct arg_data *,
                                      struct args_size *);
 static void precompute_arguments (int, struct arg_data *);
-static void compute_argument_addresses (struct arg_data *, rtx, int);
+static void compute_argument_addresses (const_tree, struct arg_data *, rtx,
+                                       int);
 static rtx rtx_for_function_call (tree, tree);
 static void load_register_parameters (struct arg_data *, int, rtx *, int,
                                      int, int *);
@@ -2769,7 +2770,8 @@ finalize_must_preallocate (int must_prea
    ARGBLOCK is an rtx for the address of the outgoing arguments.  */

 static void
-compute_argument_addresses (struct arg_data *args, rtx argblock, int
num_actuals)
+compute_argument_addresses (const_tree funtype, struct arg_data *args,
+                           rtx argblock, int num_actuals)
 {
   if (argblock)
     {
@@ -2798,7 +2800,8 @@ compute_argument_addresses (struct arg_d
              && args[i].partial == 0)
            continue;

-         if (TYPE_EMPTY_P (TREE_TYPE (args[i].tree_value)))
+         if (targetm.calls.empty_type_p (funtype,
+                                         TREE_TYPE (args[i].tree_value)))
            continue;

          addr = simplify_gen_binary (PLUS, Pmode, arg_reg, offset);
@@ -4384,7 +4387,7 @@ expand_call (tree exp, rtx target, int i
              }
        }

-      compute_argument_addresses (args, argblock, num_actuals);
+      compute_argument_addresses (funtype, args, argblock, num_actuals);

       /* Stack is properly aligned, pops can't safely be deferred during
         the evaluation of the arguments.  */
@@ -4473,7 +4476,7 @@ expand_call (tree exp, rtx target, int i
                  continue;
                }

-             if (store_one_arg (&args[i], argblock, flags,
+             if (store_one_arg (funtype, &args[i], argblock, flags,
                                 adjusted_args_size.var != 0,
                                 reg_parm_stack_space)
                  || (pass == 0
@@ -4513,7 +4516,7 @@ expand_call (tree exp, rtx target, int i
                  break;
                }

-             if (store_one_arg (&args[i], argblock, flags,
+             if (store_one_arg (funtype, &args[i], argblock, flags,
                                 adjusted_args_size.var != 0,
                                 reg_parm_stack_space)
                  || (pass == 0
@@ -5845,8 +5848,9 @@ emit_library_call_value_1 (int retval, r
    zero otherwise.  */

 static int
-store_one_arg (struct arg_data *arg, rtx argblock, int flags,
-              int variable_size ATTRIBUTE_UNUSED, int reg_parm_stack_space)
+store_one_arg (const_tree funtype, struct arg_data *arg, rtx argblock,
+              int flags, int variable_size ATTRIBUTE_UNUSED,
+              int reg_parm_stack_space)
 {
   tree pval = arg->tree_value;
   rtx reg = 0;
@@ -6016,7 +6020,7 @@ store_one_arg (struct arg_data *arg, rtx
         Note that in C the default argument promotions
         will prevent such mismatches.  */

-      poly_int64 size = (TYPE_EMPTY_P (TREE_TYPE (pval))
+      poly_int64 size = (targetm.calls.empty_type_p (funtype, TREE_TYPE
(pval))
                         ? 0 : GET_MODE_SIZE (arg->mode));

       /* Compute how much space the push instruction will push.
--- gcc/doc/tm.texi.jj  2020-03-17 13:50:52.844934839 +0100
+++ gcc/doc/tm.texi     2020-04-27 14:17:07.848721305 +0200
@@ -4693,6 +4693,12 @@ This target hook returns true if the typ
 is to return @code{false}.
 @end deftypefn

+@deftypefn {Target Hook} bool TARGET_EMPTY_TYPE_P (const_tree @var{fndecl},
const_tree @var{type})
+This target hook returns true if the type is an empty record in the ABI
+of function type @var{fntype}, or if NULL of the current function.  The
+default is to return @code{TYPE_EMPTY_P(@var{type})}.
+@end deftypefn
+
 @deftypefn {Target Hook} void TARGET_WARN_PARAMETER_PASSING_ABI
(cumulative_args_t @var{ca}, tree @var{type})
 This target hook warns about the change in empty class parameter passing
 ABI.
--- gcc/doc/tm.texi.in.jj       2020-03-12 09:35:05.432126619 +0100
+++ gcc/doc/tm.texi.in  2020-04-27 14:17:02.920795688 +0200
@@ -3490,6 +3490,8 @@ nothing when you use @option{-freg-struc

 @hook TARGET_EMPTY_RECORD_P

+@hook TARGET_EMPTY_TYPE_P
+
 @hook TARGET_WARN_PARAMETER_PASSING_ABI

 @node Caller Saves
--- gcc/target.def.jj   2020-03-17 13:50:52.713936762 +0100
+++ gcc/target.def      2020-04-27 14:16:25.740356959 +0200
@@ -5225,6 +5225,15 @@ is to return @code{false}.",
  bool, (const_tree type),
  hook_bool_const_tree_false)

+/* Return true if a type is an empty record in a particular ABI context.  */
+DEFHOOK
+(empty_type_p,
+ "This target hook returns true if the type is an empty record in the ABI\n\
+of function type @var{fntype}, or if NULL of the current function.  The\n\
+default is to return @code{TYPE_EMPTY_P(@var{type})}.",
+ bool, (const_tree fndecl, const_tree type),
+ default_empty_type_p)
+
 /* Warn about the change in empty class parameter passing ABI.  */
 DEFHOOK
 (warn_parameter_passing_abi,

The remaining problem are (besides testing) that two last uses of TYPE_EMPTY_P
in tree.c and one use in calls.c need to pass in information on the function
type being called if it is on the caller side, or NULL on the callee side, and
that means the function needs new argument, and associated target hook too etc.
:(

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug target/94770] class with empty base passed incorrectly with -std=c++17 on mingw
  2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
                   ` (12 preceding siblings ...)
  2020-04-27 12:27 ` jakub at gcc dot gnu.org
@ 2020-05-09 19:37 ` sbence92 at gmail dot com
  13 siblings, 0 replies; 15+ messages in thread
From: sbence92 at gmail dot com @ 2020-05-09 19:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94770

--- Comment #14 from Bence Szabó <sbence92 at gmail dot com> ---
(In reply to Jakub Jelinek from comment #13)
> Completely untested WIP patch:

Results with ead1c27a530 + this patch:
The same tests fail as in the original description, t032 and t059 crash/pass
the same way as described in comment 6. Also, running the testsuite (check-c++)
shows new failed tests:
FAIL: g++.dg/compat/abi/pr83487-1 cp_compat_x_tst.o-cp_compat_y_tst.o execute
FAIL: g++.dg/compat/abi/pr83487-2 cp_compat_x_tst.o-cp_compat_y_tst.o execute
FAIL: g++.dg/lookup/ns1.C  -std=c++98 (test for excess errors)
FAIL: g++.dg/torture/pr39417.C   -O0  execution test
FAIL: g++.old-deja/g++.robertl/eb21.C  -std=c++14 execution test (timeout)
FAIL: g++.old-deja/g++.robertl/eb21.C  -std=c++17 execution test (timeout)
FAIL: g++.old-deja/g++.robertl/eb21.C  -std=c++2a execution test (timeout)

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-05-09 19:37 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-26  9:17 [Bug target/94770] New: class with empty base passed incorrectly with -std=c++17 on mingw sbence92 at gmail dot com
2020-04-26 15:15 ` [Bug target/94770] " jakub at gcc dot gnu.org
2020-04-26 20:44 ` sbence92 at gmail dot com
2020-04-26 20:45 ` sbence92 at gmail dot com
2020-04-26 21:26 ` sbence92 at gmail dot com
2020-04-26 21:28 ` jakub at gcc dot gnu.org
2020-04-27  7:50 ` sbence92 at gmail dot com
2020-04-27  9:51 ` jakub at gcc dot gnu.org
2020-04-27 10:49 ` redi at gcc dot gnu.org
2020-04-27 10:50 ` redi at gcc dot gnu.org
2020-04-27 11:04 ` jakub at gcc dot gnu.org
2020-04-27 11:41 ` jakub at gcc dot gnu.org
2020-04-27 11:48 ` jakub at gcc dot gnu.org
2020-04-27 12:27 ` jakub at gcc dot gnu.org
2020-05-09 19:37 ` sbence92 at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).