From 71fa02e0d8932de4ba1a527f50df98bf211f2ffd Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 2 Jun 2015 12:33:02 +0000 Subject: [PATCH] re PR debug/65549 (crash in htab_hash_string with -flto -g) 2015-06-02 Richard Biener PR debug/65549 * dwarf2out.c (lookup_context_die): New function. (resolve_addr): Avoid forcing a full DIE for the target of a DW_TAG_GNU_call_site during late compilation. Instead create a stub DIE without a type if we have a context DIE present. * g++.dg/lto/pr65549_0.C: New testcase. From-SVN: r224029 --- gcc/ChangeLog | 9 ++ gcc/dwarf2out.c | 38 ++++++- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/lto/pr65549_0.C | 144 +++++++++++++++++++++++++++ 4 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lto/pr65549_0.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f09b8ee4ae8..e22dbb9481e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-06-02 Richard Biener + + PR debug/65549 + * dwarf2out.c (lookup_context_die): New function. + (resolve_addr): Avoid forcing a full DIE for the + target of a DW_TAG_GNU_call_site during late compilation. + Instead create a stub DIE without a type if we have a + context DIE present. + 2015-06-02 Uros Bizjak * df-scan.c (df_scan_start_dump): Add space between regno and regname. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 15c545e8e74..1116f86a137 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -20621,6 +20621,28 @@ is_naming_typedef_decl (const_tree decl) != TYPE_NAME (TREE_TYPE (decl)))); } +/* Looks up the DIE for a context. */ + +static inline dw_die_ref +lookup_context_die (tree context) +{ + if (context) + { + /* Find die that represents this context. */ + if (TYPE_P (context)) + { + context = TYPE_MAIN_VARIANT (context); + dw_die_ref ctx = lookup_type_die (context); + if (!ctx) + return NULL; + return strip_naming_typedef (context, ctx); + } + else + return lookup_decl_die (context); + } + return comp_unit_die (); +} + /* Returns the DIE for a context. */ static inline dw_die_ref @@ -23949,12 +23971,22 @@ resolve_addr (dw_die_ref die) { tree tdecl = SYMBOL_REF_DECL (a->dw_attr_val.v.val_addr); dw_die_ref tdie = lookup_decl_die (tdecl); + dw_die_ref cdie; if (tdie == NULL && DECL_EXTERNAL (tdecl) - && DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE) + && DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE + && (cdie = lookup_context_die (DECL_CONTEXT (tdecl)))) { - force_decl_die (tdecl); - tdie = lookup_decl_die (tdecl); + /* Creating a full DIE for tdecl is overly expensive and + at this point even wrong when in the LTO phase + as it can end up generating new type DIEs we didn't + output and thus optimize_external_refs will crash. */ + tdie = new_die (DW_TAG_subprogram, cdie, NULL_TREE); + add_AT_flag (tdie, DW_AT_external, 1); + add_AT_flag (tdie, DW_AT_declaration, 1); + add_linkage_attr (tdie, tdecl); + add_name_and_src_coords_attributes (tdie, tdecl); + equate_decl_number_to_die (tdecl, tdie); } if (tdie) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3f51b10ec95..4dd3014c91e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-06-02 Richard Biener + + PR debug/65549 + * g++.dg/lto/pr65549_0.C: New testcase. + 2015-06-02 Thomas Schwinge PR libgomp/65742 diff --git a/gcc/testsuite/g++.dg/lto/pr65549_0.C b/gcc/testsuite/g++.dg/lto/pr65549_0.C new file mode 100644 index 00000000000..4c6358dc7b9 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr65549_0.C @@ -0,0 +1,144 @@ +// { dg-lto-do link } +// { dg-lto-options { { -std=gnu++14 -flto -g } { -std=gnu++14 -flto -g -O2 -fno-inline -flto-partition=max } } } +// { dg-extra-ld-options "-r -nostdlib" } + +namespace std { +inline namespace __cxx11 {} +template struct integral_constant { + static constexpr _Tp value = 0; +}; +template struct __and_; +struct is_member_object_pointer : integral_constant {}; +template +struct is_member_function_pointer : integral_constant {}; +template struct remove_reference { typedef int type; }; +template class C; +template struct __result_of_impl; +template +struct __result_of_impl { + typedef decltype(0) type; +}; +template +struct C<_Functor(_ArgTypes...)> + : __result_of_impl::type>::value, + _Functor> {}; +template using result_of_t = typename C<_Tp>::type; +template void forward(); +template _Tp move(_Tp) {} +namespace __cxx11 { +class basic_string typedef string; +} +template struct allocator_traits { typedef decltype(0) pointer; }; +} +struct F : std::allocator_traits {}; +namespace std { +namespace __cxx11 { +class basic_string { +public: + struct _Alloc_hider : F { + _Alloc_hider(pointer); + } _M_dataplus; + basic_string(int) : _M_dataplus(0) {} + ~basic_string(); +}; +} +template class function; +template class _Base_manager { +protected: + static _Functor *_M_get_pointer(int) {} +}; +template class _Function_handler; +template +class _Function_handler<_Res(_ArgTypes...), _Functor> + : _Base_manager<_Functor> { +public: + static _Res _M_invoke(const int &) { + (*_Base_manager<_Functor>::_M_get_pointer(0))(); + } +}; +template using __check_func_return_type = int; +template +class function<_Res(_ArgTypes...)> { + template using _Invoke = decltype(0); + template + using _Callable = __and_<__check_func_return_type<_Invoke<_Functor>, _Res>>; + template using _Requires = int; + +public: + template , void>> + function(_Functor); + using _Invoker_type = _Res (*)(const int &); + _Invoker_type _M_invoker; +}; +template +template +function<_Res(_ArgTypes...)>::function(_Functor) { + _M_invoker = _Function_handler<_Res(), _Functor>::_M_invoke; +} +class unique_ptr { +public: + ~unique_ptr(); +}; +template _Tp make_unique(_Args... __args) { + _Tp(__args...); +} +} +class A { +public: + template T as(); +}; +class variables_map { +public: + A operator[](std::basic_string); +}; +class B { +public: + variables_map configuration(); + void run(int, int, std::function); +}; +class H; +struct G { + enum {} _state; +}; +class D { + G _local_state; + std::unique_ptr _task; + template void schedule(Func func) { + struct task_with_state { + task_with_state(Func func) : _func(func) {} + Func _func; + } tws = std::make_unique(std::move(func)); + } + friend H; +}; +template using futurize_t = H; +class H { + D *_promise; + template void schedule(Func func) { + G __trans_tmp_1; + struct task_with_ready_state { + task_with_ready_state(Func, G); + }; + std::make_unique(std::move(func), __trans_tmp_1); + _promise->schedule(std::move(func)); + } + template void then(Func func, Param) { + using P = D; + P pr; + schedule([ pr = std::move(pr), func, param = std::forward ]{}); + } + +public: + template futurize_t> then(Func) { + then(0, [] {}); + } +} clients; +main() { + B app; + app.run(0, 0, [&] { + auto config = app.configuration()[0].as(); + clients.then([] {}); + }); +} -- 2.30.2