When IPA ICF keeps a distinct symbol for an address-taken function by
replacing its body with a wrapper, cgraph_node::create_wrapper reuses the
original function declaration and its early debug DIE.
create_wrapper then calls expand_thunk with force_gimple_thunk set. Forced
GIMPLE thunks are normally created after early debug, so expand_thunk marks
their declarations ignored. For an ICF wrapper this also prevents final
debug emission from attaching the wrapper address to the existing DIE.
The wrapper consequently has code and an STT_FUNC symbol but no
address-bearing DW_TAG_subprogram DIE.
Preserve the declaration's original DECL_IGNORED_P value across forced
GIMPLE thunk expansion in create_wrapper. Declarations that were already
ignored remain ignored, while an original source declaration can receive
its final address information.
Tested on x86_64-pc-linux-gnu with the new gcc.dg/debug/dwarf2 test. The
test fails before the change and passes afterwards.
PR debug/126355
gcc/ChangeLog:
* cgraphunit.cc (cgraph_node::create_wrapper): Preserve
DECL_IGNORED_P across forced GIMPLE thunk expansion.
gcc/testsuite/ChangeLog:
* gcc.dg/debug/dwarf2/pr126355.c: New test.
Signed-off-by: Longjun Luo <[email protected]>
---
gcc/cgraphunit.cc | 5 +++
gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c | 35 ++++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 67aaebf108b..d397c9ae4cc 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -2683,7 +2683,12 @@ cgraph_node::create_wrapper (cgraph_node *target)
arguments = TREE_CHAIN (arguments);
}
+ /* Forced GIMPLE thunks are normally ignored because they are created
+ after early debug. ICF wrappers retain the original function decl and
+ its early DIE, so preserve its original debug state. */
+ bool ignored_p = DECL_IGNORED_P (decl);
expand_thunk (this, false, true);
+ DECL_IGNORED_P (decl) = ignored_p;
thunk_info::remove (this);
/* Inline summary set-up. */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
b/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
new file mode 100644
index 00000000000..35e321008aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
@@ -0,0 +1,35 @@
+/* PR debug/126355 */
+/* Verify that an IPA ICF wrapper for an address-taken function keeps an
+ address-bearing subprogram DIE. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -gdwarf -dA -fdump-ipa-icf-details" } */
+
+int
+pr_icf_wrapper_a (const char *host)
+{
+ (void) host;
+ return 0;
+}
+
+int
+pr_icf_wrapper_b (const char *host)
+{
+ (void) host;
+ return 0;
+}
+
+int (*keep_a) (const char *) = pr_icf_wrapper_a;
+int (*keep_b) (const char *) = pr_icf_wrapper_b;
+
+int
+main (int argc, char **argv)
+{
+ const char *arg = argc > 1 ? argv[1] : "x";
+ return keep_a (arg) + keep_b (arg);
+}
+
+/* Check the ICF direction explicitly because the DWARF scan below inspects
+ pr_icf_wrapper_b, the wrapper. */
+/* { dg-final { scan-ipa-dump "Semantic equality
hit:pr_icf_wrapper_a/\[0-9+\]+->pr_icf_wrapper_b/\[0-9+\]+" "icf" } } */
+/* { dg-final { scan-ipa-dump "Wrapper has been created" "icf" } } */
+/* { dg-final { scan-assembler "\\(DIE \\(0x\[0-9a-f\]+\\)
DW_TAG_subprogram\\)\[\r\n\]+(\[^\r\n\]*\[\r\n\]+){1,12}\[^\r\n\]*DW_AT_name:
\"pr_icf_wrapper_b\"\[\r\n\]+(\[^\r\n\]*\[\r\n\]+){1,12}\[^\r\n\]*DW_AT_low_pc"
} } */
--
2.43.7