+2018-09-27 Richard Biener <rguenther@suse.de>
+
+ PR debug/37801
+ PR debug/87440
+ * dwarf2out.c (set_block_origin_self): Do not mark outermost
+ block as we do not output that.
+ (gen_inlined_subroutine_die): Elide the originally outermost
+ block, matching what we do for concrete instances.
+ (decls_for_scope): Add parameter specifying whether to recurse
+ to subblocks.
+
2018-09-27 Andrew Stubbs <ams@codesourcery.com>
Tom de Vries <tom@codesourcery.com>
static void gen_typedef_die (tree, dw_die_ref);
static void gen_type_die (tree, dw_die_ref);
static void gen_block_die (tree, dw_die_ref);
-static void decls_for_scope (tree, dw_die_ref);
+static void decls_for_scope (tree, dw_die_ref, bool = true);
static bool is_naming_typedef_decl (const_tree);
static inline dw_die_ref get_context_die (tree);
static void gen_namespace_die (tree, dw_die_ref);
add_high_low_attributes (stmt, subr_die);
add_call_src_coords_attributes (stmt, subr_die);
- decls_for_scope (stmt, subr_die);
+ /* The inliner creates an extra BLOCK for the parameter setup,
+ we want to merge that with the actual outermost BLOCK of the
+ inlined function to avoid duplicate locals in consumers.
+ Do that by doing the recursion to subblocks on the single subblock
+ of STMT. */
+ bool unwrap_one = false;
+ if (BLOCK_SUBBLOCKS (stmt) && !BLOCK_CHAIN (BLOCK_SUBBLOCKS (stmt)))
+ {
+ tree origin = block_ultimate_origin (BLOCK_SUBBLOCKS (stmt));
+ if (origin
+ && TREE_CODE (origin) == BLOCK
+ && BLOCK_SUPERCONTEXT (origin) == decl)
+ unwrap_one = true;
+ }
+ decls_for_scope (stmt, subr_die, !unwrap_one);
+ if (unwrap_one)
+ decls_for_scope (BLOCK_SUBBLOCKS (stmt), subr_die);
}
}
all of its sub-blocks. */
static void
-decls_for_scope (tree stmt, dw_die_ref context_die)
+decls_for_scope (tree stmt, dw_die_ref context_die, bool recurse)
{
tree decl;
unsigned int i;
/* Output the DIEs to represent all sub-blocks (and the items declared
therein) of this block. */
- for (subblocks = BLOCK_SUBBLOCKS (stmt);
- subblocks != NULL;
- subblocks = BLOCK_CHAIN (subblocks))
- gen_block_die (subblocks, context_die);
+ if (recurse)
+ for (subblocks = BLOCK_SUBBLOCKS (stmt);
+ subblocks != NULL;
+ subblocks = BLOCK_CHAIN (subblocks))
+ gen_block_die (subblocks, context_die);
}
/* Is this a typedef we can avoid emitting? */
of third, second and first. */
/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_inlined_subroutine" 6 } } */
-/* Likewise we should have 6 DW_TAG_lexical_block DIEs:
- - One for each subroutine inlined into main, so that's 3.
- - One for each subroutine inlined in the out of line instances
- of third, second and first, that's 3.
-*/
-/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_lexical_block" 6 } } */
+/* We should have no DW_TAG_lexical_block DIEs, all inline instances
+ should have the first subblock elided to match the abstract instance
+ layout. */
+/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_lexical_block" 0 } } */
/* There are 3 DW_AT_inline attributes: one per abstract inline instance.
--- /dev/null
+/* Verify that the inline instance has no extra DW_TAG_lexical_block between
+ the DW_TAG_inlined_subroutine and the DW_TAG_variable for the local. */
+/* { dg-options "-O -gdwarf -dA" } */
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "DW_TAG_inlined_subroutine\[^\\(\]*\\(\[^\\)\]*\\)\[^\\(\]*\\(DIE \\(0x\[0-9a-f\]*\\) DW_TAG_formal_parameter\[^\\(\]*\\(DIE \\(0x\[0-9a-f\]*\\) DW_TAG_variable" } } */
+/* { dg-final { scan-assembler-times "DW_TAG_inlined_subroutine" 2 } } */
+
+static int foo (int i)
+{
+ volatile int j = i + 3;
+ return j - 2;
+}
+int main()
+{
+ volatile int z = foo (-1);
+ return z;
+}