re PR debug/65549 (crash in htab_hash_string with -flto -g)
authorRichard Biener <rguenther@suse.de>
Tue, 2 Jun 2015 12:33:02 +0000 (12:33 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 2 Jun 2015 12:33:02 +0000 (12:33 +0000)
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.

* g++.dg/lto/pr65549_0.C: New testcase.

From-SVN: r224029

gcc/ChangeLog
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lto/pr65549_0.C [new file with mode: 0644]

index f09b8ee4ae8d4dc1f89f917a3893b32d4441fdd1..e22dbb9481e756fd5504f43ca972958cda2b74a7 100644 (file)
@@ -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.
index 15c545e8e7416d6cd370b4668a34a5d5b2f5f833..1116f86a13701f6a195808a95b3a923b3c6a89e2 100644 (file)
@@ -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)
              {
index 3f51b10ec95e70a61fc74b03e16153e1a6cdd903..4dd3014c91e61d4e2b28905aec8a6e76623a15b8 100644 (file)
@@ -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 (file)
index 0000000..4c6358d
--- /dev/null
@@ -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([] {});
+  });
+}