[Bug target/94707] [8/9/10 Regression] class with empty base passed incorrectly with -std=c++17 on powerpc64le

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Apr 22 10:12:12 GMT 2020


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

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Updated incomplete patch on top of
https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544276.html

I've handled one rs6000_discover_homogeneous_aggregate caller where it wasn't
that hard to figure out
how to report different decisions based on if GCC 7/8/9 with -std=c++17 would
make the aggregate
non-homogeneous because of the C++17 empty base artificial FIELD_DECL and we'd
return true because of that, while
in -std=c++14 and in patched GCC trunk we'd return false.
But I'm getting lost in all the other spots, figuring out if we made different
decisions is harder.

--- gcc/config/rs6000/rs6000-internal.h.jj      2020-03-20 09:11:36.229903622
+0100
+++ gcc/config/rs6000/rs6000-internal.h 2020-04-22 11:31:23.943522525 +0200
@@ -129,7 +129,8 @@ extern int rs6000_darwin64_struct_check_
 extern bool rs6000_discover_homogeneous_aggregate (machine_mode mode,
                                                   const_tree type,
                                                   machine_mode *elt_mode,
-                                                  int *n_elts);
+                                                  int *n_elts,
+                                                  bool
*cxx17_empty_base_seen);
 extern void rs6000_output_mi_thunk (FILE *file,
                                    tree thunk_fndecl ATTRIBUTE_UNUSED,
                                    HOST_WIDE_INT delta,
--- gcc/config/rs6000/rs6000-call.c.jj  2020-03-30 22:53:40.746640328 +0200
+++ gcc/config/rs6000/rs6000-call.c     2020-04-22 12:06:00.066843119 +0200
@@ -5528,7 +5528,8 @@ const struct altivec_builtin_types altiv
    sub-tree.  */

 static int
-rs6000_aggregate_candidate (const_tree type, machine_mode *modep)
+rs6000_aggregate_candidate (const_tree type, machine_mode *modep,
+                           bool *cxx17_empty_base_seen)
 {
   machine_mode mode;
   HOST_WIDE_INT size;
@@ -5598,7 +5599,8 @@ rs6000_aggregate_candidate (const_tree t
            || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
          return -1;

-       count = rs6000_aggregate_candidate (TREE_TYPE (type), modep);
+       count = rs6000_aggregate_candidate (TREE_TYPE (type), modep,
+                                           cxx17_empty_base_seen);
        if (count == -1
            || !index
            || !TYPE_MAX_VALUE (index)
@@ -5636,7 +5638,15 @@ rs6000_aggregate_candidate (const_tree t
            if (TREE_CODE (field) != FIELD_DECL)
              continue;

-           sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep);
+           if (cxx17_empty_base_field_p (field))
+             {
+               if (cxx17_empty_base_seen)
+                 *cxx17_empty_base_seen = true;
+               continue;
+             }
+
+           sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
+                                                   cxx17_empty_base_seen);
            if (sub_count < 0)
              return -1;
            count += sub_count;
@@ -5669,7 +5679,8 @@ rs6000_aggregate_candidate (const_tree t
            if (TREE_CODE (field) != FIELD_DECL)
              continue;

-           sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep);
+           sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep,
+                                                   cxx17_empty_base_seen);
            if (sub_count < 0)
              return -1;
            count = count > sub_count ? count : sub_count;
@@ -5700,7 +5711,8 @@ rs6000_aggregate_candidate (const_tree t
 bool
 rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type,
                                       machine_mode *elt_mode,
-                                      int *n_elts)
+                                      int *n_elts,
+                                      bool *cxx17_empty_base_seen)
 {
   /* Note that we do not accept complex types at the top level as
      homogeneous aggregates; these types are handled via the
@@ -5710,7 +5722,8 @@ rs6000_discover_homogeneous_aggregate (m
       && AGGREGATE_TYPE_P (type))
     {
       machine_mode field_mode = VOIDmode;
-      int field_count = rs6000_aggregate_candidate (type, &field_mode);
+      int field_count = rs6000_aggregate_candidate (type, &field_mode,
+                                                   cxx17_empty_base_seen);

       if (field_count > 0)
        {
@@ -5734,6 +5747,8 @@ rs6000_discover_homogeneous_aggregate (m
     *elt_mode = mode;
   if (n_elts)
     *n_elts = 1;
+  if (cxx17_empty_base_seen)
+    *cxx17_empty_base_seen = false;
   return false;
 }

@@ -5790,9 +5805,14 @@ rs6000_return_in_memory (const_tree type
     }

   /* The ELFv2 ABI returns homogeneous VFP aggregates in registers */
+  bool cxx17_empty_base_seen = false;
   if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (type), type,
-                                            NULL, NULL))
-    return false;
+                                            NULL, NULL,
+                                            &cxx17_empty_base_seen))
+    {
+      if (!cxx17_empty_base_seen || !warn_psabi)
+       return false;
+    }

   /* The ELFv2 ABI returns aggregates up to 16B in registers */
   if (DEFAULT_ABI == ABI_ELFv2 && AGGREGATE_TYPE_P (type)
@@ -5802,7 +5822,21 @@ rs6000_return_in_memory (const_tree type
   if (AGGREGATE_TYPE_P (type)
       && (aix_struct_return
          || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8))
-    return true;
+    {
+      if (cxx17_empty_base_seen)
+       {
+         inform (input_location,
+                 "prior to GCC 10, parameters of type %qT were passed "
+                 "incorrectly for C++17", type);
+         return false;
+       }
+
+      return true;
+    }
+
+  /* The ELFv2 ABI returns homogeneous VFP aggregates in registers.  */
+  if (cxx17_empty_base_seen)
+    return false;

   /* Allow -maltivec -mabi=no-altivec without warning.  Altivec vector
      modes only exist for GCC vector types if -maltivec.  */
@@ -6141,7 +6175,8 @@ rs6000_function_arg_boundary (machine_mo
   machine_mode elt_mode;
   int n_elts;

-  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts,
+                                        NULL);

   if (DEFAULT_ABI == ABI_V4
       && (GET_MODE_SIZE (mode) == 8
@@ -6409,7 +6444,8 @@ rs6000_function_arg_advance_1 (CUMULATIV
   machine_mode elt_mode;
   int n_elts;

-  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts,
+                                        NULL);

   /* Only tick off an argument if we're not recursing.  */
   if (depth == 0)
@@ -6993,7 +7029,9 @@ rs6000_function_arg (cumulative_args_t c
       return GEN_INT (cum->call_cookie & ~CALL_LIBCALL);
     }

-  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+  bool cxx17_empty_base_seen = false;
+  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts,
+                                        &cxx17_empty_base_seen);

   if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type))
     {
@@ -7229,7 +7267,7 @@ rs6000_arg_partial_bytes (cumulative_arg
   int n_elts;

   rs6000_discover_homogeneous_aggregate (arg.mode, arg.type,
-                                        &elt_mode, &n_elts);
+                                        &elt_mode, &n_elts, NULL);

   if (DEFAULT_ABI == ABI_V4)
     return 0;
--- gcc/config/rs6000/rs6000.c.jj       2020-04-17 08:49:49.040683868 +0200
+++ gcc/config/rs6000/rs6000.c  2020-04-22 12:06:34.988310057 +0200
@@ -22428,7 +22428,8 @@ rs6000_function_value (const_tree valtyp
   mode = TYPE_MODE (valtype);

   /* The ELFv2 ABI returns homogeneous VFP aggregates in registers.  */
-  if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode,
&n_elts))
+  if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode,
&n_elts,
+                                            NULL))
     {
       int first_reg, n_regs;


More information about the Gcc-bugs mailing list