diff mbox

Improve DWARF constant attribute langhooks

Message ID 20161014172927.GK7282@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Oct. 14, 2016, 5:29 p.m. UTC
Hi!

Before early dwarf changes, if we wanted to note some decl property so that
some corresponding DWARF attribute can be emitted, we had to use some
generic IL bit for that.  Now a langhook can be used instead (hopefully for
7.x even with LTO), but having a single langhook for each such bit looks
excessive to me, when all we actually want is forward some bits from the C++
FE lang structures/macros to dwarf2out.

So, this patch introduces a lang hook through which dwarf2out can ask if
some DW_AT_* attribute should be added to decl (it is dwarf2out's business
to guard it with dwarf_version, dwarf_strict and other conditions), and the
lang hook just returns -1 if nothing should be added (most attributes we
care about here have either boolean 0/1 or small unsigned integer values),
or the value of the attribute that should be added.

I've converted 3 attributes to this new langhook.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-10-14  Jakub Jelinek  <jakub@redhat.com>

	* langhooks.h (struct lang_hooks_for_decls): Remove
	function_decl_explicit_p, function_decl_deleted_p and
	function_decl_defaulted hooks.  Add decl_dwarf_attribute hook.
	* langhooks-def.h (lhd_decl_dwarf_attribute): Declare.
	(LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
	LANG_HOOKS_FUNCTION_DECL_DELETED_P,
	LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Remove.
	(LANG_HOOKS_DECL_DWARF_ATTRIBUTE): Define.
	(LANG_HOOKS_DECLS): Remove LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
	LANG_HOOKS_FUNCTION_DECL_DELETED_P and
	LANG_HOOKS_FUNCTION_DECL_DEFAULTED.  Add
	LANG_HOOKS_DECL_DWARF_ATTRIBUTE.
	* langhooks.c (lhd_decl_dwarf_attribute): New function.
	* dwarf2out.c (gen_subprogram_die): Use
	lang_hooks.decls.decl_dwarf_attribute instead of
	lang_hooks.decls.function_decl_*.
cp/
	* cp-objcp-common.h (cp_function_decl_explicit_p,
	cp_function_decl_deleted_p, cp_function_decl_defaulted): Remove.
	(cp_decl_dwarf_attribute): Declare.
	(LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
	LANG_HOOKS_FUNCTION_DECL_DELETED_P,
	LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Remove.
	(LANG_HOOKS_DECL_DWARF_ATTRIBUTE): Redefine.
	* cp-objcp-common.c (cp_function_decl_explicit_p,
	cp_function_decl_deleted_p, cp_function_decl_defaulted): Remove.
	(cp_decl_dwarf_attribute): New function.


	Jakub

Comments

Jason Merrill Oct. 14, 2016, 9:55 p.m. UTC | #1
OK.

On Fri, Oct 14, 2016 at 1:29 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> Before early dwarf changes, if we wanted to note some decl property so that
> some corresponding DWARF attribute can be emitted, we had to use some
> generic IL bit for that.  Now a langhook can be used instead (hopefully for
> 7.x even with LTO), but having a single langhook for each such bit looks
> excessive to me, when all we actually want is forward some bits from the C++
> FE lang structures/macros to dwarf2out.
>
> So, this patch introduces a lang hook through which dwarf2out can ask if
> some DW_AT_* attribute should be added to decl (it is dwarf2out's business
> to guard it with dwarf_version, dwarf_strict and other conditions), and the
> lang hook just returns -1 if nothing should be added (most attributes we
> care about here have either boolean 0/1 or small unsigned integer values),
> or the value of the attribute that should be added.
>
> I've converted 3 attributes to this new langhook.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2016-10-14  Jakub Jelinek  <jakub@redhat.com>
>
>         * langhooks.h (struct lang_hooks_for_decls): Remove
>         function_decl_explicit_p, function_decl_deleted_p and
>         function_decl_defaulted hooks.  Add decl_dwarf_attribute hook.
>         * langhooks-def.h (lhd_decl_dwarf_attribute): Declare.
>         (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
>         LANG_HOOKS_FUNCTION_DECL_DELETED_P,
>         LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Remove.
>         (LANG_HOOKS_DECL_DWARF_ATTRIBUTE): Define.
>         (LANG_HOOKS_DECLS): Remove LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
>         LANG_HOOKS_FUNCTION_DECL_DELETED_P and
>         LANG_HOOKS_FUNCTION_DECL_DEFAULTED.  Add
>         LANG_HOOKS_DECL_DWARF_ATTRIBUTE.
>         * langhooks.c (lhd_decl_dwarf_attribute): New function.
>         * dwarf2out.c (gen_subprogram_die): Use
>         lang_hooks.decls.decl_dwarf_attribute instead of
>         lang_hooks.decls.function_decl_*.
> cp/
>         * cp-objcp-common.h (cp_function_decl_explicit_p,
>         cp_function_decl_deleted_p, cp_function_decl_defaulted): Remove.
>         (cp_decl_dwarf_attribute): Declare.
>         (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
>         LANG_HOOKS_FUNCTION_DECL_DELETED_P,
>         LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Remove.
>         (LANG_HOOKS_DECL_DWARF_ATTRIBUTE): Redefine.
>         * cp-objcp-common.c (cp_function_decl_explicit_p,
>         cp_function_decl_deleted_p, cp_function_decl_defaulted): Remove.
>         (cp_decl_dwarf_attribute): New function.
>
> --- gcc/langhooks.h.jj  2016-10-13 10:24:46.000000000 +0200
> +++ gcc/langhooks.h     2016-10-14 14:27:07.806695803 +0200
> @@ -182,16 +182,9 @@ struct lang_hooks_for_decls
>    /* Returns the chain of decls so far in the current scope level.  */
>    tree (*getdecls) (void);
>
> -  /* Returns true if DECL is explicit member function.  */
> -  bool (*function_decl_explicit_p) (const_tree);
> -
> -  /* Returns true if DECL is C++11 deleted special member function.  */
> -  bool (*function_decl_deleted_p) (const_tree);
> -
> -  /* Returns 0 if DECL is NOT a C++11 defaulted special member
> -     function, 1 if it is explicitly defaulted within the class body,
> -     or 2 if it is explicitly defaulted outside the class body.  */
> -  int (*function_decl_defaulted) (const_tree);
> +  /* Returns -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
> +     value otherwise.  */
> +  int (*decl_dwarf_attribute) (const_tree, int);
>
>    /* Returns True if the parameter is a generic parameter decl
>       of a generic type, e.g a template template parameter for the C++ FE.  */
> --- gcc/langhooks-def.h.jj      2016-10-13 10:28:19.000000000 +0200
> +++ gcc/langhooks-def.h 2016-10-14 14:29:09.535146412 +0200
> @@ -83,6 +83,7 @@ extern bool lhd_omp_mappable_type (tree)
>
>  extern const char *lhd_get_substring_location (const substring_loc &,
>                                                location_t *out_loc);
> +extern int lhd_decl_dwarf_attribute (const_tree, int);
>
>  #define LANG_HOOKS_NAME                        "GNU unknown"
>  #define LANG_HOOKS_IDENTIFIER_SIZE     sizeof (struct lang_identifier)
> @@ -213,9 +214,7 @@ extern tree lhd_make_node (enum tree_cod
>  #define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p
>  #define LANG_HOOKS_PUSHDECL    pushdecl
>  #define LANG_HOOKS_GETDECLS    getdecls
> -#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_const_tree_false
> -#define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_const_tree_false
> -#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED hook_int_const_tree_0
> +#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE lhd_decl_dwarf_attribute
>  #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
>  #define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
>  #define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
> @@ -236,9 +235,7 @@ extern tree lhd_make_node (enum tree_cod
>    LANG_HOOKS_GLOBAL_BINDINGS_P, \
>    LANG_HOOKS_PUSHDECL, \
>    LANG_HOOKS_GETDECLS, \
> -  LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
> -  LANG_HOOKS_FUNCTION_DECL_DELETED_P, \
> -  LANG_HOOKS_FUNCTION_DECL_DEFAULTED, \
> +  LANG_HOOKS_DECL_DWARF_ATTRIBUTE, \
>    LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
>    LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
>    LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
> --- gcc/langhooks.c.jj  2016-10-13 10:28:19.000000000 +0200
> +++ gcc/langhooks.c     2016-10-14 14:27:16.810581200 +0200
> @@ -693,6 +693,15 @@ lhd_get_substring_location (const substr
>    return "unimplemented";
>  }
>
> +/* Default implementation of LANG_HOOKS_DECL_DWARF_ATTRIBUTE.  Don't add
> +   any attributes.  */
> +
> +int
> +lhd_decl_dwarf_attribute (const_tree, int)
> +{
> +  return -1;
> +}
> +
>  /* Returns true if the current lang_hooks represents the GNU C frontend.  */
>
>  bool
> --- gcc/dwarf2out.c.jj  2016-10-14 12:31:50.000000000 +0200
> +++ gcc/dwarf2out.c     2016-10-14 14:37:15.481961156 +0200
> @@ -20625,20 +20625,19 @@ gen_subprogram_die (tree decl, dw_die_re
>           /* When we process the method declaration, we haven't seen
>              the out-of-class defaulted definition yet, so we have to
>              recheck now.  */
> -         int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
> -         if (defaulted && (dwarf_version >= 5 || ! dwarf_strict)
> +         if ((dwarf_version >= 5 || ! dwarf_strict)
>               && !get_AT (subr_die, DW_AT_defaulted))
> -           switch (defaulted)
> -             {
> -             case 2:
> -               add_AT_unsigned (subr_die, DW_AT_defaulted,
> -                                DW_DEFAULTED_out_of_class);
> -               break;
> -
> -             case 1: /* This must have been handled before.  */
> -             default:
> -               gcc_unreachable ();
> -             }
> +           {
> +             int defaulted
> +               = lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                        DW_AT_defaulted);
> +             if (defaulted != -1)
> +               {
> +                 /* Other values must have been handled before.  */
> +                 gcc_assert (defaulted == DW_DEFAULTED_out_of_class);
> +                 add_AT_unsigned (subr_die, DW_AT_defaulted, defaulted);
> +               }
> +           }
>         }
>      }
>    /* Create a fresh DIE for anything else.  */
> @@ -20681,40 +20680,28 @@ gen_subprogram_die (tree decl, dw_die_re
>
>           /* If this is an explicit function declaration then generate
>              a DW_AT_explicit attribute.  */
> -         if (lang_hooks.decls.function_decl_explicit_p (decl)
> -             && (dwarf_version >= 3 || !dwarf_strict))
> +         if ((dwarf_version >= 3 || !dwarf_strict)
> +             && lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                       DW_AT_explicit) == 1)
>             add_AT_flag (subr_die, DW_AT_explicit, 1);
>
>           /* If this is a C++11 deleted special function member then generate
>              a DW_AT_deleted attribute.  */
> -         if (lang_hooks.decls.function_decl_deleted_p (decl)
> -             && (dwarf_version >= 5 || ! dwarf_strict))
> +         if ((dwarf_version >= 5 || !dwarf_strict)
> +             && lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                       DW_AT_deleted) == 1)
>             add_AT_flag (subr_die, DW_AT_deleted, 1);
>
>           /* If this is a C++11 defaulted special function member then
>              generate a DW_AT_GNU_defaulted attribute.  */
> -         int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
> -         if (defaulted && (dwarf_version >= 5 || ! dwarf_strict))
> -           switch (defaulted)
> -             {
> -             case 1:
> -               add_AT_unsigned (subr_die, DW_AT_defaulted,
> -                                DW_DEFAULTED_in_class);
> -               break;
> -
> -               /* It is likely that this will never hit, since we
> -                  don't have the out-of-class definition yet when we
> -                  process the class definition and the method
> -                  declaration.  We recheck elsewhere, but leave it
> -                  here just in case.  */
> -             case 2:
> -               add_AT_unsigned (subr_die, DW_AT_defaulted,
> -                                DW_DEFAULTED_out_of_class);
> -               break;
> -
> -             default:
> -               gcc_unreachable ();
> -             }
> +         if (dwarf_version >= 5 || !dwarf_strict)
> +           {
> +             int defaulted
> +               = lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                        DW_AT_defaulted);
> +             if (defaulted != -1)
> +               add_AT_unsigned (subr_die, DW_AT_defaulted, defaulted);
> +           }
>         }
>      }
>    /* Tag abstract instances with DW_AT_inline.  */
> --- gcc/cp/cp-objcp-common.h.jj 2016-08-12 11:12:46.000000000 +0200
> +++ gcc/cp/cp-objcp-common.h    2016-10-14 14:27:45.223219556 +0200
> @@ -26,9 +26,7 @@ along with GCC; see the file COPYING3.
>  extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
>                                          tree, bool);
>
> -extern bool cp_function_decl_explicit_p (const_tree decl);
> -extern bool cp_function_decl_deleted_p (const_tree decl);
> -extern int cp_function_decl_defaulted (const_tree decl);
> +extern int cp_decl_dwarf_attribute (const_tree, int);
>  extern void cp_common_init_ts (void);
>
>  /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
> @@ -131,12 +129,8 @@ extern void cp_common_init_ts (void);
>  #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
>  #undef LANG_HOOKS_GIMPLIFY_EXPR
>  #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
> -#undef LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P
> -#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P cp_function_decl_explicit_p
> -#undef LANG_HOOKS_FUNCTION_DECL_DELETED_P
> -#define LANG_HOOKS_FUNCTION_DECL_DELETED_P cp_function_decl_deleted_p
> -#undef LANG_HOOKS_FUNCTION_DECL_DEFAULTED
> -#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED cp_function_decl_defaulted
> +#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
> +#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
>  #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
>  #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
>  #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
> --- gcc/cp/cp-objcp-common.c.jj 2016-10-07 21:36:47.000000000 +0200
> +++ gcc/cp/cp-objcp-common.c    2016-10-14 14:27:56.923070637 +0200
> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.
>  #include "coretypes.h"
>  #include "cp-tree.h"
>  #include "cp-objcp-common.h"
> +#include "dwarf2.h"
>
>  /* Special routine to get the alias set for C++.  */
>
> @@ -130,45 +131,48 @@ cxx_types_compatible_p (tree x, tree y)
>    return same_type_ignoring_top_level_qualifiers_p (x, y);
>  }
>
> -/* Return true if DECL is explicit member function.  */
> -
> -bool
> -cp_function_decl_explicit_p (const_tree decl)
> +/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
> +   value otherwise.  */
> +int
> +cp_decl_dwarf_attribute (const_tree decl, int attr)
>  {
> -  return (decl
> -         && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> -         && DECL_NONCONVERTING_P (decl));
> -}
> +  if (decl == NULL_TREE)
> +    return -1;
>
> -/* Return true if DECL is deleted special member function.  */
> -
> -bool
> -cp_function_decl_deleted_p (const_tree decl)
> -{
> -  return (decl
> +  switch (attr)
> +    {
> +    case DW_AT_explicit:
> +      if (TREE_CODE (decl) == FUNCTION_DECL
>           && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> -         && DECL_DELETED_FN (decl));
> -}
> -
> -/* Returns 0 if DECL is NOT a C++11 defaulted special member function,
> -   1 if it is explicitly defaulted within the class body, or 2 if it
> -   is explicitly defaulted outside the class body.  */
> +         && DECL_NONCONVERTING_P (decl))
> +       return 1;
> +      break;
>
> -int
> -cp_function_decl_defaulted (const_tree decl)
> -{
> -  if (decl
> -      && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> -      && DECL_DEFAULTED_FN (decl))
> -    {
> -      if (DECL_DEFAULTED_IN_CLASS_P (decl))
> +    case DW_AT_deleted:
> +      if (TREE_CODE (decl) == FUNCTION_DECL
> +         && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> +         && DECL_DELETED_FN (decl))
>         return 1;
> +      break;
> +
> +    case DW_AT_defaulted:
> +      if (TREE_CODE (decl) == FUNCTION_DECL
> +         && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> +         && DECL_DEFAULTED_FN (decl))
> +       {
> +         if (DECL_DEFAULTED_IN_CLASS_P (decl))
> +           return DW_DEFAULTED_in_class;
> +
> +         if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
> +           return DW_DEFAULTED_out_of_class;
> +       }
> +      break;
>
> -      if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
> -       return 2;
> +    default:
> +      break;
>      }
>
> -  return 0;
> +  return -1;
>  }
>
>  /* Stubs to keep c-opts.c happy.  */
>
>         Jakub
Richard Biener Oct. 17, 2016, 8:36 a.m. UTC | #2
On Fri, Oct 14, 2016 at 7:29 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> Before early dwarf changes, if we wanted to note some decl property so that
> some corresponding DWARF attribute can be emitted, we had to use some
> generic IL bit for that.  Now a langhook can be used instead (hopefully for
> 7.x even with LTO), but having a single langhook for each such bit looks
> excessive to me, when all we actually want is forward some bits from the C++
> FE lang structures/macros to dwarf2out.
>
> So, this patch introduces a lang hook through which dwarf2out can ask if
> some DW_AT_* attribute should be added to decl (it is dwarf2out's business
> to guard it with dwarf_version, dwarf_strict and other conditions), and the
> lang hook just returns -1 if nothing should be added (most attributes we
> care about here have either boolean 0/1 or small unsigned integer values),
> or the value of the attribute that should be added.
>
> I've converted 3 attributes to this new langhook.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

At the GNU Cauldron I talked with AdaCore folks about how to generally
move forward with debug info format support (the specific question was
about the Windows one).  I shared my opinion that the middle-end should
move to a DWARF-only representation, all debug hooks should be removed
and the FEs given direct access to (a subset of) the dwarf2out API.

GCC would have to cease supporting the stabs variants or output them
from the DWARF IL we have.  I believe this is what LLVM does.
(I specifically discouraged the AdaCore folks from writing a windows
debug format within the current framework).

Your langhook could have been sth like lang_hooks.annotate_die
(dw_die_ref *, tree)
with exposing the dwarf API and thus letting the FE amend a DIE as it likes
(instead of just exposing three attributes).

Richard.

> 2016-10-14  Jakub Jelinek  <jakub@redhat.com>
>
>         * langhooks.h (struct lang_hooks_for_decls): Remove
>         function_decl_explicit_p, function_decl_deleted_p and
>         function_decl_defaulted hooks.  Add decl_dwarf_attribute hook.
>         * langhooks-def.h (lhd_decl_dwarf_attribute): Declare.
>         (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
>         LANG_HOOKS_FUNCTION_DECL_DELETED_P,
>         LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Remove.
>         (LANG_HOOKS_DECL_DWARF_ATTRIBUTE): Define.
>         (LANG_HOOKS_DECLS): Remove LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
>         LANG_HOOKS_FUNCTION_DECL_DELETED_P and
>         LANG_HOOKS_FUNCTION_DECL_DEFAULTED.  Add
>         LANG_HOOKS_DECL_DWARF_ATTRIBUTE.
>         * langhooks.c (lhd_decl_dwarf_attribute): New function.
>         * dwarf2out.c (gen_subprogram_die): Use
>         lang_hooks.decls.decl_dwarf_attribute instead of
>         lang_hooks.decls.function_decl_*.
> cp/
>         * cp-objcp-common.h (cp_function_decl_explicit_p,
>         cp_function_decl_deleted_p, cp_function_decl_defaulted): Remove.
>         (cp_decl_dwarf_attribute): Declare.
>         (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P,
>         LANG_HOOKS_FUNCTION_DECL_DELETED_P,
>         LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Remove.
>         (LANG_HOOKS_DECL_DWARF_ATTRIBUTE): Redefine.
>         * cp-objcp-common.c (cp_function_decl_explicit_p,
>         cp_function_decl_deleted_p, cp_function_decl_defaulted): Remove.
>         (cp_decl_dwarf_attribute): New function.
>
> --- gcc/langhooks.h.jj  2016-10-13 10:24:46.000000000 +0200
> +++ gcc/langhooks.h     2016-10-14 14:27:07.806695803 +0200
> @@ -182,16 +182,9 @@ struct lang_hooks_for_decls
>    /* Returns the chain of decls so far in the current scope level.  */
>    tree (*getdecls) (void);
>
> -  /* Returns true if DECL is explicit member function.  */
> -  bool (*function_decl_explicit_p) (const_tree);
> -
> -  /* Returns true if DECL is C++11 deleted special member function.  */
> -  bool (*function_decl_deleted_p) (const_tree);
> -
> -  /* Returns 0 if DECL is NOT a C++11 defaulted special member
> -     function, 1 if it is explicitly defaulted within the class body,
> -     or 2 if it is explicitly defaulted outside the class body.  */
> -  int (*function_decl_defaulted) (const_tree);
> +  /* Returns -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
> +     value otherwise.  */
> +  int (*decl_dwarf_attribute) (const_tree, int);
>
>    /* Returns True if the parameter is a generic parameter decl
>       of a generic type, e.g a template template parameter for the C++ FE.  */
> --- gcc/langhooks-def.h.jj      2016-10-13 10:28:19.000000000 +0200
> +++ gcc/langhooks-def.h 2016-10-14 14:29:09.535146412 +0200
> @@ -83,6 +83,7 @@ extern bool lhd_omp_mappable_type (tree)
>
>  extern const char *lhd_get_substring_location (const substring_loc &,
>                                                location_t *out_loc);
> +extern int lhd_decl_dwarf_attribute (const_tree, int);
>
>  #define LANG_HOOKS_NAME                        "GNU unknown"
>  #define LANG_HOOKS_IDENTIFIER_SIZE     sizeof (struct lang_identifier)
> @@ -213,9 +214,7 @@ extern tree lhd_make_node (enum tree_cod
>  #define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p
>  #define LANG_HOOKS_PUSHDECL    pushdecl
>  #define LANG_HOOKS_GETDECLS    getdecls
> -#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_const_tree_false
> -#define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_const_tree_false
> -#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED hook_int_const_tree_0
> +#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE lhd_decl_dwarf_attribute
>  #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
>  #define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
>  #define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
> @@ -236,9 +235,7 @@ extern tree lhd_make_node (enum tree_cod
>    LANG_HOOKS_GLOBAL_BINDINGS_P, \
>    LANG_HOOKS_PUSHDECL, \
>    LANG_HOOKS_GETDECLS, \
> -  LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
> -  LANG_HOOKS_FUNCTION_DECL_DELETED_P, \
> -  LANG_HOOKS_FUNCTION_DECL_DEFAULTED, \
> +  LANG_HOOKS_DECL_DWARF_ATTRIBUTE, \
>    LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
>    LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
>    LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
> --- gcc/langhooks.c.jj  2016-10-13 10:28:19.000000000 +0200
> +++ gcc/langhooks.c     2016-10-14 14:27:16.810581200 +0200
> @@ -693,6 +693,15 @@ lhd_get_substring_location (const substr
>    return "unimplemented";
>  }
>
> +/* Default implementation of LANG_HOOKS_DECL_DWARF_ATTRIBUTE.  Don't add
> +   any attributes.  */
> +
> +int
> +lhd_decl_dwarf_attribute (const_tree, int)
> +{
> +  return -1;
> +}
> +
>  /* Returns true if the current lang_hooks represents the GNU C frontend.  */
>
>  bool
> --- gcc/dwarf2out.c.jj  2016-10-14 12:31:50.000000000 +0200
> +++ gcc/dwarf2out.c     2016-10-14 14:37:15.481961156 +0200
> @@ -20625,20 +20625,19 @@ gen_subprogram_die (tree decl, dw_die_re
>           /* When we process the method declaration, we haven't seen
>              the out-of-class defaulted definition yet, so we have to
>              recheck now.  */
> -         int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
> -         if (defaulted && (dwarf_version >= 5 || ! dwarf_strict)
> +         if ((dwarf_version >= 5 || ! dwarf_strict)
>               && !get_AT (subr_die, DW_AT_defaulted))
> -           switch (defaulted)
> -             {
> -             case 2:
> -               add_AT_unsigned (subr_die, DW_AT_defaulted,
> -                                DW_DEFAULTED_out_of_class);
> -               break;
> -
> -             case 1: /* This must have been handled before.  */
> -             default:
> -               gcc_unreachable ();
> -             }
> +           {
> +             int defaulted
> +               = lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                        DW_AT_defaulted);
> +             if (defaulted != -1)
> +               {
> +                 /* Other values must have been handled before.  */
> +                 gcc_assert (defaulted == DW_DEFAULTED_out_of_class);
> +                 add_AT_unsigned (subr_die, DW_AT_defaulted, defaulted);
> +               }
> +           }
>         }
>      }
>    /* Create a fresh DIE for anything else.  */
> @@ -20681,40 +20680,28 @@ gen_subprogram_die (tree decl, dw_die_re
>
>           /* If this is an explicit function declaration then generate
>              a DW_AT_explicit attribute.  */
> -         if (lang_hooks.decls.function_decl_explicit_p (decl)
> -             && (dwarf_version >= 3 || !dwarf_strict))
> +         if ((dwarf_version >= 3 || !dwarf_strict)
> +             && lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                       DW_AT_explicit) == 1)
>             add_AT_flag (subr_die, DW_AT_explicit, 1);
>
>           /* If this is a C++11 deleted special function member then generate
>              a DW_AT_deleted attribute.  */
> -         if (lang_hooks.decls.function_decl_deleted_p (decl)
> -             && (dwarf_version >= 5 || ! dwarf_strict))
> +         if ((dwarf_version >= 5 || !dwarf_strict)
> +             && lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                       DW_AT_deleted) == 1)
>             add_AT_flag (subr_die, DW_AT_deleted, 1);
>
>           /* If this is a C++11 defaulted special function member then
>              generate a DW_AT_GNU_defaulted attribute.  */
> -         int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
> -         if (defaulted && (dwarf_version >= 5 || ! dwarf_strict))
> -           switch (defaulted)
> -             {
> -             case 1:
> -               add_AT_unsigned (subr_die, DW_AT_defaulted,
> -                                DW_DEFAULTED_in_class);
> -               break;
> -
> -               /* It is likely that this will never hit, since we
> -                  don't have the out-of-class definition yet when we
> -                  process the class definition and the method
> -                  declaration.  We recheck elsewhere, but leave it
> -                  here just in case.  */
> -             case 2:
> -               add_AT_unsigned (subr_die, DW_AT_defaulted,
> -                                DW_DEFAULTED_out_of_class);
> -               break;
> -
> -             default:
> -               gcc_unreachable ();
> -             }
> +         if (dwarf_version >= 5 || !dwarf_strict)
> +           {
> +             int defaulted
> +               = lang_hooks.decls.decl_dwarf_attribute (decl,
> +                                                        DW_AT_defaulted);
> +             if (defaulted != -1)
> +               add_AT_unsigned (subr_die, DW_AT_defaulted, defaulted);
> +           }
>         }
>      }
>    /* Tag abstract instances with DW_AT_inline.  */
> --- gcc/cp/cp-objcp-common.h.jj 2016-08-12 11:12:46.000000000 +0200
> +++ gcc/cp/cp-objcp-common.h    2016-10-14 14:27:45.223219556 +0200
> @@ -26,9 +26,7 @@ along with GCC; see the file COPYING3.
>  extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
>                                          tree, bool);
>
> -extern bool cp_function_decl_explicit_p (const_tree decl);
> -extern bool cp_function_decl_deleted_p (const_tree decl);
> -extern int cp_function_decl_defaulted (const_tree decl);
> +extern int cp_decl_dwarf_attribute (const_tree, int);
>  extern void cp_common_init_ts (void);
>
>  /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
> @@ -131,12 +129,8 @@ extern void cp_common_init_ts (void);
>  #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
>  #undef LANG_HOOKS_GIMPLIFY_EXPR
>  #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
> -#undef LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P
> -#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P cp_function_decl_explicit_p
> -#undef LANG_HOOKS_FUNCTION_DECL_DELETED_P
> -#define LANG_HOOKS_FUNCTION_DECL_DELETED_P cp_function_decl_deleted_p
> -#undef LANG_HOOKS_FUNCTION_DECL_DEFAULTED
> -#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED cp_function_decl_defaulted
> +#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
> +#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
>  #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
>  #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
>  #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
> --- gcc/cp/cp-objcp-common.c.jj 2016-10-07 21:36:47.000000000 +0200
> +++ gcc/cp/cp-objcp-common.c    2016-10-14 14:27:56.923070637 +0200
> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.
>  #include "coretypes.h"
>  #include "cp-tree.h"
>  #include "cp-objcp-common.h"
> +#include "dwarf2.h"
>
>  /* Special routine to get the alias set for C++.  */
>
> @@ -130,45 +131,48 @@ cxx_types_compatible_p (tree x, tree y)
>    return same_type_ignoring_top_level_qualifiers_p (x, y);
>  }
>
> -/* Return true if DECL is explicit member function.  */
> -
> -bool
> -cp_function_decl_explicit_p (const_tree decl)
> +/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
> +   value otherwise.  */
> +int
> +cp_decl_dwarf_attribute (const_tree decl, int attr)
>  {
> -  return (decl
> -         && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> -         && DECL_NONCONVERTING_P (decl));
> -}
> +  if (decl == NULL_TREE)
> +    return -1;
>
> -/* Return true if DECL is deleted special member function.  */
> -
> -bool
> -cp_function_decl_deleted_p (const_tree decl)
> -{
> -  return (decl
> +  switch (attr)
> +    {
> +    case DW_AT_explicit:
> +      if (TREE_CODE (decl) == FUNCTION_DECL
>           && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> -         && DECL_DELETED_FN (decl));
> -}
> -
> -/* Returns 0 if DECL is NOT a C++11 defaulted special member function,
> -   1 if it is explicitly defaulted within the class body, or 2 if it
> -   is explicitly defaulted outside the class body.  */
> +         && DECL_NONCONVERTING_P (decl))
> +       return 1;
> +      break;
>
> -int
> -cp_function_decl_defaulted (const_tree decl)
> -{
> -  if (decl
> -      && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> -      && DECL_DEFAULTED_FN (decl))
> -    {
> -      if (DECL_DEFAULTED_IN_CLASS_P (decl))
> +    case DW_AT_deleted:
> +      if (TREE_CODE (decl) == FUNCTION_DECL
> +         && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> +         && DECL_DELETED_FN (decl))
>         return 1;
> +      break;
> +
> +    case DW_AT_defaulted:
> +      if (TREE_CODE (decl) == FUNCTION_DECL
> +         && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
> +         && DECL_DEFAULTED_FN (decl))
> +       {
> +         if (DECL_DEFAULTED_IN_CLASS_P (decl))
> +           return DW_DEFAULTED_in_class;
> +
> +         if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
> +           return DW_DEFAULTED_out_of_class;
> +       }
> +      break;
>
> -      if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
> -       return 2;
> +    default:
> +      break;
>      }
>
> -  return 0;
> +  return -1;
>  }
>
>  /* Stubs to keep c-opts.c happy.  */
>
>         Jakub
Jakub Jelinek Oct. 17, 2016, 8:45 a.m. UTC | #3
On Mon, Oct 17, 2016 at 10:36:48AM +0200, Richard Biener wrote:
> GCC would have to cease supporting the stabs variants or output them
> from the DWARF IL we have.  I believe this is what LLVM does.
> (I specifically discouraged the AdaCore folks from writing a windows
> debug format within the current framework).
> 
> Your langhook could have been sth like lang_hooks.annotate_die
> (dw_die_ref *, tree)
> with exposing the dwarf API and thus letting the FE amend a DIE as it likes
> (instead of just exposing three attributes).

I think that would risk FEs would then repeat too much stuff that dwarf2out
could do for them, many attributes are used by multiple languages for the
same or similar purpose.  E.g. the current langhooks for DW_AT_inline is used
multiple times, not just to add the attribute but also for other purposes
before it happens.  Plus allowing other files to use the dwarf2out
infrastructure would be quite a lot of work.

As for emitting other debug formats from DWARF, I guess that is reasonable,
but the question is whether anybody still cares about stabs enough to
convert it.

	Jakub
Richard Biener Oct. 17, 2016, 9 a.m. UTC | #4
On Mon, Oct 17, 2016 at 10:45 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Mon, Oct 17, 2016 at 10:36:48AM +0200, Richard Biener wrote:
>> GCC would have to cease supporting the stabs variants or output them
>> from the DWARF IL we have.  I believe this is what LLVM does.
>> (I specifically discouraged the AdaCore folks from writing a windows
>> debug format within the current framework).
>>
>> Your langhook could have been sth like lang_hooks.annotate_die
>> (dw_die_ref *, tree)
>> with exposing the dwarf API and thus letting the FE amend a DIE as it likes
>> (instead of just exposing three attributes).
>
> I think that would risk FEs would then repeat too much stuff that dwarf2out
> could do for them, many attributes are used by multiple languages for the
> same or similar purpose.  E.g. the current langhooks for DW_AT_inline is used
> multiple times, not just to add the attribute but also for other purposes
> before it happens.  Plus allowing other files to use the dwarf2out
> infrastructure would be quite a lot of work.

Sure.  But the current way of trying to put everything into trees somewhere and
then make dwarf2out reverse-engineer stuff doesn't really scale.  Yes, adding
more langhooks and more debug hooks would be the current canonical way
of addressing things in a better way.  But then debug hooks would just become
high-level entry into the DWARF machinery.

> As for emitting other debug formats from DWARF, I guess that is reasonable,
> but the question is whether anybody still cares about stabs enough to
> convert it.

I'd be happy to remove stabs support but IIRC we still have targets that default
to stabs.

Richard.

>         Jakub
diff mbox

Patch

--- gcc/langhooks.h.jj	2016-10-13 10:24:46.000000000 +0200
+++ gcc/langhooks.h	2016-10-14 14:27:07.806695803 +0200
@@ -182,16 +182,9 @@  struct lang_hooks_for_decls
   /* Returns the chain of decls so far in the current scope level.  */
   tree (*getdecls) (void);
 
-  /* Returns true if DECL is explicit member function.  */
-  bool (*function_decl_explicit_p) (const_tree);
-
-  /* Returns true if DECL is C++11 deleted special member function.  */
-  bool (*function_decl_deleted_p) (const_tree);
-
-  /* Returns 0 if DECL is NOT a C++11 defaulted special member
-     function, 1 if it is explicitly defaulted within the class body,
-     or 2 if it is explicitly defaulted outside the class body.  */
-  int (*function_decl_defaulted) (const_tree);
+  /* Returns -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
+     value otherwise.  */
+  int (*decl_dwarf_attribute) (const_tree, int);
 
   /* Returns True if the parameter is a generic parameter decl
      of a generic type, e.g a template template parameter for the C++ FE.  */
--- gcc/langhooks-def.h.jj	2016-10-13 10:28:19.000000000 +0200
+++ gcc/langhooks-def.h	2016-10-14 14:29:09.535146412 +0200
@@ -83,6 +83,7 @@  extern bool lhd_omp_mappable_type (tree)
 
 extern const char *lhd_get_substring_location (const substring_loc &,
 					       location_t *out_loc);
+extern int lhd_decl_dwarf_attribute (const_tree, int);
 
 #define LANG_HOOKS_NAME			"GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
@@ -213,9 +214,7 @@  extern tree lhd_make_node (enum tree_cod
 #define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p
 #define LANG_HOOKS_PUSHDECL	pushdecl
 #define LANG_HOOKS_GETDECLS	getdecls
-#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_const_tree_false
-#define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_const_tree_false
-#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED hook_int_const_tree_0
+#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE lhd_decl_dwarf_attribute
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
 #define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
 #define LANG_HOOKS_DECL_OK_FOR_SIBCALL	lhd_decl_ok_for_sibcall
@@ -236,9 +235,7 @@  extern tree lhd_make_node (enum tree_cod
   LANG_HOOKS_GLOBAL_BINDINGS_P, \
   LANG_HOOKS_PUSHDECL, \
   LANG_HOOKS_GETDECLS, \
-  LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
-  LANG_HOOKS_FUNCTION_DECL_DELETED_P, \
-  LANG_HOOKS_FUNCTION_DECL_DEFAULTED, \
+  LANG_HOOKS_DECL_DWARF_ATTRIBUTE, \
   LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
   LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
   LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
--- gcc/langhooks.c.jj	2016-10-13 10:28:19.000000000 +0200
+++ gcc/langhooks.c	2016-10-14 14:27:16.810581200 +0200
@@ -693,6 +693,15 @@  lhd_get_substring_location (const substr
   return "unimplemented";
 }
 
+/* Default implementation of LANG_HOOKS_DECL_DWARF_ATTRIBUTE.  Don't add
+   any attributes.  */
+
+int
+lhd_decl_dwarf_attribute (const_tree, int)
+{
+  return -1;
+}
+
 /* Returns true if the current lang_hooks represents the GNU C frontend.  */
 
 bool
--- gcc/dwarf2out.c.jj	2016-10-14 12:31:50.000000000 +0200
+++ gcc/dwarf2out.c	2016-10-14 14:37:15.481961156 +0200
@@ -20625,20 +20625,19 @@  gen_subprogram_die (tree decl, dw_die_re
 	  /* When we process the method declaration, we haven't seen
 	     the out-of-class defaulted definition yet, so we have to
 	     recheck now.  */
-	  int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
-	  if (defaulted && (dwarf_version >= 5 || ! dwarf_strict)
+	  if ((dwarf_version >= 5 || ! dwarf_strict)
 	      && !get_AT (subr_die, DW_AT_defaulted))
-	    switch (defaulted)
-	      {
-	      case 2:
-		add_AT_unsigned (subr_die, DW_AT_defaulted,
-				 DW_DEFAULTED_out_of_class);
-		break;
-
-	      case 1: /* This must have been handled before.  */
-	      default:
-		gcc_unreachable ();
-	      }
+	    {
+	      int defaulted
+		= lang_hooks.decls.decl_dwarf_attribute (decl,
+							 DW_AT_defaulted);
+	      if (defaulted != -1)
+		{
+		  /* Other values must have been handled before.  */
+		  gcc_assert (defaulted == DW_DEFAULTED_out_of_class);
+		  add_AT_unsigned (subr_die, DW_AT_defaulted, defaulted);
+		}
+	    }
 	}
     }
   /* Create a fresh DIE for anything else.  */
@@ -20681,40 +20680,28 @@  gen_subprogram_die (tree decl, dw_die_re
 
 	  /* If this is an explicit function declaration then generate
 	     a DW_AT_explicit attribute.  */
-	  if (lang_hooks.decls.function_decl_explicit_p (decl)
-	      && (dwarf_version >= 3 || !dwarf_strict))
+	  if ((dwarf_version >= 3 || !dwarf_strict)
+	      && lang_hooks.decls.decl_dwarf_attribute (decl,
+							DW_AT_explicit) == 1)
 	    add_AT_flag (subr_die, DW_AT_explicit, 1);
 
 	  /* If this is a C++11 deleted special function member then generate
 	     a DW_AT_deleted attribute.  */
-	  if (lang_hooks.decls.function_decl_deleted_p (decl)
-	      && (dwarf_version >= 5 || ! dwarf_strict))
+	  if ((dwarf_version >= 5 || !dwarf_strict)
+	      && lang_hooks.decls.decl_dwarf_attribute (decl,
+							DW_AT_deleted) == 1)
 	    add_AT_flag (subr_die, DW_AT_deleted, 1);
 
 	  /* If this is a C++11 defaulted special function member then
 	     generate a DW_AT_GNU_defaulted attribute.  */
-	  int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
-	  if (defaulted && (dwarf_version >= 5 || ! dwarf_strict))
-	    switch (defaulted)
-	      {
-	      case 1:
-		add_AT_unsigned (subr_die, DW_AT_defaulted,
-				 DW_DEFAULTED_in_class);
-		break;
-
-		/* It is likely that this will never hit, since we
-		   don't have the out-of-class definition yet when we
-		   process the class definition and the method
-		   declaration.  We recheck elsewhere, but leave it
-		   here just in case.  */
-	      case 2:
-		add_AT_unsigned (subr_die, DW_AT_defaulted,
-				 DW_DEFAULTED_out_of_class);
-		break;
-
-	      default:
-		gcc_unreachable ();
-	      }
+	  if (dwarf_version >= 5 || !dwarf_strict)
+	    {
+	      int defaulted
+		= lang_hooks.decls.decl_dwarf_attribute (decl,
+							 DW_AT_defaulted);
+	      if (defaulted != -1)
+		add_AT_unsigned (subr_die, DW_AT_defaulted, defaulted);
+	    }
 	}
     }
   /* Tag abstract instances with DW_AT_inline.  */
--- gcc/cp/cp-objcp-common.h.jj	2016-08-12 11:12:46.000000000 +0200
+++ gcc/cp/cp-objcp-common.h	2016-10-14 14:27:45.223219556 +0200
@@ -26,9 +26,7 @@  along with GCC; see the file COPYING3.
 extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
 					 tree, bool);
 
-extern bool cp_function_decl_explicit_p (const_tree decl);
-extern bool cp_function_decl_deleted_p (const_tree decl);
-extern int cp_function_decl_defaulted (const_tree decl);
+extern int cp_decl_dwarf_attribute (const_tree, int);
 extern void cp_common_init_ts (void);
 
 /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
@@ -131,12 +129,8 @@  extern void cp_common_init_ts (void);
 #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
-#undef LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P
-#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P cp_function_decl_explicit_p
-#undef LANG_HOOKS_FUNCTION_DECL_DELETED_P
-#define LANG_HOOKS_FUNCTION_DECL_DELETED_P cp_function_decl_deleted_p
-#undef LANG_HOOKS_FUNCTION_DECL_DEFAULTED
-#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED cp_function_decl_defaulted
+#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
+#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
 #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
 #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
--- gcc/cp/cp-objcp-common.c.jj	2016-10-07 21:36:47.000000000 +0200
+++ gcc/cp/cp-objcp-common.c	2016-10-14 14:27:56.923070637 +0200
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.
 #include "coretypes.h"
 #include "cp-tree.h"
 #include "cp-objcp-common.h"
+#include "dwarf2.h"
 
 /* Special routine to get the alias set for C++.  */
 
@@ -130,45 +131,48 @@  cxx_types_compatible_p (tree x, tree y)
   return same_type_ignoring_top_level_qualifiers_p (x, y);
 }
 
