aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPierre-Marie de Rodat <derodat@adacore.com>2017-09-25 12:26:36 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2017-09-25 12:26:36 +0000
commit504e0b5f2c7128a89f869ca984949d063bab52c4 (patch)
tree1835ef494a1d2796ab0739ed02b9dfc3d0206767 /gcc
parentd362ac6c6d5a9419d9b7a0db84155a065e113434 (diff)
downloadgcc-504e0b5f2c7128a89f869ca984949d063bab52c4.zip
gcc-504e0b5f2c7128a89f869ca984949d063bab52c4.tar.gz
gcc-504e0b5f2c7128a89f869ca984949d063bab52c4.tar.bz2
[PR82155] Fix crash in dwarf2out_abstract_function
This patch is an attempt to fix the crash reported in PR82155. When generating a C++ class method for a class that is itself nested in a class method, dwarf2out_early_global_decl currently leaves the existing context DIE as it is if it already exists. However, it is possible that this call happens at a point where this context DIE is just a declaration that is itself not located in its own context. From there, if dwarf2out_early_global_decl is not called on any of the FUNCTION_DECL in the context chain, DIEs will be left badly scoped and some (such as the nested method) will be removed by the type pruning machinery. As a consequence, dwarf2out_abstract_function will will crash when called on the corresponding DECL because it asserts that the DECL has a DIE. This patch fixes this crash making dwarf2out_early_global_decl process context DIEs the same way we process abstract origins for FUNCTION_DECL: if the corresponding DIE exists but is only a declaration, call dwarf2out_decl anyway on it so that it is turned into a more complete DIE and so that it is relocated in the proper context. Bootstrapped and regtested on x86_64-linux. gcc/ PR debug/82155 * dwarf2out.c (dwarf2out_early_global_decl): Call dwarf2out_decl on the FUNCTION_DECL function context if it has a DIE that is a declaration. gcc/testsuite/ * g++.dg/pr82155.C: New testcase. From-SVN: r253147
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/dwarf2out.c10
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/pr82155.C36
4 files changed, 55 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f618113..b3dadab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2017-09-25 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ PR debug/82155
+ * dwarf2out.c (dwarf2out_early_global_decl): Call dwarf2out_decl
+ on the FUNCTION_DECL function context if it has a DIE that is a
+ declaration.
+
2017-09-25 Richard Biener <rguenther@suse.de>
PR tree-optimization/82285
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index dda569f..e97ceb6 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -25490,10 +25490,16 @@ dwarf2out_early_global_decl (tree decl)
so that all nested DIEs are generated at the proper scope in the
first shot. */
tree context = decl_function_context (decl);
- if (context != NULL && lookup_decl_die (context) == NULL)
+ if (context != NULL)
{
+ dw_die_ref context_die = lookup_decl_die (context);
current_function_decl = context;
- dwarf2out_decl (context);
+
+ /* Avoid emitting DIEs multiple times, but still process CONTEXT
+ enough so that it lands in its own context. This avoids type
+ pruning issues later on. */
+ if (context_die == NULL || is_declaration_die (context_die))
+ dwarf2out_decl (context);
}
/* Emit an abstract origin of a function first. This happens
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 333e2c8..8cdcbc6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-09-25 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ * g++.dg/pr82155.C: New testcase.
+
2017-09-25 Richard Biener <rguenther@suse.de>
PR tree-optimization/82285
diff --git a/gcc/testsuite/g++.dg/pr82155.C b/gcc/testsuite/g++.dg/pr82155.C
new file mode 100644
index 0000000..75d9b61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr82155.C
@@ -0,0 +1,36 @@
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-g -O2" } */
+
+template <typename a> struct b { a c; };
+template <typename d> struct e { d *operator->(); };
+template <typename d> class h {
+public:
+ typedef e<d> ag;
+};
+class i {
+protected:
+ i(int);
+};
+class j {
+ virtual void k(int) = 0;
+
+public:
+ int f;
+ void l() { k(f); }
+};
+struct m : i {
+ int cn;
+ m() : i(cn) {
+ struct n : j {
+ n() {}
+ void k(int) {}
+ };
+ }
+};
+struct o {
+ o() {
+ for (h<b<b<j *>>>::ag g;;)
+ g->c.c->l();
+ }
+};
+void fn1() { o(); }