diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lto/pr65549_0.C | 144 |
4 files changed, 193 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f09b8ee..e22dbb9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-06-02 Richard Biener <rguenther@suse.de> + + 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 <ubizjak@gmail.com> * df-scan.c (df_scan_start_dump): Add space between regno and regname. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 15c545e..1116f86 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 3f51b10..4dd3014 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-06-02 Richard Biener <rguenther@suse.de> + + PR debug/65549 + * g++.dg/lto/pr65549_0.C: New testcase. + 2015-06-02 Thomas Schwinge <thomas@codesourcery.com> 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 0000000..4c6358d --- /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 <typename _Tp, _Tp> struct integral_constant { + static constexpr _Tp value = 0; +}; +template <typename> struct __and_; +struct is_member_object_pointer : integral_constant<bool, false> {}; +template <typename> +struct is_member_function_pointer : integral_constant<bool, false> {}; +template <typename> struct remove_reference { typedef int type; }; +template <typename> class C; +template <bool, int, typename...> struct __result_of_impl; +template <typename _Functor, typename... _ArgTypes> +struct __result_of_impl<false, 0, _Functor, _ArgTypes...> { + typedef decltype(0) type; +}; +template <typename _Functor, typename... _ArgTypes> +struct C<_Functor(_ArgTypes...)> + : __result_of_impl<is_member_object_pointer::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type>::value, + _Functor> {}; +template <typename _Tp> using result_of_t = typename C<_Tp>::type; +template <typename> void forward(); +template <typename _Tp> _Tp move(_Tp) {} +namespace __cxx11 { +class basic_string typedef string; +} +template <typename> struct allocator_traits { typedef decltype(0) pointer; }; +} +struct F : std::allocator_traits<int> {}; +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 <typename> class function; +template <typename _Functor> class _Base_manager { +protected: + static _Functor *_M_get_pointer(int) {} +}; +template <typename, typename> class _Function_handler; +template <typename _Res, typename _Functor, typename... _ArgTypes> +class _Function_handler<_Res(_ArgTypes...), _Functor> + : _Base_manager<_Functor> { +public: + static _Res _M_invoke(const int &) { + (*_Base_manager<_Functor>::_M_get_pointer(0))(); + } +}; +template <typename, typename> using __check_func_return_type = int; +template <typename _Res, typename... _ArgTypes> +class function<_Res(_ArgTypes...)> { + template <typename> using _Invoke = decltype(0); + template <typename _Functor> + using _Callable = __and_<__check_func_return_type<_Invoke<_Functor>, _Res>>; + template <typename, typename> using _Requires = int; + +public: + template <typename _Functor, typename = _Requires<_Callable<_Functor>, void>> + function(_Functor); + using _Invoker_type = _Res (*)(const int &); + _Invoker_type _M_invoker; +}; +template <typename _Res, typename... _ArgTypes> +template <typename _Functor, typename> +function<_Res(_ArgTypes...)>::function(_Functor) { + _M_invoker = _Function_handler<_Res(), _Functor>::_M_invoke; +} +class unique_ptr { +public: + ~unique_ptr(); +}; +template <typename _Tp, typename... _Args> _Tp make_unique(_Args... __args) { + _Tp(__args...); +} +} +class A { +public: + template <class T> T as(); +}; +class variables_map { +public: + A operator[](std::basic_string); +}; +class B { +public: + variables_map configuration(); + void run(int, int, std::function<void()>); +}; +class H; +struct G { + enum {} _state; +}; +class D { + G _local_state; + std::unique_ptr _task; + template <typename Func> void schedule(Func func) { + struct task_with_state { + task_with_state(Func func) : _func(func) {} + Func _func; + } tws = std::make_unique<task_with_state>(std::move(func)); + } + friend H; +}; +template <typename> using futurize_t = H; +class H { + D *_promise; + template <typename Func> void schedule(Func func) { + G __trans_tmp_1; + struct task_with_ready_state { + task_with_ready_state(Func, G); + }; + std::make_unique<task_with_ready_state>(std::move(func), __trans_tmp_1); + _promise->schedule(std::move(func)); + } + template <typename Func, typename Param> void then(Func func, Param) { + using P = D; + P pr; + schedule([ pr = std::move(pr), func, param = std::forward<Param> ]{}); + } + +public: + template <typename Func> futurize_t<std::result_of_t<Func()>> then(Func) { + then(0, [] {}); + } +} clients; +main() { + B app; + app.run(0, 0, [&] { + auto config = app.configuration()[0].as<std::string>(); + clients.then([] {}); + }); +} |