-/* Return true if DECL is explicit member function.  */
-
-bool
-cp_function_decl_explicit_p (const_tree decl)
+/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
+   value otherwise.  */
+int
+cp_decl_dwarf_attribute (const_tree decl, int attr)
 {
-  return (decl
-	  && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
-	  && DECL_NONCONVERTING_P (decl));
-}
+  if (decl == NULL_TREE)
+    return -1;
 
-/* Return true if DECL is deleted special member function.  */
-
-bool
-cp_function_decl_deleted_p (const_tree decl)
-{
-  return (decl
+  switch (attr)
+    {
+    case DW_AT_explicit:
+      if (TREE_CODE (decl) == FUNCTION_DECL
 	  && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
-	  && DECL_DELETED_FN (decl));
-}
-
-/* Returns 0 if DECL is NOT a C++11 defaulted special member function,
-   1 if it is explicitly defaulted within the class body, or 2 if it
-   is explicitly defaulted outside the class body.  */
+	  && DECL_NONCONVERTING_P (decl))
+	return 1;
+      break;
 
-int
-cp_function_decl_defaulted (const_tree decl)
-{
-  if (decl
-      && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
-      && DECL_DEFAULTED_FN (decl))
-    {
-      if (DECL_DEFAULTED_IN_CLASS_P (decl))
+    case DW_AT_deleted:
+      if (TREE_CODE (decl) == FUNCTION_DECL
+	  && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
+	  && DECL_DELETED_FN (decl))
 	return 1;
+      break;
+
+    case DW_AT_defaulted:
+      if (TREE_CODE (decl) == FUNCTION_DECL
+	  && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
+	  && DECL_DEFAULTED_FN (decl))
+	{
+	  if (DECL_DEFAULTED_IN_CLASS_P (decl))
+	    return DW_DEFAULTED_in_class;
+
+	  if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
+	    return DW_DEFAULTED_out_of_class;
+	}
+      break;
 
-      if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
-	return 2;
+    default:
+      break;
     }
 
-  return 0;
+  return -1;
 }
 
 /* Stubs to keep c-opts.c happy.  */