jarin created this revision.
jarin added a reviewer: labath.
jarin added a project: LLDB.
Herald added a subscriber: JDevlieghere.
jarin requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added subscribers: lldb-commits, sstefan1.

This change fixes a problem introduced by clang change
described by https://reviews.llvm.org/D95617 and described by
https://bugs.llvm.org/show_bug.cgi?id=50076#c6, where inlined
functions omit the unused parameters both in the stack trace
and in `frame var` command. With this change, the parameters
are listed correctly in the stack trace and in `frame var`
command (the included test tests `frame var`).

This change adds parsing of formal parameters from the abstract
version of inlined functions and use those formal parameters if
they are missing from the concrete version.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D110571

Files:
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  lldb/test/Shell/SymbolFile/DWARF/x86/Inputs/unused-inlined-params.s
  lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test

Index: lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
@@ -0,0 +1,34 @@
+# UNSUPPORTED: system-darwin, system-windows
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -filetype=obj %S/Inputs/unused-inlined-params.s \
+# RUN:         -triple x86_64-pc-linux -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: %lldb %t -s %s -o exit | FileCheck %s
+
+breakpoint set -n f
+process launch
+
+# CHECK: Process {{.*}} stopped
+
+# Let us check that unused parameters (of an inlined function) are listed.
+frame variable
+# CHECK-LABEL: frame variable
+# CHECK: (void *) unused1 = <
+# CHECK: (int) used = 42
+# CHECK: (int) unused2 = <
+# CHECK: (int) partial = 1
+# CHECK: (int) unused3 = <
+
+# Step out of the live range of the 'partial' parameter.
+next
+next
+# Check the variable contents.
+frame variable
+# CHECK-LABEL: frame variable
+# CHECK: (void *) unused1 = <
+# CHECK: (int) used = 43
+# CHECK: (int) unused2 = <
+# CHECK: (int) partial = <
+# CHECK: (int) unused3 = <
Index: lldb/test/Shell/SymbolFile/DWARF/x86/Inputs/unused-inlined-params.s
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/DWARF/x86/Inputs/unused-inlined-params.s
@@ -0,0 +1,423 @@
+# Generated from the following program (with some pruning):
+#
+# 1   #include <stdio.h>
+# 2
+# 3   __attribute__((always_inline))
+# 4   void f(void* unused1, int used, int unused2, int partial, int unused3) {
+# 5     used += partial;
+# 6     printf("%i", partial);
+# 7     printf("%i", used);
+# 8   }
+# 9
+# 10  int main(int argc, char** argv) {
+# 11    f(argv, 42, 1, argc, 2);
+# 12    return 0;
+# 13  }
+	.text
+	.file	"unused-inlined-params.c"
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@function
+main:                                   # @main
+.Lfunc_begin1:
+	.file	1 "/example" "unused-inlined-params.c"
+	.loc	1 10 0                          # unused-inlined-params.c:10:0
+	.cfi_startproc
+# %bb.0:
+	#DEBUG_VALUE: main:argc <- $edi
+	#DEBUG_VALUE: main:argv <- $rsi
+	#DEBUG_VALUE: f:partial <- $edi
+	pushq	%rbx
+	.cfi_def_cfa_offset 16
+	.cfi_offset %rbx, -16
+	movl	%edi, %esi
+.Lline5:
+	#DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi
+	#DEBUG_VALUE: f:unused3 <- undef
+	#DEBUG_VALUE: f:unused2 <- undef
+	#DEBUG_VALUE: f:used <- 42
+	#DEBUG_VALUE: f:unused1 <- undef
+	#DEBUG_VALUE: f:partial <- $esi
+	#DEBUG_VALUE: main:argc <- $esi
+	.loc	1 5 8 prologue_end              # unused-inlined-params.c:5:8
+	leal	42(%rsi), %ebx
+.Lline6:
+	#DEBUG_VALUE: f:used <- $ebx
+	.loc	1 6 3                           # unused-inlined-params.c:6:3
+	movl	$.L.str, %edi
+                                        # kill: def $esi killed $esi killed $rsi
+	xorl	%eax, %eax
+	callq	printf
+.Lline7:
+	.loc	1 7 3                           # unused-inlined-params.c:7:3
+	movl	$.L.str, %edi
+	movl	%ebx, %esi
+	xorl	%eax, %eax
+	callq	printf
+.Lline12:
+	.loc	1 12 3                          # unused-inlined-params.c:12:3
+	xorl	%eax, %eax
+	popq	%rbx
+.Lreturn1:
+	.cfi_def_cfa_offset 8
+	retq
+.Lfunc_end1:
+	.size	main, .Lfunc_end1-main
+	.cfi_endproc
+                                                # -- End function
+# Dummy printf implementation.
+printf:
+        retq
+
+# Simple implementation of _start - set up argc, argv and tail-call main.
+	.globl	_start
+	.p2align	4, 0x90
+	.type	_start,@function
+_start:
+        movl    (%rsp), %edi
+        leaq    4(%rsp), %rsi
+        jmp     main
+
+	.type	.L.str,@object                  # @.str
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.L.str:
+	.asciz	"%i"
+	.size	.L.str, 3
+
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc_argc:
+	.quad	.Lfunc_begin1-.Lfunc_begin1
+	.quad	.Lline5-.Lfunc_begin1
+	.short	1                               # Loc expr size
+	.byte	85                              # super-register DW_OP_reg5
+	.quad	.Lline5-.Lfunc_begin1
+	.quad	.Lline7-.Lfunc_begin1
+	.short	1                               # Loc expr size
+	.byte	84                              # super-register DW_OP_reg4
+	.quad	0
+	.quad	0
+.Ldebug_loc3:
+	.quad	.Lfunc_begin1-.Lfunc_begin1
+	.quad	.Lline5-.Lfunc_begin1
+	.short	1                               # Loc expr size
+	.byte	84                              # DW_OP_reg4
+	.quad	.Lline5-.Lfunc_begin1
+	.quad	.Lfunc_end1-.Lfunc_begin1
+	.short	4                               # Loc expr size
+	.byte	243                             # DW_OP_GNU_entry_value
+	.byte	1                               # 1
+	.byte	84                              # DW_OP_reg4
+	.byte	159                             # DW_OP_stack_value
+	.quad	0
+	.quad	0
+.Ldebug_loc4:
+	.quad	.Lfunc_begin1-.Lfunc_begin1
+	.quad	.Lline5-.Lfunc_begin1
+	.short	1                               # Loc expr size
+	.byte	85                              # super-register DW_OP_reg5
+	.quad	.Lline5-.Lfunc_begin1
+	.quad	.Lline7-.Lfunc_begin1
+	.short	1                               # Loc expr size
+	.byte	84                              # super-register DW_OP_reg4
+	.quad	0
+	.quad	0
+.Ldebug_loc5:
+	.quad	.Lline5-.Lfunc_begin1
+	.quad	.Lline6-.Lfunc_begin1
+	.short	3                               # Loc expr size
+	.byte	17                              # DW_OP_consts
+	.byte	42                              # 42
+	.byte	159                             # DW_OP_stack_value
+	.quad	.Lline6-.Lfunc_begin1
+	.quad	.Lreturn1-.Lfunc_begin1
+	.short	1                               # Loc expr size
+	.byte	83                              # super-register DW_OP_reg3
+	.quad	0
+	.quad	0
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                               # Abbreviation Code
+	.byte	17                              # DW_TAG_compile_unit
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	19                              # DW_AT_language
+	.byte	5                               # DW_FORM_data2
+	.byte	3                               # DW_AT_name
+	.byte	14                              # DW_FORM_strp
+	.byte	16                              # DW_AT_stmt_list
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	27                              # DW_AT_comp_dir
+	.byte	14                              # DW_FORM_strp
+	.byte	17                              # DW_AT_low_pc
+	.byte	1                               # DW_FORM_addr
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	4                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	5                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	3                               # DW_AT_name
+	.byte	14                              # DW_FORM_strp
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	39                              # DW_AT_prototyped
+	.byte	25                              # DW_FORM_flag_present
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	32                              # DW_AT_inline
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	6                               # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	14                              # DW_FORM_strp
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	7                               # Abbreviation Code
+	.byte	15                              # DW_TAG_pointer_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	8                               # Abbreviation Code
+	.byte	36                              # DW_TAG_base_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	3                               # DW_AT_name
+	.byte	14                              # DW_FORM_strp
+	.byte	62                              # DW_AT_encoding
+	.byte	11                              # DW_FORM_data1
+	.byte	11                              # DW_AT_byte_size
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	9                               # Abbreviation Code
+	.byte	46                              # DW_TAG_subprogram
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	17                              # DW_AT_low_pc
+	.byte	1                               # DW_FORM_addr
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	64                              # DW_AT_frame_base
+	.byte	24                              # DW_FORM_exprloc
+	.ascii	"\227B"                         # DW_AT_GNU_all_call_sites
+	.byte	25                              # DW_FORM_flag_present
+	.byte	3                               # DW_AT_name
+	.byte	14                              # DW_FORM_strp
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	39                              # DW_AT_prototyped
+	.byte	25                              # DW_FORM_flag_present
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	63                              # DW_AT_external
+	.byte	25                              # DW_FORM_flag_present
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	10                              # Abbreviation Code
+	.byte	5                               # DW_TAG_formal_parameter
+	.byte	0                               # DW_CHILDREN_no
+	.byte	2                               # DW_AT_location
+	.byte	23                              # DW_FORM_sec_offset
+	.byte	3                               # DW_AT_name
+	.byte	14                              # DW_FORM_strp
+	.byte	58                              # DW_AT_decl_file
+	.byte	11                              # DW_FORM_data1
+	.byte	59                              # DW_AT_decl_line
+	.byte	11                              # DW_FORM_data1
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	11                              # Abbreviation Code
+	.byte	29                              # DW_TAG_inlined_subroutine
+	.byte	1                               # DW_CHILDREN_yes
+	.byte	49                              # DW_AT_abstract_origin
+	.byte	19                              # DW_FORM_ref4
+	.byte	17                              # DW_AT_low_pc
+	.byte	1                               # DW_FORM_addr
+	.byte	18                              # DW_AT_high_pc
+	.byte	6                               # DW_FORM_data4
+	.byte	88                              # DW_AT_call_file
+	.byte	11                              # DW_FORM_data1
+	.byte	89                              # DW_AT_call_line
+	.byte	11                              # DW_FORM_data1
+	.byte	87                              # DW_AT_call_column
+	.byte	11                              # DW_FORM_data1
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	12                              # Abbreviation Code
+	.byte	15                              # DW_TAG_pointer_type
+	.byte	0                               # DW_CHILDREN_no
+	.byte	73                              # DW_AT_type
+	.byte	19                              # DW_FORM_ref4
+	.byte	0                               # EOM(1)
+	.byte	0                               # EOM(2)
+	.byte	0                               # EOM(3)
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.short	4                               # DWARF version number
+	.long	.debug_abbrev                   # Offset Into Abbrev. Section
+	.byte	8                               # Address Size (in bytes)
+	.byte	1                               # Abbrev [1] 0xb:0x11c DW_TAG_compile_unit
+	.short	12                              # DW_AT_language
+	.long	.Linfo_string1                  # DW_AT_name
+	.long	.Lline_table_start0             # DW_AT_stmt_list
+	.long	.Linfo_string2                  # DW_AT_comp_dir
+	.quad	.Lfunc_begin1                   # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin1       # DW_AT_high_pc
+.Ldebug_info_f:
+	.byte	5                               # Abbrev [5] 0x5f:0x40 DW_TAG_subprogram
+	.long	.Linfo_string3                  # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	4                               # DW_AT_decl_line
+                                        # DW_AT_prototyped
+                                        # DW_AT_external
+	.byte	1                               # DW_AT_inline
+.Ldebug_info_param1:
+	.byte	6                               # Abbrev [6] 0x67:0xb DW_TAG_formal_parameter
+	.long	.Linfo_string4                  # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	4                               # DW_AT_decl_line
+	.long	.Ldebug_info_void_ptr-.Lcu_begin0
+	                                        # DW_AT_type
+.Ldebug_info_param2:
+	.byte	6                               # Abbrev [6] 0x72:0xb DW_TAG_formal_parameter
+	.long	.Linfo_string5                  # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	4                               # DW_AT_decl_line
+	.long	.Ldebug_info_int-.Lcu_begin0    # DW_AT_type
+.Ldebug_info_param3:
+	.byte	6                               # Abbrev [6] 0x7d:0xb DW_TAG_formal_parameter
+	.long	.Linfo_string7                  # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	4                               # DW_AT_decl_line
+	.long	.Ldebug_info_int-.Lcu_begin0    # DW_AT_type
+.Ldebug_info_param4:
+	.byte	6                               # Abbrev [6] 0x88:0xb DW_TAG_formal_parameter
+	.long	.Linfo_string8                  # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	4                               # DW_AT_decl_line
+	.long	.Ldebug_info_int-.Lcu_begin0    # DW_AT_type
+.Ldebug_info_param5:
+	.byte	6                               # Abbrev [6] 0x93:0xb DW_TAG_formal_parameter
+	.long	.Linfo_string9                  # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	4                               # DW_AT_decl_line
+	.long	.Ldebug_info_int-.Lcu_begin0    # DW_AT_type
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_void_ptr:
+	.byte	7                               # Abbrev [7] 0x9f:0x1 DW_TAG_pointer_type
+.Ldebug_info_int:
+	.byte	8                               # Abbrev [8] 0xa0:0x7 DW_TAG_base_type
+	.long	.Linfo_string6                  # DW_AT_name
+	.byte	5                               # DW_AT_encoding
+	.byte	4                               # DW_AT_byte_size
+	.byte	9                               # Abbrev [9] 0xa7:0x6e DW_TAG_subprogram
+	.quad	.Lfunc_begin1                   # DW_AT_low_pc
+	.long	.Lfunc_end1-.Lfunc_begin1       # DW_AT_high_pc
+	.byte	1                               # DW_AT_frame_base
+	.byte	87
+                                        # DW_AT_GNU_all_call_sites
+	.long	.Linfo_string10                 # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	10                              # DW_AT_decl_line
+                                        # DW_AT_prototyped
+	.long	.Ldebug_info_int-.Lcu_begin0    # DW_AT_type
+                                        # DW_AT_external
+	.byte	10                              # Abbrev [10] 0xc0:0xf DW_TAG_formal_parameter
+	.long	.Ldebug_loc_argc                # DW_AT_location
+	.long	.Linfo_string11                 # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	10                              # DW_AT_decl_line
+	.long	.Ldebug_info_int-.Lcu_begin0    # DW_AT_type
+	.byte	10                              # Abbrev [10] 0xcf:0xf DW_TAG_formal_parameter
+	.long	.Ldebug_loc3                    # DW_AT_location
+	.long	.Linfo_string12                 # DW_AT_name
+	.byte	1                               # DW_AT_decl_file
+	.byte	10                              # DW_AT_decl_line
+	.long	.Ldebug_info_char_ptr_ptr-.Lcu_begin0
+	                                        # DW_AT_type
+	.byte	11                              # Abbrev [11] 0xde:0x36 DW_TAG_inlined_subroutine
+	.long	.Ldebug_info_f-.Lcu_begin0
+	                                        # DW_AT_abstract_origin
+	.quad	.Lline5                         # DW_AT_low_pc
+	.long	.Lline12-.Lline5                # DW_AT_high_pc
+	.byte	1                               # DW_AT_call_file
+	.byte	11                              # DW_AT_call_line
+	.byte	3                               # DW_AT_call_column
+	.byte	4                               # Abbrev [4] 0xf7:0x9 DW_TAG_formal_parameter
+	.long	.Ldebug_loc5                    # DW_AT_location
+	.long	.Ldebug_info_param2-.Lcu_begin0
+	                                        # DW_AT_abstract_origin
+	.byte	4                               # Abbrev [4] 0x105:0x9 DW_TAG_formal_parameter
+	.long	.Ldebug_loc4                    # DW_AT_location
+	.long	.Ldebug_info_param4-.Lcu_begin0
+	                                        # DW_AT_abstract_origin
+	.byte	0                               # End Of Children Mark
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_char_ptr_ptr:
+	.byte	12                              # Abbrev [12] 0x115:0x5 DW_TAG_pointer_type
+	.long	.Ldebug_info_char_ptr-.Lcu_begin0
+	                                        # DW_AT_type
+.Ldebug_info_char_ptr:
+	.byte	12                              # Abbrev [12] 0x11a:0x5 DW_TAG_pointer_type
+	.long	.Ldebug_info_char-.Lcu_begin0   # DW_AT_type
+.Ldebug_info_char:
+	.byte	8                               # Abbrev [8] 0x11f:0x7 DW_TAG_base_type
+	.long	.Linfo_string13                 # DW_AT_name
+	.byte	6                               # DW_AT_encoding
+	.byte	1                               # DW_AT_byte_size
+	.byte	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str,"MS",@progbits,1
+.Linfo_string1:
+	.asciz	"unused-inlined-params.c"       # string offset=30
+.Linfo_string2:
+	.asciz	"/usr/local/google/home/jarin/projects/emsample/ccpp" # string offset=54
+.Linfo_string3:
+	.asciz	"f"                             # string offset=106
+.Linfo_string4:
+	.asciz	"unused1"                       # string offset=108
+.Linfo_string5:
+	.asciz	"used"                          # string offset=116
+.Linfo_string6:
+	.asciz	"int"                           # string offset=121
+.Linfo_string7:
+	.asciz	"unused2"                       # string offset=125
+.Linfo_string8:
+	.asciz	"partial"                       # string offset=133
+.Linfo_string9:
+	.asciz	"unused3"                       # string offset=141
+.Linfo_string10:
+	.asciz	"main"                          # string offset=149
+.Linfo_string11:
+	.asciz	"argc"                          # string offset=154
+.Linfo_string12:
+	.asciz	"argv"                          # string offset=159
+.Linfo_string13:
+	.asciz	"char"                          # string offset=164
+	.section	".note.GNU-stack","",@progbits
+	.addrsig
+	.section	.debug_line,"",@progbits
+.Lline_table_start0:
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -380,10 +380,9 @@
                                     const DWARFDIE &die,
                                     const lldb::addr_t func_low_pc);
 
