diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c | 65 |
4 files changed, 88 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 687ab97..fb9b6a7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-05-10 Pierre-Marie de Rodat <derodat@adacore.com> + + * dwarf2out.c (add_abstract_origin_attribute): Adjust + documentation comment. For BLOCK nodes, add a + DW_AT_abstract_origin attribute that points to the DIE generated + for the origin BLOCK. + (gen_lexical_block_die): Call add_abstract_origin_attribute for + blocks from inlined functions. + 2016-05-10 Alan Modra <amodra@gmail.com> PR target/70947 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index fb3f7b9..da95e19 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -18621,15 +18621,16 @@ add_prototyped_attribute (dw_die_ref die, tree func_type) } /* Add an 'abstract_origin' attribute below a given DIE. The DIE is found - by looking in either the type declaration or object declaration - equate table. */ + by looking in the type declaration, the object declaration equate table or + the block mapping. */ static inline dw_die_ref add_abstract_origin_attribute (dw_die_ref die, tree origin) { dw_die_ref origin_die = NULL; - if (TREE_CODE (origin) != FUNCTION_DECL) + if (TREE_CODE (origin) != FUNCTION_DECL + && TREE_CODE (origin) != BLOCK) { /* We may have gotten separated from the block for the inlined function, if we're in an exception handler or some such; make @@ -18651,6 +18652,8 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin) origin_die = lookup_decl_die (origin); else if (TYPE_P (origin)) origin_die = lookup_type_die (origin); + else if (TREE_CODE (origin) == BLOCK) + origin_die = BLOCK_DIE (origin); /* XXX: Functions that are never lowered don't always have correct block trees (in the case of java, they simply have no block tree, in some other @@ -21467,6 +21470,10 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die) BLOCK_DIE (stmt) = stmt_die; old_die = NULL; } + + tree origin = block_ultimate_origin (stmt); + if (origin != NULL_TREE && origin != stmt) + add_abstract_origin_attribute (stmt_die, origin); } if (old_die) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 29a9709..f144648 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-05-10 Pierre-Marie de Rodat <derodat@adacore.com> + + * gcc.dg/debug/dwarf2/nested_fun.c: New testcase. + 2016-05-09 Uros Bizjak <ubizjak@gmail.com> * gcc.target/i386/fabsneg-1.c New test. diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c b/gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c new file mode 100644 index 0000000..c783ac0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/nested_fun.c @@ -0,0 +1,65 @@ +/* As part of inlining, a BLOCK (described as DW_TAG_lexical_block DIE's) may + be present both as an abstract instance and a concrete one in the DWARF + output. This testcase attempts to make sure that the concrete ones refer to + the abstract ones thanks to the DW_AT_abstract_origin attribute. + + Such a back-link enables debuggers to make entities present in the abstract + instance only available in concrete ones. */ + +/* { dg-options "-O2 -g -std=gnu99 -gdwarf -dA" } */ +/* { dg-final { scan-assembler-times "\\(DIE \\(0x.*\\) DW_TAG_lexical_block\\)\[^)\]*DW_AT_abstract_origin" 1 } } */ + +extern void *create (const char *); +extern void destroy (void *); +extern void do_nothing (char); + +struct string +{ + const char *data; + int lb; + int ub; +}; + +int +main (void) +{ + void *o1 = create ("foo"); + + void + parent (void) + { + { + void *o2 = create ("bar"); + + int + child (struct string s) + { + int i = s.lb; + + if (s.lb <= s.ub) + while (1) + { + char c = s.data[i - s.lb]; + do_nothing (c); + if (c == 'o') + return 1; + if (i == s.ub) + break; + ++i; + } + return 0; + } + + int r; + + r = child ((struct string) {"baz", 1, 3}); + r = child ((struct string) {"qux", 2, 4}); + r = child ((struct string) {"foobar", 1, 6}); + } + + do_nothing (0); + } + + parent (); + return 0; +} |