From e366d7d807f8d06dc35570871ba2b723b78975af Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Fri, 12 Aug 2016 07:11:50 +0000 Subject: [PATCH] [PR63240] generate debug info for defaulted member functions This implements , a proposal already accepted for inclusion in DWARF-5, but using DW_AT_GNU_defaulted instead of DW_AT_defaulted as the attribute name, because the attribute id for DW_AT_defaulted is not yet publicly available. for include/ChangeLog PR debug/63240 * dwarf2.def (DW_AT_deleted, DW_AT_defaulted): New. * dwarf2.h (enu dwarf_defaulted_attribute): New. for gcc/ChangeLog PR debug/63240 * langhooks-def.h (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P): Const_tree-ify. (LANG_HOOKS_FUNCTION_DECL_DELETED_P): Likewise. (LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Set default. (LANG_HOOKS_DECLS): Add it. * langhooks.h (struct lang_hooks_for_decls): Add function_decl_defaulted. Const_tree-ify function_decl_explicit_p and function_decl_deleted_p. * dwarf2out.c (gen_subprogram_die): Add DW_AT_defaulted attribute. Add DW_AT_deleted instead of DW_AT_GNU_deleted, also at strict DWARF v5. for gcc/cp/ChangeLog PR debug/63240 * cp-objcp-common.c (cp_function_decl_defaulted): New. (cp_function_decl_explicit_p): Const_tree-ify. (cp_function_decl_deleted_p): Likewise. * cp-objcp-common.h (cp_function_decl_defaulted): Declare. (cp_function_decl_explicit_p): Const_tree-ify. (cp_function_decl_deleted_p): Likewise. (LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Redefine. for gcc/testsuite/ChangeLog PR debug/63240 * g++.dg/debug/dwarf2/defaulted-member-function-1.C: New. * g++.dg/debug/dwarf2/defaulted-member-function-2.C: New. * g++.dg/debug/dwarf2/defaulted-member-function-3.C: New. * g++.dg/debug/dwarf2/deleted-member-function.C: Expect DW_AT_deleted. From-SVN: r239403 --- gcc/ChangeLog | 13 +++++ gcc/cp/ChangeLog | 11 +++++ gcc/cp/cp-objcp-common.c | 25 +++++++++- gcc/cp/cp-objcp-common.h | 7 ++- gcc/dwarf2out.c | 49 +++++++++++++++++-- gcc/langhooks-def.h | 6 ++- gcc/langhooks.h | 9 +++- gcc/testsuite/ChangeLog | 7 +++ .../dwarf2/defaulted-member-function-1.C | 14 ++++++ .../dwarf2/defaulted-member-function-2.C | 16 ++++++ .../dwarf2/defaulted-member-function-3.C | 13 +++++ .../debug/dwarf2/deleted-member-function.C | 2 +- include/ChangeLog | 6 +++ include/dwarf2.def | 2 + include/dwarf2.h | 8 +++ 15 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 59e4fcf0eac..11d6e548dba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,18 @@ 2016-08-12 Alexandre Oliva + PR debug/63240 + * langhooks-def.h + (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P): Const_tree-ify. + (LANG_HOOKS_FUNCTION_DECL_DELETED_P): Likewise. + (LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Set default. + (LANG_HOOKS_DECLS): Add it. + * langhooks.h (struct lang_hooks_for_decls): Add + function_decl_defaulted. Const_tree-ify + function_decl_explicit_p and function_decl_deleted_p. + * dwarf2out.c (gen_subprogram_die): Add DW_AT_defaulted + attribute. Add DW_AT_deleted instead of DW_AT_GNU_deleted, + also at strict DWARF v5. + PR debug/55641 * dwarf2out.c (decl_quals): Don't map TREE_READONLY to TYPE_QUAL_CONST in reference-typed decls. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c0d24606085..4049c76bfeb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2016-08-12 Alexandre Oliva + + PR debug/63240 + * cp-objcp-common.c (cp_function_decl_defaulted): New. + (cp_function_decl_explicit_p): Const_tree-ify. + (cp_function_decl_deleted_p): Likewise. + * cp-objcp-common.h (cp_function_decl_defaulted): Declare. + (cp_function_decl_explicit_p): Const_tree-ify. + (cp_function_decl_deleted_p): Likewise. + (LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Redefine. + 2016-08-11 Jakub Jelinek PR c++/72868 diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index f7ddb00b02c..9cb9dd780fb 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -133,7 +133,7 @@ cxx_types_compatible_p (tree x, tree y) /* Return true if DECL is explicit member function. */ bool -cp_function_decl_explicit_p (tree decl) +cp_function_decl_explicit_p (const_tree decl) { return (decl && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl)) @@ -143,13 +143,34 @@ cp_function_decl_explicit_p (tree decl) /* Return true if DECL is deleted special member function. */ bool -cp_function_decl_deleted_p (tree decl) +cp_function_decl_deleted_p (const_tree decl) { return (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. */ + +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)) + return 1; + + if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl)) + return 2; + } + + return 0; +} + /* Stubs to keep c-opts.c happy. */ void push_file_scope (void) diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 1bb19ee04b9..3ad3eb64c0b 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -26,8 +26,9 @@ along with GCC; see the file COPYING3. If not see extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree, bool); -extern bool cp_function_decl_explicit_p (tree decl); -extern bool cp_function_decl_deleted_p (tree decl); +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 void cp_common_init_ts (void); /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks @@ -134,6 +135,8 @@ extern void cp_common_init_ts (void); #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_OMP_PREDETERMINED_SHARING #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 06dbadbd15f..3b25358459d 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -20477,6 +20477,24 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)), TYPE_UNQUALIFIED, false, context_die); } + + /* 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) + && !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 (); + } } } /* Create a fresh DIE for anything else. */ @@ -20524,10 +20542,35 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) add_AT_flag (subr_die, DW_AT_explicit, 1); /* If this is a C++11 deleted special function member then generate - a DW_AT_GNU_deleted attribute. */ + a DW_AT_deleted attribute. */ if (lang_hooks.decls.function_decl_deleted_p (decl) - && (! dwarf_strict)) - add_AT_flag (subr_die, DW_AT_GNU_deleted, 1); + && (dwarf_version >= 5 || ! dwarf_strict)) + 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 (); + } } } /* Tag abstract instances with DW_AT_inline. */ diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index c17f9984184..10d910c960d 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -209,8 +209,9 @@ extern tree lhd_make_node (enum tree_code); #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_tree_false -#define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_tree_false +#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_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 @@ -233,6 +234,7 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_GETDECLS, \ LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \ LANG_HOOKS_FUNCTION_DECL_DELETED_P, \ + LANG_HOOKS_FUNCTION_DECL_DEFAULTED, \ LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \ LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \ LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 169a6784b6a..44c258e9638 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -181,10 +181,15 @@ struct lang_hooks_for_decls tree (*getdecls) (void); /* Returns true if DECL is explicit member function. */ - bool (*function_decl_explicit_p) (tree); + bool (*function_decl_explicit_p) (const_tree); /* Returns true if DECL is C++11 deleted special member function. */ - bool (*function_decl_deleted_p) (tree); + 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 True if the parameter is a generic parameter decl of a generic type, e.g a template template parameter for the C++ FE. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1726157067e..b2d0e64ec58 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2016-08-12 Alexandre Oliva + PR debug/63240 + * g++.dg/debug/dwarf2/defaulted-member-function-1.C: New. + * g++.dg/debug/dwarf2/defaulted-member-function-2.C: New. + * g++.dg/debug/dwarf2/defaulted-member-function-3.C: New. + * g++.dg/debug/dwarf2/deleted-member-function.C: Expect + DW_AT_deleted. + PR debug/55641 * g++.dg/debug/dwarf2/ref-1.C: New. diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C new file mode 100644 index 00000000000..e798b490367 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" } +// { dg-final { scan-assembler-times "0x1\[ \t\]\[^\n\]* DW_AT_defaulted" 1 { xfail { powerpc-ibm-aix* } } } } + +struct Foo +{ + Foo () = default; +}; + +void +bar () +{ + Foo foo; +} diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C new file mode 100644 index 00000000000..5b569494952 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C @@ -0,0 +1,16 @@ +// { dg-do compile } +// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" } +// { dg-final { scan-assembler-times "0x2\[ \t\]\[^\n\]* DW_AT_defaulted" 1 { xfail { powerpc-ibm-aix* } } } } + +struct Foo +{ + Foo (); +}; + +Foo::Foo () = default; + +void +bar () +{ + Foo foo; +} diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C new file mode 100644 index 00000000000..190fe50845d --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" } +// { dg-final { scan-assembler-not " DW_AT_defaulted" { xfail { powerpc-ibm-aix* } } } } + +struct Foo +{ +}; + +void +bar () +{ + Foo foo; +} diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C b/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C index c0c36a97775..7f42719d669 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C @@ -1,6 +1,6 @@ // { dg-do compile } // { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" } -// { dg-final { scan-assembler-times " DW_AT_GNU_deleted" 2 { xfail { powerpc-ibm-aix* } } } } +// { dg-final { scan-assembler-times " DW_AT_deleted" 2 { xfail { powerpc-ibm-aix* } } } } struct Foo { diff --git a/include/ChangeLog b/include/ChangeLog index 06be0281e26..5a3843bde1c 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2016-08-12 Alexandre Oliva + + PR debug/63240 + * dwarf2.def (DW_AT_deleted, DW_AT_defaulted): New. + * dwarf2.h (enu dwarf_defaulted_attribute): New. + 2016-07-29 Aldy Hernandez * libiberty.h (MAX_ALLOCA_SIZE): New macro. diff --git a/include/dwarf2.def b/include/dwarf2.def index 2dfee5666de..67b2a5bd39d 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -310,6 +310,8 @@ DW_AT (DW_AT_enum_class, 0x6d) DW_AT (DW_AT_linkage_name, 0x6e) /* DWARF 5. */ DW_AT (DW_AT_noreturn, 0x87) +DW_AT (DW_AT_deleted, 0x8a) +DW_AT (DW_AT_defaulted, 0x8b) DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start. */ DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end. */ diff --git a/include/dwarf2.h b/include/dwarf2.h index 1a145aa48f7..d166a965db5 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -342,6 +342,14 @@ enum dwarf_macinfo_record_type DW_MACINFO_vendor_ext = 255 }; +/* DW_TAG_GNU_defaulted/DW_TAG_defaulted attributes. */ +enum dwarf_defaulted_attribute + { + DW_DEFAULTED_no = 0x00, + DW_DEFAULTED_in_class = 0x01, + DW_DEFAULTED_out_of_class = 0x02 + }; + /* Names and codes for new style macro information. */ enum dwarf_macro_record_type {