-  void
-  ParseAndAppendGlobalVariable(const lldb_private::SymbolContext &sc,
-                               const DWARFDIE &die,
-                               lldb_private::VariableList &cc_variable_list);
+  void ParseAndAppendGlobalVariable(
+      const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+      lldb_private::VariableList &cc_variable_list);
 
   size_t ParseVariablesInFunctionContext(const lldb_private::SymbolContext &sc,
                                          const DWARFDIE &die,
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3498,7 +3498,9 @@
     return;
   }
 
-  // We haven't already parsed it, lets do that now.
+  // We haven't parsed the variable yet, lets do that now. Also, let us include
+  // the variable in the relevant compilation unit's variable list, if it
+  // exists.
   VariableListSP variable_list_sp;
   DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
   dw_tag_t parent_tag = sc_parent_die.Tag();
@@ -3540,13 +3542,46 @@
   if (!die || !sc.function)
     return 0;
 
-  const std::function<size_t(const DWARFDIE &, VariableListSP)>
+  using DIEVector = llvm::SmallVector<DWARFDIE, 2>;
+
+  const std::function<size_t(const DWARFDIE &, VariableListSP, DIEVector &,
+                             size_t &)>
       parse_recursive = [this, func_low_pc, &parse_recursive,
                          &sc](const DWARFDIE &die,
-                              VariableListSP variable_list_sp) -> size_t {
+                              VariableListSP variable_list_sp,
+                              DIEVector &abstract_formal_parameters,
+                              size_t &abstract_parameter_index) -> size_t {
     size_t vars_added = 0;
     dw_tag_t tag = die.Tag();
 
+    // If we are parsing a formal parameter, let us make sure that we insert
+    // preceding abstract parameters if they were omitted from the concrete
+    // function instance.
+    if (tag == DW_TAG_formal_parameter) {
+      while (abstract_parameter_index <
+             abstract_formal_parameters.size()) {
+        const DWARFDIE &abstract_parameter =
+            abstract_formal_parameters[abstract_parameter_index++];
+        DWARFDIE parameter = die;
+        bool found = false;
+        while (parameter) {
+          parameter = parameter.GetReferencedDIE(DW_AT_abstract_origin);
+          if (parameter == abstract_parameter) {
+            found = true;
+            break;
+          }
+        }
+        if (found)
+          break;
+        VariableSP var_sp(ParseVariableDIE(sc, abstract_parameter, func_low_pc));
+        if (var_sp) {
+          variable_list_sp->AddVariableIfUnique(var_sp);
+          ++vars_added;
+        }
+      }
+    }
+
+    // If |die| is a variable, parse it and insert it.
     if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
         (tag == DW_TAG_formal_parameter)) {
       VariableSP var_sp(ParseVariableDIE(sc, die, func_low_pc));
@@ -3560,7 +3595,8 @@
     case DW_TAG_subprogram:
     case DW_TAG_inlined_subroutine:
     case DW_TAG_lexical_block: {
-      // If we start a new block, compute a new block context and recurse.
+      // If we are starting a new block, compute a new block context and recurse
+      // in that context.
       Block *block = sc.function->GetBlock(true).FindBlockByID(die.GetID());
       if (block == nullptr) {
         // This must be a specification or abstract origin with a
@@ -3584,11 +3620,46 @@
         block_variable_list_sp = std::make_shared<VariableList>();
         block->SetVariableList(block_variable_list_sp);
       }
+
+      DIEVector block_abstract_formal_parameters;
+      if (tag == DW_TAG_inlined_subroutine) {
+        // Walk abstract origins until we find DW_TAG_subprogram and extract
+        // its formal parameters.
+        DWARFDIE abs_die = die;
+        while (abs_die && abs_die.Tag() != DW_TAG_subprogram) {
+          abs_die = abs_die.GetReferencedDIE(DW_AT_abstract_origin);
+        }
+        if (abs_die && abs_die.HasChildren()) {
+          for (DWARFDIE child = abs_die.GetFirstChild(); child;
+               child = child.GetSibling()) {
+            if (child.Tag() == DW_TAG_formal_parameter) {
+              block_abstract_formal_parameters.push_back(child);
+            }
+          }
+        }
+      }
+
+      size_t block_parameter_index = 0;
+      // Recursively parse children in the context of the block.
       for (DWARFDIE child = die.GetFirstChild(); child;
            child = child.GetSibling()) {
-        vars_added += parse_recursive(child, block_variable_list_sp);
+        vars_added += parse_recursive(child, block_variable_list_sp,
+                                      block_abstract_formal_parameters,
+                                      block_parameter_index);
       }
 
+      // If there any remaining abstract formal parameters, parse and insert
+      // them as well.
+      while (block_parameter_index < block_abstract_formal_parameters.size()) {
+        const DWARFDIE &abstract_parameter =
+            block_abstract_formal_parameters[block_parameter_index++];
+        VariableSP var_sp(
+            ParseVariableDIE(sc, abstract_parameter, func_low_pc));
+        if (var_sp) {
+          block_variable_list_sp->AddVariableIfUnique(var_sp);
+          ++vars_added;
+        }
+      }
       break;
     }
 
@@ -3596,9 +3667,10 @@
       // Recurse to children with the same block context.
       for (DWARFDIE child = die.GetFirstChild(); child;
            child = child.GetSibling()) {
-        vars_added += parse_recursive(child, variable_list_sp);
+        vars_added +=
+            parse_recursive(child, variable_list_sp, abstract_formal_parameters,
+                            abstract_parameter_index);
       }
-
       break;
     }
 
@@ -3608,7 +3680,11 @@
   Block *block = sc.function->GetBlock(true).FindBlockByID(die.GetID());
   const bool can_create = false;
   VariableListSP variable_list_sp = block->GetBlockVariableList(can_create);
-  return parse_recursive(die, variable_list_sp);
+  DIEVector block_abstract_formal_parameters;
+  size_t block_parameter_index = 0;
+  return parse_recursive(die, variable_list_sp,
+                         block_abstract_formal_parameters,
+                         block_parameter_index);
 }
 
 /// Collect call site parameters in a DW_TAG_call_site DIE.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to