This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Add LANG_HOOKS_EMPTY_RECORD_P for C++ empty class


On Tue, Nov 17, 2015 at 12:01 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> Empty record should be returned and passed the same way in C and C++.
> This patch adds LANG_HOOKS_EMPTY_RECORD_P for C++ empty class, which
> defaults to return false.  For C++, LANG_HOOKS_EMPTY_RECORD_P is defined
> to is_really_empty_class, which returns true for C++ empty classes.  For
> LTO, we stream out a bit to indicate if a record is empty and we store
> it in TYPE_LANG_FLAG_0 when streaming in.  get_ref_base_and_extent is
> changed to set bitsize to 0 for empty records.  Middle-end and x86
> backend are updated to ignore empty records for parameter passing and
> function value return.  Other targets may need similar changes.

Please avoid a new langhook for this and instead claim a bit in tree_type_common
like for example restrict_flag (double-check it is unused for non-pointers).

I don't like that you need to modify targets - those checks should be done
in the caller (which may just use a new wrapper with the logic and then
dispatching to the actual hook).

Why do you need do adjust get_ref_base_and_extent?

Thanks,
Richard.

> gcc/
>
>         PR c++/60336
>         PR middle-end/67239
>         PR target/68355
>         * calls.c (store_one_arg): Use 0 for empty record size.  Don't
>         push 0 size argument onto stack.
>         (must_pass_in_stack_var_size_or_pad): Return false for empty
>         record.
>         * function.c (locate_and_pad_parm): Use 0 for empty record size.
>         * tree-dfa.c (get_ref_base_and_extent): Likewise.
>         * langhooks-def.h (LANG_HOOKS_EMPTY_RECORD_P): New.
>         (LANG_HOOKS_DECLS): Add LANG_HOOKS_EMPTY_RECORD_P.
>         * langhooks.h (lang_hooks_for_decls): Add empty_record_p.
>         * lto-streamer.h (LTO_major_version): Increase by 1 to 6.
>         * targhooks.c: Include "langhooks.h".
>         (std_gimplify_va_arg_expr): Use 0 for empty record size.
>         * tree-streamer-in.c (unpack_ts_base_value_fields): Stream in
>         TYPE_LANG_FLAG_0.
>         * tree-streamer-out.c: Include "langhooks.h".
>         (pack_ts_base_value_fields): Stream out a bit to indicate if a
>         record is empty.
>         * config/i386/i386.c (classify_argument): Return 0 for empty
>         record.
>         (construct_container): Return NULL for empty record.
>         (ix86_function_arg): Likewise.
>         (ix86_function_arg_advance): Skip empty record.
>         (ix86_return_in_memory): Return false for empty record.
>         (ix86_gimplify_va_arg): Use 0 for empty record size.
>
> gcc/cp/
>
>         PR c++/60336
>         PR middle-end/67239
>         PR target/68355
>         * class.c (is_empty_class): Changed to return bool and take
>         const_tree.
>         (is_really_empty_class): Changed to take const_tree.  Check
>         if TYPE_BINFO is zero.
>         * cp-tree.h (is_empty_class): Updated.
>         (is_really_empty_class): Likewise.
>         * cp-lang.c (LANG_HOOKS_EMPTY_RECORD_P): New.
>
> gcc/lto/
>
>         PR c++/60336
>         PR middle-end/67239
>         PR target/68355
>         * lto-lang.c (lto_empty_record_p): New.
>         (LANG_HOOKS_EMPTY_RECORD_P): Likewise.
>
> gcc/testsuite/
>
>         PR c++/60336
>         PR middle-end/67239
>         PR target/68355
>         * g++.dg/abi/empty12.C: New test.
>         * g++.dg/abi/empty12.h: Likewise.
>         * g++.dg/abi/empty12a.c: Likewise.
>         * g++.dg/pr60336-1.C: Likewise.
>         * g++.dg/pr60336-2.C: Likewise.
>         * g++.dg/pr68355.C: Likewise.
> ---
>  gcc/calls.c                         | 41 +++++++++++++++++++++++++++----------
>  gcc/config/i386/i386.c              | 18 +++++++++++++++-
>  gcc/cp/class.c                      | 17 ++++++++-------
>  gcc/cp/cp-lang.c                    |  2 ++
>  gcc/cp/cp-tree.h                    |  4 ++--
>  gcc/function.c                      |  7 +++++--
>  gcc/langhooks-def.h                 |  2 ++
>  gcc/langhooks.h                     |  3 +++
>  gcc/lto-streamer.h                  |  2 +-
>  gcc/lto/lto-lang.c                  | 13 ++++++++++++
>  gcc/targhooks.c                     |  6 +++++-
>  gcc/testsuite/g++.dg/abi/empty12.C  | 17 +++++++++++++++
>  gcc/testsuite/g++.dg/abi/empty12.h  |  9 ++++++++
>  gcc/testsuite/g++.dg/abi/empty12a.c |  6 ++++++
>  gcc/testsuite/g++.dg/pr60336-1.C    | 17 +++++++++++++++
>  gcc/testsuite/g++.dg/pr60336-2.C    | 28 +++++++++++++++++++++++++
>  gcc/testsuite/g++.dg/pr68355.C      | 24 ++++++++++++++++++++++
>  gcc/tree-dfa.c                      |  2 ++
>  gcc/tree-streamer-in.c              |  5 +++++
>  gcc/tree-streamer-out.c             |  6 ++++++
>  20 files changed, 204 insertions(+), 25 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/abi/empty12.C
>  create mode 100644 gcc/testsuite/g++.dg/abi/empty12.h
>  create mode 100644 gcc/testsuite/g++.dg/abi/empty12a.c
>  create mode 100644 gcc/testsuite/g++.dg/pr60336-1.C
>  create mode 100644 gcc/testsuite/g++.dg/pr60336-2.C
>  create mode 100644 gcc/testsuite/g++.dg/pr68355.C
>
> diff --git a/gcc/calls.c b/gcc/calls.c
> index b56556a..ecc9b7a 100644
> --- a/gcc/calls.c
> +++ b/gcc/calls.c
> @@ -4835,7 +4835,10 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
>          Note that in C the default argument promotions
>          will prevent such mismatches.  */
>
> -      size = GET_MODE_SIZE (arg->mode);
> +      if (lang_hooks.decls.empty_record_p (TREE_TYPE (pval)))
> +       size = 0;
> +      else
> +       size = GET_MODE_SIZE (arg->mode);
>        /* Compute how much space the push instruction will push.
>          On many machines, pushing a byte will advance the stack
>          pointer by a halfword.  */
> @@ -4865,10 +4868,14 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
>
>        /* This isn't already where we want it on the stack, so put it there.
>          This can either be done with push or copy insns.  */
> -      if (!emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
> -                     parm_align, partial, reg, used - size, argblock,
> -                     ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
> -                     ARGS_SIZE_RTX (arg->locate.alignment_pad), true))
> +      if (used
> +         && !emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval),
> +                             NULL_RTX, parm_align, partial, reg,
> +                             used - size, argblock,
> +                             ARGS_SIZE_RTX (arg->locate.offset),
> +                             reg_parm_stack_space,
> +                             ARGS_SIZE_RTX (arg->locate.alignment_pad),
> +                             true))
>         sibcall_failure = 1;
>
>        /* Unless this is a partially-in-register argument, the argument is now
> @@ -4900,10 +4907,16 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
>         {
>           /* PUSH_ROUNDING has no effect on us, because emit_push_insn
>              for BLKmode is careful to avoid it.  */
> +         bool empty_record
> +           = lang_hooks.decls.empty_record_p (TREE_TYPE (pval));
>           excess = (arg->locate.size.constant
> -                   - int_size_in_bytes (TREE_TYPE (pval))
> +                   - (empty_record
> +                      ? 0
> +                      : int_size_in_bytes (TREE_TYPE (pval)))
>                     + partial);
> -         size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
> +         size_rtx = expand_expr ((empty_record
> +                                  ? size_zero_node
> +                                  : size_in_bytes (TREE_TYPE (pval))),
>                                   NULL_RTX, TYPE_MODE (sizetype),
>                                   EXPAND_NORMAL);
>         }
> @@ -4971,10 +4984,13 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
>             }
>         }
>
> -      emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
> -                     parm_align, partial, reg, excess, argblock,
> -                     ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
> -                     ARGS_SIZE_RTX (arg->locate.alignment_pad), false);
> +      if (!CONST_INT_P (size_rtx) || INTVAL (size_rtx) != 0)
> +       emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval),
> +                       size_rtx, parm_align, partial, reg, excess,
> +                       argblock, ARGS_SIZE_RTX (arg->locate.offset),
> +                       reg_parm_stack_space,
> +                       ARGS_SIZE_RTX (arg->locate.alignment_pad),
> +                       false);
>
>        /* Unless this is a partially-in-register argument, the argument is now
>          in the stack.
> @@ -5052,6 +5068,9 @@ must_pass_in_stack_var_size_or_pad (machine_mode mode, const_tree type)
>    if (TREE_ADDRESSABLE (type))
>      return true;
>
> +  if (lang_hooks.decls.empty_record_p (type))
> +    return false;
> +
>    /* If the padding and mode of the type is such that a copy into
>       a register would put it into the wrong part of the register.  */
>    if (mode == BLKmode
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 6173dae..8bd6198 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -7920,6 +7920,9 @@ static int
>  classify_argument (machine_mode mode, const_tree type,
>                    enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset)
>  {
> +  if (type && lang_hooks.decls.empty_record_p (type))
> +    return 0;
> +
>    HOST_WIDE_INT bytes =
>      (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
>    int words = CEIL (bytes + (bit_offset % 64) / 8, UNITS_PER_WORD);
> @@ -8371,6 +8374,9 @@ construct_container (machine_mode mode, machine_mode orig_mode,
>    static bool issued_sse_ret_error;
>    static bool issued_x87_ret_error;
>
> +  if (type && lang_hooks.decls.empty_record_p (type))
> +    return NULL;
> +
>    machine_mode tmpmode;
>    int bytes =
>      (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
> @@ -8783,6 +8789,9 @@ ix86_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
>    HOST_WIDE_INT bytes, words;
>    int nregs;
>
> +  if (type && lang_hooks.decls.empty_record_p (type))
> +    return;
> +
>    if (mode == BLKmode)
>      bytes = int_size_in_bytes (type);
>    else
> @@ -9099,6 +9108,9 @@ ix86_function_arg (cumulative_args_t cum_v, machine_mode omode,
>    HOST_WIDE_INT bytes, words;
>    rtx arg;
>
> +  if (type && lang_hooks.decls.empty_record_p (type))
> +    return NULL;
> +
>    /* All pointer bounds arguments are handled separately here.  */
>    if ((type && POINTER_BOUNDS_TYPE_P (type))
>        || POINTER_BOUNDS_MODE_P (mode))
> @@ -9708,6 +9720,9 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
>    if (POINTER_BOUNDS_TYPE_P (type))
>      return false;
>
> +  if (type && lang_hooks.decls.empty_record_p (type))
> +    return false;
> +
>    if (TARGET_64BIT)
>      {
>        if (ix86_function_type_abi (fntype) == MS_ABI)
> @@ -10266,7 +10281,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
>    indirect_p = pass_by_reference (NULL, TYPE_MODE (type), type, false);
>    if (indirect_p)
>      type = build_pointer_type (type);
> -  size = int_size_in_bytes (type);
> +  bool empty_record = type && lang_hooks.decls.empty_record_p (type);
> +  size = empty_record ? 0 : int_size_in_bytes (type);
>    rsize = CEIL (size, UNITS_PER_WORD);
>
>    nat_mode = type_natural_mode (type, NULL, false);
> diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> index 216a301..c380734 100644
> --- a/gcc/cp/class.c
> +++ b/gcc/cp/class.c
> @@ -8068,8 +8068,8 @@ build_self_reference (void)
>
>  /* Returns 1 if TYPE contains only padding bytes.  */
>
> -int
> -is_empty_class (tree type)
> +bool
> +is_empty_class (const_tree type)
>  {
>    if (type == error_mark_node)
>      return 0;
> @@ -8084,7 +8084,7 @@ is_empty_class (tree type)
>     possible combinations of empty classes and possibly a vptr.  */
>
>  bool
> -is_really_empty_class (tree type)
> +is_really_empty_class (const_tree type)
>  {
>    if (CLASS_TYPE_P (type))
>      {
> @@ -8098,10 +8098,13 @@ is_really_empty_class (tree type)
>        if (COMPLETE_TYPE_P (type) && is_empty_class (type))
>         return true;
>
> -      for (binfo = TYPE_BINFO (type), i = 0;
> -          BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
> -       if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
> -         return false;
> +      /* TYPE_BINFO may be zeron when is_really_empty_class is called
> +        from LANG_HOOKS_EMPTY_RECORD_P.  */
> +      binfo = TYPE_BINFO (type);
> +      if (binfo)
> +       for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
> +         if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
> +           return false;
>        for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
>         if (TREE_CODE (field) == FIELD_DECL
>             && !DECL_ARTIFICIAL (field)
> diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
> index 048108d..80174cb 100644
> --- a/gcc/cp/cp-lang.c
> +++ b/gcc/cp/cp-lang.c
> @@ -78,6 +78,8 @@ static tree cxx_enum_underlying_base_type (const_tree);
>  #define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
>  #undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE
>  #define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE cxx_enum_underlying_base_type
> +#undef LANG_HOOKS_EMPTY_RECORD_P
> +#define LANG_HOOKS_EMPTY_RECORD_P is_really_empty_class
>
>  /* Each front end provides its own lang hook initializer.  */
>  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 84437b4..dc79979 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -5578,8 +5578,8 @@ extern tree finish_struct                 (tree, tree);
>  extern void finish_struct_1                    (tree);
>  extern int resolves_to_fixed_type_p            (tree, int *);
>  extern void init_class_processing              (void);
> -extern int is_empty_class                      (tree);
> -extern bool is_really_empty_class              (tree);
> +extern bool is_empty_class                     (const_tree);
> +extern bool is_really_empty_class              (const_tree);
>  extern void pushclass                          (tree);
>  extern void popclass                           (void);
>  extern void push_nested_class                  (tree);
> diff --git a/gcc/function.c b/gcc/function.c
> index afc2c87..b59157d 100644
> --- a/gcc/function.c
> +++ b/gcc/function.c
> @@ -4093,8 +4093,11 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs,
>
>    part_size_in_regs = (reg_parm_stack_space == 0 ? partial : 0);
>
> -  sizetree
> -    = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
> +  if (type)
> +    sizetree = (lang_hooks.decls.empty_record_p (type)
> +               ? size_zero_node : size_in_bytes (type));
> +  else
> +    sizetree = size_int (GET_MODE_SIZE (passed_mode));
>    where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
>    boundary = targetm.calls.function_arg_boundary (passed_mode, type);
>    round_boundary = targetm.calls.function_arg_round_boundary (passed_mode,
> diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
> index 18ac84d..df4cbf8 100644
> --- a/gcc/langhooks-def.h
> +++ b/gcc/langhooks-def.h
> @@ -163,6 +163,7 @@ extern tree lhd_make_node (enum tree_code);
>  #define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P hook_bool_const_tree_false
>  #define LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P \
>                                         hook_bool_tree_tree_false
> +#define LANG_HOOKS_EMPTY_RECORD_P      hook_bool_const_tree_false
>  #define LANG_HOOKS_GET_GENERIC_FUNCTION_DECL hook_tree_const_tree_null
>  #define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to
>  #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type
> @@ -228,6 +229,7 @@ extern tree lhd_make_node (enum tree_code);
>    LANG_HOOKS_FUNCTION_DECL_DELETED_P, \
>    LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
>    LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
> +  LANG_HOOKS_EMPTY_RECORD_P, \
>    LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
>    LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
>    LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \
> diff --git a/gcc/langhooks.h b/gcc/langhooks.h
> index d8d01fa..450bdee 100644
> --- a/gcc/langhooks.h
> +++ b/gcc/langhooks.h
> @@ -177,6 +177,9 @@ struct lang_hooks_for_decls
>       function parameter pack.  */
>    bool (*function_parm_expanded_from_pack_p) (tree, tree);
>
> +  /* Determine if a type is an empty record.  */
> +  bool (*empty_record_p) (const_tree type);
> +
>    /* Returns the generic declaration of a generic function instantiations.  */
>    tree (*get_generic_function_decl) (const_tree);
>
> diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
> index 5aae9e9..cc4cede 100644
> --- a/gcc/lto-streamer.h
> +++ b/gcc/lto-streamer.h
> @@ -128,7 +128,7 @@ along with GCC; see the file COPYING3.  If not see
>       String are represented in the table as pairs, a length in ULEB128
>       form followed by the data for the string.  */
>
> -#define LTO_major_version 5
> +#define LTO_major_version 6
>  #define LTO_minor_version 0
>
>  typedef unsigned char  lto_decl_flags_t;
> diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
> index 53dd8f6..dc849a4 100644
> --- a/gcc/lto/lto-lang.c
> +++ b/gcc/lto/lto-lang.c
> @@ -1306,6 +1306,16 @@ static void lto_init_ts (void)
>    tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1;
>  }
>
> +/* Return true if TYPE contains no actual data, just various possible
> +   combinations of empty records.  */
> +
> +static bool
> +lto_empty_record_p (const_tree type)
> +{
> +  /* Set if a record is empty.  */
> +  return TYPE_LANG_FLAG_0 (type);
> +}
> +
>  #undef LANG_HOOKS_NAME
>  #define LANG_HOOKS_NAME "GNU GIMPLE"
>  #undef LANG_HOOKS_OPTION_LANG_MASK
> @@ -1363,6 +1373,9 @@ static void lto_init_ts (void)
>  #undef LANG_HOOKS_INIT_TS
>  #define LANG_HOOKS_INIT_TS lto_init_ts
>
> +#undef LANG_HOOKS_EMPTY_RECORD_P
> +#define LANG_HOOKS_EMPTY_RECORD_P lto_empty_record_p
> +
>  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
>
>  /* Language hooks that are not part of lang_hooks.  */
> diff --git a/gcc/targhooks.c b/gcc/targhooks.c
> index c34b4e9..5e74dd9 100644
> --- a/gcc/targhooks.c
> +++ b/gcc/targhooks.c
> @@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "intl.h"
>  #include "opts.h"
>  #include "gimplify.h"
> +#include "langhooks.h"
>
>
>  bool
> @@ -1823,9 +1824,12 @@ std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
>    /* Hoist the valist value into a temporary for the moment.  */
>    valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
>
> +  bool empty_record = lang_hooks.decls.empty_record_p (type);
> +
>    /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
>       requires greater alignment, we must perform dynamic alignment.  */
>    if (boundary > align
> +      && !empty_record
>        && !integer_zerop (TYPE_SIZE (type)))
>      {
>        t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
> @@ -1852,7 +1856,7 @@ 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);
> +  type_size = empty_record ? size_zero_node : 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/testsuite/g++.dg/abi/empty12.C b/gcc/testsuite/g++.dg/abi/empty12.C
> new file mode 100644
> index 0000000..430d57d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/empty12.C
> @@ -0,0 +1,17 @@
> +// PR c++/60336
> +// { dg-do run }
> +// { dg-options "-x c" }
> +// { dg-additional-sources "empty12a.c" }
> +// { dg-prune-output "command line option" }
> +
> +#include "empty12.h"
> +extern "C" void fun(struct dummy, struct foo);
> +
> +int main()
> +{
> +  struct dummy d;
> +  struct foo f = { -1, -2, -3, -4, -5 };
> +
> +  fun(d, f);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/abi/empty12.h b/gcc/testsuite/g++.dg/abi/empty12.h
> new file mode 100644
> index 0000000..c61afcd
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/empty12.h
> @@ -0,0 +1,9 @@
> +struct dummy { };
> +struct foo
> +{
> +  int i1;
> +  int i2;
> +  int i3;
> +  int i4;
> +  int i5;
> +};
> diff --git a/gcc/testsuite/g++.dg/abi/empty12a.c b/gcc/testsuite/g++.dg/abi/empty12a.c
> new file mode 100644
> index 0000000..34a25ba
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/empty12a.c
> @@ -0,0 +1,6 @@
> +#include "empty12.h"
> +void fun(struct dummy d, struct foo f)
> +{
> +  if (f.i1 != -1)
> +    __builtin_abort();
> +}
> diff --git a/gcc/testsuite/g++.dg/pr60336-1.C b/gcc/testsuite/g++.dg/pr60336-1.C
> new file mode 100644
> index 0000000..af08638
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr60336-1.C
> @@ -0,0 +1,17 @@
> +// { dg-do compile }
> +// { dg-options "-O2 -std=c++11 -fno-pic" }
> +// { dg-require-effective-target fpic }
> +
> +struct dummy { };
> +struct true_type { struct dummy i; };
> +
> +extern true_type y;
> +extern void xxx (true_type c);
> +
> +void
> +yyy (void)
> +{
> +  xxx (y);
> +}
> +
> +// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }
> diff --git a/gcc/testsuite/g++.dg/pr60336-2.C b/gcc/testsuite/g++.dg/pr60336-2.C
> new file mode 100644
> index 0000000..7b902e8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr60336-2.C
> @@ -0,0 +1,28 @@
> +// { dg-do run }
> +// { dg-options "-O2" }
> +
> +#include <stdarg.h>
> +
> +struct dummy { struct{}__attribute__((aligned (4))) a[7]; };
> +
> +void
> +test (struct dummy a, ...)
> +{
> +  va_list va_arglist;
> +  int i;
> +
> +  va_start (va_arglist, a);
> +  i = va_arg (va_arglist, int);
> +  if (i != 0x10)
> +    __builtin_abort ();
> +  va_end (va_arglist);
> +}
> +
> +struct dummy a0;
> +
> +int
> +main ()
> +{
> +  test (a0, 0x10);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/pr68355.C b/gcc/testsuite/g++.dg/pr68355.C
> new file mode 100644
> index 0000000..1354fc4
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/pr68355.C
> @@ -0,0 +1,24 @@
> +// { dg-do compile }
> +// { dg-options "-O2 -std=c++11 -fno-pic" }
> +// { dg-require-effective-target fpic }
> +
> +template<typename _Tp, _Tp __v>
> +struct integral_constant
> +{
> +  static constexpr _Tp value = __v;
> +  typedef _Tp value_type;
> +  typedef integral_constant<_Tp, __v> type;
> +  constexpr operator value_type() const { return value; }
> +};
> +
> +typedef integral_constant<bool, true> true_type;
> +extern void xxx (true_type c);
> +
> +void
> +yyy (void)
> +{
> +  true_type y;
> +  xxx (y);
> +}
> +
> +// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx17integral_constantIbLb1EE" { target i?86-*-* x86_64-*-* } } }
> diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
> index bb5cd49..6b1e25d 100644
> --- a/gcc/tree-dfa.c
> +++ b/gcc/tree-dfa.c
> @@ -394,6 +394,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
>        machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
>        if (mode == BLKmode)
>         size_tree = TYPE_SIZE (TREE_TYPE (exp));
> +      else if (lang_hooks.decls.empty_record_p (TREE_TYPE (exp)))
> +       bitsize = 0;
>        else
>         bitsize = int (GET_MODE_PRECISION (mode));
>      }
> diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
> index 65a1ce3..1c32d81 100644
> --- a/gcc/tree-streamer-in.c
> +++ b/gcc/tree-streamer-in.c
> @@ -154,6 +154,11 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
>      }
>    else
>      bp_unpack_value (bp, 9);
> +  if (TYPE_P (expr))
> +    /* Set if a record is empty.  */
> +    TYPE_LANG_FLAG_0 (expr) = (unsigned) bp_unpack_value (bp, 1);
> +  else
> +     bp_unpack_value (bp, 1);
>  }
>
>
> diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
> index d0b7f6d..a1bf962 100644
> --- a/gcc/tree-streamer-out.c
> +++ b/gcc/tree-streamer-out.c
> @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "alias.h"
>  #include "stor-layout.h"
>  #include "gomp-constants.h"
> +#include "langhooks.h"
>
>
>  /* Output the STRING constant to the string
> @@ -128,6 +129,11 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
>      }
>    else
>      bp_pack_value (bp, 0, 9);
> +  if (TYPE_P (expr))
> +    /* Stream out a bit to indicate if a record is empty.  */
> +    bp_pack_value (bp, lang_hooks.decls.empty_record_p (expr), 1);
> +  else
> +    bp_pack_value (bp, 0, 1);
>  }
>
>
> --
> 2.4.3
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]