From patchwork Mon Dec 29 15:15:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 127188 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 950584BA2E05 for ; Mon, 29 Dec 2025 15:18:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 950584BA2E05 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=kOsJaS3e X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.10]) by sourceware.org (Postfix) with ESMTPS id B89C64BA2E25 for ; Mon, 29 Dec 2025 15:16:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B89C64BA2E25 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B89C64BA2E25 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.10 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021372; cv=none; b=OaUcERqt0A5uIFrbG/dI/YfpNdGdLy2bwhYpO0VlCGLSefmAIoCOauJPd6ZfKLxEeNdHwqI8U+qiAv6RfaJuDlPnQcPWqcfWB/LDKHgxaz9hqzxyfYeAJ3gHx2Lk6rFLdndbEUhUCaizCQj96J0rPSn8bmPY6GxsXbVr1X868us= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021372; c=relaxed/simple; bh=p7oyQDgWfT2R6j0fV5GYv28ANRbxxOPROJI87j6sEbI=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-Id: MIME-Version; b=cUUJPFWuyKxJkcbIAk9hOgvP0ELRW/brf9DbiKKhxbBm3XmPYEAzP/9Mu3hgnhcJsB6c8hhucqDsTN5LhSWHqyjhfJ96ier+41S5kMT+A4KnCYqh3gjfNnSopHP5Vv8TFogw6WagLHRvMTbNPE7j9c3fnj+ItWww3CpuySwvaKg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B89C64BA2E25 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1767021372; x=1798557372; h=from:to:subject:date:message-id:in-reply-to:references; bh=p7oyQDgWfT2R6j0fV5GYv28ANRbxxOPROJI87j6sEbI=; b=kOsJaS3evqc+BBTeXP2PY7DvGAg8ornUT8dIDX8JP71OGwMnzTEMbOs8 wKiInQ/Rd2I4D69EVqf7eTTY+6keB2TbU5JEHT0Mc0IKxSr4jInrPMMK5 1kfj58w/4fHq/M23PCSJxg8WU0QSDEn50gZ7SimRTCg4bZR9GNl7xTWm6 58BBQm/R04XtdiMiU5vWDX/cYRatfwMe4u0H3VEmuPziZaRzJPcIxfuO+ EzA4hTGPuRHJVmHRXLpxReZ6PJJub3Sa7UqwoQPSlQvJE/925Ir6u3SXg K6pFsBghJSamK0FAw+YADCT34eqjbuGYHSlmUmmHJVF49biyyw4Tcc2tl g==; X-CSE-ConnectionGUID: wdmO2Ei+QoSjzb8gX9P1nA== X-CSE-MsgGUID: SpDUxhhhQPuujkV5R9L34Q== X-IronPort-AV: E=McAfee;i="6800,10657,11656"; a="86054033" X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="86054033" MIME-Version: 1.0 Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:11 -0800 X-CSE-ConnectionGUID: rv9ceIFtRgWIpkzRYom9cg== X-CSE-MsgGUID: fI1EEC35RPS4/0nNf6I2Og== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="205976290" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:11 -0800 From: Christina Schimpe To: gdb-patches@sourceware.org Subject: [PATCH 1/5] gdb: Update comment of c_type_print_template_args. Date: Mon, 29 Dec 2025 15:15:14 +0000 Message-Id: <20251229151518.475440-2-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251229151518.475440-1-christina.schimpe@intel.com> References: <20251229151518.475440-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org Remove function description for TABLE. This function does not take a parameter "table". --- gdb/c-typeprint.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 2f921aec8fc..7b1fa7f5c7c 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -787,14 +787,8 @@ c_type_print_varspec_suffix (struct type *type, } } -/* A helper for c_type_print_base that displays template - parameters and their bindings, if needed. - - TABLE is the local bindings table to use. If NULL, no printing is - done. Note that, at this point, TABLE won't have any useful - information in it -- but it is also used as a flag to - print_name_maybe_canonical to activate searching the global typedef - table. +/* A helper for c_type_print_base_struct_union that displays template + parameters. TYPE is the type whose template arguments are being displayed. From patchwork Mon Dec 29 15:15:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 127189 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 796B04BA2E1D for ; Mon, 29 Dec 2025 15:18:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 796B04BA2E1D Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=arjideem X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.10]) by sourceware.org (Postfix) with ESMTPS id 167634BA2E31 for ; Mon, 29 Dec 2025 15:16:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 167634BA2E31 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 167634BA2E31 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.10 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021379; cv=none; b=e/M8sWHB2tKQMvOezWekjeVTY8h9hluEvijR2yRFEmP2OCWSLKQLfoFgt/gbXmhl8330M9+R4FsnNiPZ59IgnAl+g6q1R7Hx+Ht8zZZ20tr2rrrLqHWjbGP/hmjKL7Y9U65ATyMNFacdaxo4sbCvAZxlFhFjGIRjhmFkzZCs4Ek= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021379; c=relaxed/simple; bh=EplS/qmKxyaTEppdfCCd7wxqTuoY4NxaJOs46YNKeHA=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-Id: MIME-Version; b=e5V/fUWe/zQ3ANmEGRzWXoIKmfa7iGxCYvQU1ZNeKqMQJUK7bvEOgfqFj+iBp4PkDfOIK+g89RQB1eW3NnBLNKq1l5tl6F1bQODCRVJ3OBCcizkv5s1Mex5U0zmGBxFwkCoow2gLrdr27GoVvfZI31xDIr0vBzzsPQRHHFhnpSg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 167634BA2E31 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1767021379; x=1798557379; h=from:to:subject:date:message-id:in-reply-to:references; bh=EplS/qmKxyaTEppdfCCd7wxqTuoY4NxaJOs46YNKeHA=; b=arjideemyn4FPqA8xey3uU0sdTdcBpmuGSLBZwgZZE14TKXk7oI9kKFO LwWOmXHIk+WDSBcrZR2MB9rgxcpRW4yzVTDaxYkVabDQHG0H7aUmmv0GD 6VI1a1IU5QcC2J/dVamvh0btjVm/VsB/Pwi/tb9g1hZ+/1rbXszlQE8IT 7P8robz/ghDEe/KV79E341z6Rj/dt62E0+aTz+3SGPMMEoq2R/Irws7lo ytMPbb393xKZDiThtj39oBJ7JZpmYUg+mKQDwWSlB163FO81Px7hVqVHi godoRgMi5Ux3+2eJ8ePR1LR5prE8XHCdi4Z/FFOCul45u/rIA8JrRdT+R A==; X-CSE-ConnectionGUID: Yw2fGG2oQ2ikV5Kk8arXhQ== X-CSE-MsgGUID: 1xRIZAZgTzmNz3T5/T5Zcg== X-IronPort-AV: E=McAfee;i="6800,10657,11656"; a="86054062" X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="86054062" MIME-Version: 1.0 Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:19 -0800 X-CSE-ConnectionGUID: fksRLNbUR0Cv3YSTjYb2xA== X-CSE-MsgGUID: gp1E3o+4Ra64f8tDTn3OGA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="205976307" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:18 -0800 From: Christina Schimpe To: gdb-patches@sourceware.org Subject: [PATCH 2/5] gdb: Support new DWARF for template type parameters. Date: Mon, 29 Dec 2025 15:15:15 +0000 Message-Id: <20251229151518.475440-3-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251229151518.475440-1-christina.schimpe@intel.com> References: <20251229151518.475440-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org The DWARF Version 5 Debugging Format Standard describes the following for a template type parameter: "A template type parameter is represented by a debugging information entry with the tag DW_TAG_template_type_parameter.". It lists the following example (Figure D.51): ~~~ ! DWARF description ! 11$: DW_TAG_structure_type DW_AT_name("wrapper") 12$: DW_TAG_template_type_parameter DW_AT_name("T") DW_AT_type(reference to "int") 13$: DW_TAG_member DW_AT_name("comp") DW_AT_type(reference to 12$) 14$: DW_TAG_variable DW_AT_name("obj") DW_AT_type(reference to 11$) ~~~ Recent compilers like clang and gcc do not support this DWARF feature. Instead, DIE type references which describe source entities referring to the formal template parameter reference the underlying type DIE and not the DW_TAG_template_type_parameter DIE. This is the corresponding gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57006 Currently if we print a type or variable with such DWARF, GDB will print the following: ~~~ (gdb) ptype var type = struct A [with T1 = int, T2 = float] { me_tint; T1 me_int; me_tfloat; T2 me_float; } (gdb) print var $1 = {me_tint = , me_int = 0, me_tfloat = , me_float = 0} ~~~ This patch fixes the errors and adds 2 tests - gdb.dwarf2/template-type-resolution.exp - gdb.dwarf2/self-referential-templates.exp for this DWARF format. This will allow compilers to enable the DWARF format described above without breaking debug support of template type parameters in GDB. In a following commit GDB will be taught to resolve template types correctly based on this new DWARF format. --- gdb/c-typeprint.c | 15 +- gdb/c-valprint.c | 7 + gdb/dwarf2/read.c | 36 +++++ gdb/gdbtypes.c | 8 +- gdb/guile/lib/gdb.scm | 1 + .../gdb.dwarf2/self-referential-templates.exp | 117 ++++++++++++++ .../gdb.dwarf2/template-type-resolution.cc | 37 +++++ .../gdb.dwarf2/template-type-resolution.exp | 144 ++++++++++++++++++ gdb/type-codes.def | 3 + gdb/typeprint.c | 10 +- gdb/valprint.c | 11 ++ 11 files changed, 385 insertions(+), 4 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/self-referential-templates.exp create mode 100644 gdb/testsuite/gdb.dwarf2/template-type-resolution.cc create mode 100644 gdb/testsuite/gdb.dwarf2/template-type-resolution.exp diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 7b1fa7f5c7c..12b69ed6ebe 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -819,7 +819,20 @@ c_type_print_template_args (const struct type_print_options *flags, styled_string (variable_name_style.style (), sym->linkage_name ())); if (sym->loc_class () == LOC_TYPEDEF) - c_print_type (sym->type (), "", stream, -1, 0, language, flags); + { + struct type *sym_type = sym->type (); + + if (sym_type != nullptr + && sym_type->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM) + sym_type = sym_type->target_type (); + + if (sym_type == nullptr) + fprintf_styled (stream, + metadata_style.style (), + _("")); + else + c_print_type (sym_type, "", stream, -1, 0, language, flags); + } else print_variable_value (sym, {}, stream, 0, language_def (language)); } diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index fd31f09ce63..c40ba2304c5 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -424,6 +424,13 @@ c_value_print_inner (struct value *val, struct ui_file *stream, int recurse, struct type *type = val->type (); type = check_typedef (type); + + /* For templated types we want to print the value based on its target + type. */ + if (type->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM + && type->target_type () != nullptr) + type = type->target_type (); + switch (type->code ()) { case TYPE_CODE_ARRAY: diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 4e2644ba959..1525e8e4d39 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -13392,6 +13392,39 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) return ftype; } +/* Extract all information from a DW_TAG_template_type_parameter DIE and + put it in the DIE's type field. */ + +static type * +read_template_type (die_info *die, dwarf2_cu *cu) +{ + objfile *objfile = cu->per_objfile->objfile; + + const char *name = dwarf2_full_name (nullptr, die, cu); + type_allocator alloc (objfile, cu->lang ()); + type *this_type = alloc.new_type (TYPE_CODE_TEMPLATE_TYPE_PARAM, 0, name); + this_type->set_target_is_stub (true); + set_die_type (die, this_type, cu); + type *target_type = die_type (die, cu); + + if (target_type != this_type) + { + this_type->set_target_type (target_type); + this_type->set_length (target_type->length ()); + } + else + { + complaint (_("Self-referential DW_TAG_TEMPLATE_TYPE_PARAM " + "- DIE at %s [in module %s]"), + sect_offset_str (die->sect_off), objfile_name (objfile)); + /* The target type should be set to nullptr in + type_allocator::new_type (). */ + gdb_assert (this_type->target_type () == nullptr); + } + + return this_type; +} + static struct type * read_typedef (struct die_info *die, struct dwarf2_cu *cu) { @@ -17063,6 +17096,9 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_unspecified_type: this_type = read_unspecified_type (die, cu); break; + case DW_TAG_template_type_param: + this_type = read_template_type (die, cu); + break; case DW_TAG_namespace: this_type = read_namespace_type (die, cu); break; diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 975e1246a0d..0bee3fe1bc1 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -3259,9 +3259,13 @@ check_typedef (struct type *type) if (type->target_is_stub ()) { - struct type *target_type = check_typedef (type->target_type ()); + struct type *target_type = type->target_type (); - if (target_type->is_stub () || target_type->target_is_stub ()) + if (target_type != nullptr) + target_type = check_typedef (target_type); + + if (target_type == nullptr + || target_type->is_stub () || target_type->target_is_stub ()) { /* Nothing we can do. */ } diff --git a/gdb/guile/lib/gdb.scm b/gdb/guile/lib/gdb.scm index bf554eadcaf..91f02c4c52a 100644 --- a/gdb/guile/lib/gdb.scm +++ b/gdb/guile/lib/gdb.scm @@ -425,6 +425,7 @@ TYPE_CODE_BOOL TYPE_CODE_COMPLEX TYPE_CODE_TYPEDEF + TYPE_CODE_TEMPLATE_TYPE_PARAM TYPE_CODE_NAMESPACE TYPE_CODE_DECFLOAT TYPE_CODE_INTERNAL_FUNCTION diff --git a/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp b/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp new file mode 100644 index 00000000000..fbe6cad1c00 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp @@ -0,0 +1,117 @@ +# Copyright 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test template type resolution for self-referential template types. + +load_lib dwarf.exp +require dwarf2_support allow_cplus_tests + +standard_testfile template-type-resolution.cc .S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile] {debug c++}] } { + return +} + +if { ![runto_main] } { + return +} + +set asm_file [standard_output_file $srcfile2] +set int_size [get_sizeof "int" -1] + +Dwarf::assemble $asm_file { + global int_size + cu {} { + DW_TAG_compile_unit { + DW_AT_language @DW_LANG_C_plus_plus + } { + declare_labels A template_type_int template_pointer1 + + DW_TAG_subprogram { + MACRO_AT_func "main" + } + + A: DW_TAG_structure_type { + DW_AT_name "A" + DW_AT_byte_size $int_size DW_FORM_sdata + } { + # Cyclic dependency + template_type_int: DW_TAG_template_type_param { + DW_AT_type :$template_type_int + DW_AT_name "T" + } + DW_TAG_member { + DW_AT_name "me_t" + DW_AT_type :$template_type_int + } + + DW_TAG_subprogram { + DW_AT_external 1 DW_FORM_flag + DW_AT_name "t_func" + DW_AT_type :$template_type_int + DW_AT_declaration 1 DW_FORM_flag + } { + DW_TAG_formal_parameter { + DW_AT_type :$template_pointer1 + DW_AT_artificial 1 DW_FORM_flag + } + + DW_TAG_formal_parameter { + DW_AT_type :$template_type_int + } + } + } + + template_pointer1: DW_TAG_pointer_type { + DW_AT_type :$A + } + + DW_TAG_variable { + DW_AT_name "var" + DW_AT_type :$A + DW_AT_location { + DW_OP_addr [gdb_target_symbol "var"] + } SPECIAL_expr + DW_AT_external 1 DW_FORM_flag + } + } + } +} + +with_test_prefix "self-referential template types" { + + if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {debug c++}] } { + return + } + + if { ![runto_main] } { + return + } + + # Setup strings used in the tests below. + set str_unknown "" + + gdb_test "ptype var" [multi_line \ + "type = struct A \\\[with T = $str_unknown\\\] {" \ + " T me_t;.*" \ + " T t_func\\\(T\\\);.*" \ + "}"] + gdb_test "ptype var.me_t" "type = T" + + gdb_test "print var" "{me_t = $str_unknown}" + gdb_test "print var.me_t" "$str_unknown" +} diff --git a/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc b/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc new file mode 100644 index 00000000000..56d9f490fe2 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc @@ -0,0 +1,37 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +template +struct A +{ + T me_t; + + T t_func (T tval) + { + return tval; + } + +}; + +A var = {0}; + +int +main () +{ + asm ("main_label: .globl main_label"); + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp b/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp new file mode 100644 index 00000000000..4e9cc70d0fe --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp @@ -0,0 +1,144 @@ +# Copyright 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test DWARF format which allows GDB to differentiate between template +# types and normal types, which have the same target type. +# +# This format supports DIE type references that describe source entities +# referring to the formal template parameter which reference the +# DW_TAG_template_type_parameter DIE, and not the underlying type DIE. +# +# It is described in the DWARF 5 spec: +# "A template type parameter is represented by a debugging information +# entry with the tag DW_TAG_template_type_parameter." +# which also lists the following example (Figure D.51): +# ! DWARF description +# ! +# 11$: DW_TAG_structure_type +# DW_AT_name("wrapper") +# +# 12$: DW_TAG_template_type_parameter +# DW_AT_name("T") +# DW_AT_type(reference to "int") +# +# 13$: DW_TAG_member +# DW_AT_name("comp") +# DW_AT_type(reference to 12$) +# +# 14$: DW_TAG_variable +# DW_AT_name("obj") +# DW_AT_type(reference to 11$) + +load_lib dwarf.exp + +require dwarf2_support allow_cplus_tests + +standard_testfile .cc .S + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile] {debug c++}] } { + return +} + +if { ![runto_main] } { + return +} + +set int_size [get_sizeof "int" -1] + +set asm_file1 [standard_output_file $srcfile2] +Dwarf::assemble $asm_file1 { + global int_size + cu {} { + DW_TAG_compile_unit { + DW_AT_language @DW_LANG_C_plus_plus + } { + declare_labels int + declare_labels A template_type_int template_pointer1 + + int: DW_TAG_base_type { + DW_AT_name "int" + DW_AT_byte_size $int_size DW_FORM_sdata + DW_AT_encoding @DW_ATE_signed + } + + DW_TAG_subprogram { + MACRO_AT_func "main" + } + + A: DW_TAG_structure_type { + DW_AT_name "A" + DW_AT_byte_size $int_size DW_FORM_sdata + } { + template_type_int: DW_TAG_template_type_param { + DW_AT_type :$int + DW_AT_name "T" + } + DW_TAG_member { + DW_AT_name "me_t" + DW_AT_type :$template_type_int + } + + DW_TAG_subprogram { + DW_AT_external 1 DW_FORM_flag + DW_AT_name "t_func" + DW_AT_type :$template_type_int + DW_AT_declaration 1 DW_FORM_flag + } { + DW_TAG_formal_parameter { + DW_AT_type :$template_pointer1 + DW_AT_artificial 1 DW_FORM_flag + } + + DW_TAG_formal_parameter { + DW_AT_type :$template_type_int + } + } + } + + template_pointer1: DW_TAG_pointer_type { + DW_AT_type :$A + } + + DW_TAG_variable { + DW_AT_name "var" + DW_AT_type :$A + DW_AT_location { + DW_OP_addr [gdb_target_symbol "var"] + } SPECIAL_expr + DW_AT_external 1 DW_FORM_flag + } + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file1] {debug c++}] } { + return +} + +if { ![runto_main] } { + return +} + +gdb_test "ptype var" [multi_line \ + "type = struct A \\\[with T = int\\\] {" \ + " T me_t;.*" \ + " T t_func\\\(T\\\);.*" \ + "}"] + +gdb_test "ptype var.me_t" "type = T" +gdb_test "print var" "\\\{me_t = 0\\\}" + diff --git a/gdb/type-codes.def b/gdb/type-codes.def index e52650ddec9..f6057c705fe 100644 --- a/gdb/type-codes.def +++ b/gdb/type-codes.def @@ -102,6 +102,9 @@ OP (TYPE_CODE_COMPLEX) /**< Complex float */ OP (TYPE_CODE_TYPEDEF) +/* Type for a template type parameter (DW_TAG_template_type_param). */ +OP (TYPE_CODE_TEMPLATE_TYPE_PARAM) + OP (TYPE_CODE_NAMESPACE) /**< C++ namespace. */ OP (TYPE_CODE_DECFLOAT) /**< Decimal floating point. */ diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 92dadd06c90..4ba7a1aabfb 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -223,7 +223,15 @@ typedef_hash_table::add_template_parameters (struct type *t) tf = XOBNEW (&m_storage, struct decl_field); tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name (); - tf->type = TYPE_TEMPLATE_ARGUMENT (t, i)->type (); + type *arg_type = TYPE_TEMPLATE_ARGUMENT (t, i)->type (); + if (arg_type == nullptr) + { + /* Skip self-referential template type parameters for the + hashmap based substitution of template type parameters. */ + continue; + } + + tf->type = arg_type; m_table.emplace (tf); } diff --git a/gdb/valprint.c b/gdb/valprint.c index 91f225c4e60..d29846e6447 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -982,6 +982,12 @@ generic_value_print (struct value *val, struct ui_file *stream, int recurse, type = check_typedef (type); + /* For templated types we want to print the value based on its target + type. */ + if (type->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM + && type->target_type () != nullptr) + type = check_typedef (type->target_type ()); + if (is_fixed_point_type (type)) type = type->fixed_point_type_base_type (); @@ -1089,6 +1095,11 @@ generic_value_print (struct value *val, struct ui_file *stream, int recurse, stream); break; + case TYPE_CODE_TEMPLATE_TYPE_PARAM: + /* This happens for self-referential template type parameters. */ + fprintf_styled (stream, metadata_style.style (), _("")); + break; + case TYPE_CODE_UNION: case TYPE_CODE_STRUCT: default: From patchwork Mon Dec 29 15:15:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 127186 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id C6DCE4BA2E04 for ; Mon, 29 Dec 2025 15:17:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C6DCE4BA2E04 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=dIOh7CQu X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) by sourceware.org (Postfix) with ESMTPS id 93F264BA2E2B for ; Mon, 29 Dec 2025 15:16:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 93F264BA2E2B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 93F264BA2E2B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021387; cv=none; b=L+nwXdccgVNlLfsVXI2Q6Zl1ISx/0qtW7bwoI40nFPDWufSnf8COxpQBLuGkBwBwNalVHuu8TVlFPDP58q87+C5P3ooOH7kJzQaLN9b/n8I6nRaujSZVyetWXOrSvnKvVF7GZ7kM4m/PXwAX66ZjYN3X9hxhmTW4zIL9CGkMtTk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021387; c=relaxed/simple; bh=6CDd3E7pzgP4EqJ8haffUVi04tBEfJ5L6oRuL15LPQk=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-Id: MIME-Version; b=hzBIE7yT6yT5KktVOUW059KDepuBtc2Ua/XOaglMlgsShz6NPtNsIRGYJ0ytML1xu0QKxmE21W88kH7MwIRfRlT6yuMA1t5xm/baNJm6pkkpGfZ7pVy2L9le4FOLrVaXcv9d5zE7M9YdjCfskaStvICd8vRsUCGb/Z2KHtLT3TA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 93F264BA2E2B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1767021388; x=1798557388; h=from:to:subject:date:message-id:in-reply-to:references; bh=6CDd3E7pzgP4EqJ8haffUVi04tBEfJ5L6oRuL15LPQk=; b=dIOh7CQusR0IaVJPu1fQvd3uI103+8WmlNT2ax2VxyQfF/yLz/D00ee2 7cp/zlc55l/YxZ+6SIxb2kfNH/No/nA7V56Nlo1mtFk9o8Xzw2rClr+CV nEOGU8uROwFoTsCC+518j5Rddn9RFe9Mx56Qv/4ULPB+tWfbxd1JAOoeZ i4rDZtplYqiC99gJtNA+15HTo5eOstKVvAS0pJ1+A4MVjh1l4E+cM+rag vM8NRP70ez+xddlm8qiNJSxGvNuKbrOopD+rtTNEw/z382H0zVwKmqKgl KSFdfqsJvHv9VyNxgW0nnLAkARN6qvRYK6XW6YI7bpF6rPSf2t9yhYNdH g==; X-CSE-ConnectionGUID: 7MZZPS+eSyiIO+9mCgdphg== X-CSE-MsgGUID: ZqEENPuRSqmqCsP1yx5jCw== X-IronPort-AV: E=McAfee;i="6800,10657,11656"; a="56199810" X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="56199810" MIME-Version: 1.0 Received: from orviesa006.jf.intel.com ([10.64.159.146]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:27 -0800 X-CSE-ConnectionGUID: FZuA24WvQbi1OQYJovYN+Q== X-CSE-MsgGUID: GbYIwZXrS1G6TjFjwJVKrg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="200066813" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:25 -0800 From: Christina Schimpe To: gdb-patches@sourceware.org Subject: [PATCH 3/5] gdb: Enable correct template type resolution. Date: Mon, 29 Dec 2025 15:15:16 +0000 Message-Id: <20251229151518.475440-4-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251229151518.475440-1-christina.schimpe@intel.com> References: <20251229151518.475440-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org This patch addresses the GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20540 Curently GDB resolves a templated class such as ~~~ template struct A { A () : t_val (), i_val () { } T t_val; int i_val; }; int main () { A a; a.t_val = 1; a.i_val = 3; /* Break here. */ return 0; } ~~~ as follows: ~~~ 14 a.i_val = 3; /* Break here. */ (gdb) ptype a type = struct A [with T = int] { T t_val; T i_val; A(void); ~~~ The DWARF produced by clang $ clang --version Ubuntu clang version 14.0.0-1ubuntu1.1 and extracted with $ llvm-dwarfdump --version Ubuntu LLVM version 14.0.0 currently looks as follows: ~~~ [...] 0x0000000c: DW_TAG_compile_unit DW_AT_producer ("Ubuntu clang version 14.0.0-1ubuntu1.1") DW_AT_language (DW_LANG_C_plus_plus_14) [...] 0x0000002b: DW_TAG_structure_type DW_AT_calling_convention (DW_CC_pass_by_value) DW_AT_name ("A") DW_AT_byte_size (0x08) DW_AT_decl_file ("/tmp/sample.cc") DW_AT_decl_line (2) 0x00000031: DW_TAG_template_type_parameter DW_AT_type (0x00000054 "int") DW_AT_name ("T") 0x00000037: DW_TAG_member DW_AT_name ("t_val") DW_AT_type (0x00000054 "int") DW_AT_decl_file ("/tmp/sample.cc") DW_AT_decl_line (5) DW_AT_data_member_location (0x00) 0x00000040: DW_TAG_member DW_AT_name ("i_val") DW_AT_type (0x00000054 "int") DW_AT_decl_file ("/tmp/sample.cc") DW_AT_decl_line (6) DW_AT_data_member_location (0x04) 0x00000049: DW_TAG_subprogram DW_AT_name ("A") DW_AT_decl_file ("/tmp/sample.cc") DW_AT_decl_line (4) DW_AT_declaration (true) DW_AT_external (true) 0x0000004d: DW_TAG_formal_parameter DW_AT_type (0x00000058 "A *") DW_AT_artificial (true) 0x00000052: NULL 0x00000053: NULL [...] ~~~ The issue is that type references of DIEs that describe source entities referring to the formal template parameter reference the underlying type DIE and not the DW_TAG_template_type_parameter DIE. An example is the DIE describing t_val. For t_val there is no way how a debugger could distinguish this type from a normal member of type int (i_val in the example above). GDB's current template type resolution is based on a typedef_hash_table-based substitution of template type parameters in gdb/c-typeprint.c:c_print_type_1. Due to that map, GDB prints the template type for any member of type int or of the actual templated type. This patch enables correct template type resolution for such cases in case the debuggee supports the new DWARF defined by the DWARF 5 spec. The detailed format has already been described in the former commit "gdb: Support new DWARF for template type parameters.". In case GDB detects the old DWARF format, the template type resolution falls back to the typedef_hash_table-based substitution, so current template type tests will continue to work as before. The dwarf tests gdb.dwarf2/template-type-resolution.exp is extended to verify the correct template type resolution for this new DWARF. For better readability a new test gdb.cp/template-type-parameters.exp is added which focuses on the resolution of template type parameters only. It contains approriate xfails, which refer to the compiler ticket for the new DWARF format: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57006 --- gdb/c-typeprint.c | 10 +- gdb/cp-valprint.c | 6 + gdb/dwarf2/read.c | 25 +- gdb/gdbtypes.h | 8 + .../gdb.cp/template-type-parameters.cc | 95 +++++ .../gdb.cp/template-type-parameters.exp | 195 ++++++++++ .../gdb.dwarf2/template-type-resolution.cc | 9 +- .../gdb.dwarf2/template-type-resolution.exp | 339 +++++++++++++++++- gdb/typeprint.c | 9 +- gdb/typeprint.h | 9 +- 10 files changed, 684 insertions(+), 21 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/template-type-parameters.cc create mode 100644 gdb/testsuite/gdb.cp/template-type-parameters.exp diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 12b69ed6ebe..50dbb47b82c 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -970,13 +970,15 @@ c_type_print_base_struct_union (struct type *type, struct ui_file *stream, c_type_print_template_args (&local_flags, type, stream, language); - /* Add in template parameters when printing derivation info. */ - if (local_flags.local_typedefs != NULL) + if (local_flags.local_typedefs != nullptr + && !HAS_TEMPLATE_TYPE_MEMBER (type)) local_flags.local_typedefs->add_template_parameters (type); cp_type_print_derivation_info (stream, type, &local_flags); - /* This holds just the global typedefs and the template - parameters. */ + /* This holds just the global typedefs, and the template type + parameters in case the condition HAS_TEMPLATE_TYPE_MEMBER + (type) is not fulfilled. */ + struct type_print_options semi_local_flags = *flags; semi_local_flags.local_typedefs = NULL; diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index 252072b66dd..ffbf619e0ab 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -131,6 +131,12 @@ cp_print_value_fields (struct value *val, struct ui_file *stream, static int last_set_recurse = -1; struct type *type = check_typedef (val->type ()); + + /* For templated types we want to print the value based on its target + type. */ + if (val->type ()->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM + && val->type ()->target_type () != nullptr) + type = type->target_type (); if (recurse == 0) { diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 1525e8e4d39..297e01a343b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -11489,8 +11489,31 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) struct field_info fi; std::vector template_args; + if (cu->lang () == language_cplus) + { + if (!HAVE_CPLUS_STRUCT (type)) + ALLOCATE_CPLUS_STRUCT_TYPE (type); + HAS_TEMPLATE_TYPE_MEMBER (type) = false; + } + for (die_info *child_die : die->children ()) - handle_struct_member_die (child_die, type, &fi, &template_args, cu); + { + handle_struct_member_die (child_die, type, &fi, &template_args, cu); + + /* This is a heuristic to detect when DWARF actually references + template type parameter DIEs. */ + if (!template_args.empty () && !HAS_TEMPLATE_TYPE_MEMBER (type)) + { + attribute *type_attr = dwarf2_attr (child_die, DW_AT_type, cu); + if (type_attr != nullptr && type_attr->form_is_ref ()) + { + die_info *type_die + = follow_die_ref (child_die, type_attr, &cu); + if (type_die->tag == DW_TAG_template_type_param) + HAS_TEMPLATE_TYPE_MEMBER (type) = true; + } + } + } /* Attach template arguments to type. */ if (!template_args.empty ()) diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 3ae5a1ef484..c9a67210cff 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1783,6 +1783,12 @@ struct cplus_struct_type classes. */ struct symbol **template_arguments; + + /* Flag used in the heuristic to detect a specific DWARF format for + type DIEs describing source entities referring to the formal template + type parameter. This flag is true if such type DIEs refer to a + DW_TAG_template_type_parameter DIE, otherwise it is set to false. */ + bool has_template_type_member; }; /* * Struct used to store conversion rankings. */ @@ -1991,6 +1997,8 @@ extern void set_type_vptr_basetype (struct type *, struct type *); TYPE_CPLUS_SPECIFIC (thistype)->n_template_arguments #define TYPE_TEMPLATE_ARGUMENTS(thistype) \ TYPE_CPLUS_SPECIFIC (thistype)->template_arguments +#define HAS_TEMPLATE_TYPE_MEMBER(thistype) \ + TYPE_CPLUS_SPECIFIC (thistype)->has_template_type_member #define TYPE_TEMPLATE_ARGUMENT(thistype, n) \ TYPE_CPLUS_SPECIFIC (thistype)->template_arguments[n] diff --git a/gdb/testsuite/gdb.cp/template-type-parameters.cc b/gdb/testsuite/gdb.cp/template-type-parameters.cc new file mode 100644 index 00000000000..9cb0a25062b --- /dev/null +++ b/gdb/testsuite/gdb.cp/template-type-parameters.cc @@ -0,0 +1,95 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 2025 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +template +struct A +{ + A () : t_val (), u_val (), i_val (), f_val () { } + T t_val; + U u_val; + int i_val; + float f_val; + + T tfunc (T tval, U uval) + { + return tval; + } + + int ifunc (int ival, T tval) + { + return ival; + } + + float ffunc (float fval, U uval) + { + return fval; + } +}; + +template +struct B { + T t_val; + + template + struct C { + U u_val; + }; + + C c; +}; + +int +main () +{ + A a; + a.t_val = 1; + a.u_val = 2; + a.i_val = 3; + a.f_val = 4.0f; + + A b; + b.t_val = 1; + b.u_val = 2.0f; + b.i_val = 3; + b.f_val = 4.0f; + + A c; + c.t_val = 1.0; + c.u_val = 2; + c.i_val = 3; + c.f_val = 4.0f; + + A, A> d; + d.t_val = c; + d.u_val = b; + d.i_val = 3; + d.f_val = 4.0f; + + A, A> e; + e.t_val = b; + e.u_val = b; + e.i_val = 3; + e.f_val = 4.0f; + + B f; + f.t_val = 1; + + B> g; + g.t_val = f; + + return 0; /* Break here. */ +} diff --git a/gdb/testsuite/gdb.cp/template-type-parameters.exp b/gdb/testsuite/gdb.cp/template-type-parameters.exp new file mode 100644 index 00000000000..173a09f4b3c --- /dev/null +++ b/gdb/testsuite/gdb.cp/template-type-parameters.exp @@ -0,0 +1,195 @@ +# Copyright 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Test extended template type resolution for a DWARF format which allows +# GDB to differentiate between template types and normal types, which have +# the same target type. +# +# This test is only supported in case a compiler is used which supports a +# specific DWARF format for type references of DIEs that describe source +# entities referring to the formal template parameter. +# They must reference the DW_TAG_template_type_parameter DIE, and not the +# underlying type DIE. +# +# This format is described in the DWARF 5 spec: +# "A template type parameter is represented by a debugging information +# entry with the tag DW_TAG_template_type_parameter." +# which also lists the following example (Figure D.51): +# ! DWARF description +# ! +# 11$: DW_TAG_structure_type +# DW_AT_name("wrapper") +# +# 12$: DW_TAG_template_type_parameter +# DW_AT_name("T") +# DW_AT_type(reference to "int") +# +# 13$: DW_TAG_member +# DW_AT_name("comp") +# DW_AT_type(reference to 12$) +# +# 14$: DW_TAG_variable +# DW_AT_name("obj") +# DW_AT_type(reference to 11$) +# +# For current versions of GCC and Clang this test will fail. + +standard_testfile .cc + +if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug} ] } { + return +} + +if { ![runto_main] } { + return +} + +gdb_breakpoint [gdb_get_line_number "Break here."] +gdb_continue_to_breakpoint "Break here." + +# Test same target type int. +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype a" \ + [multi_line "type = struct A \\\[with T = int, U = int\\\] {" \ + ".*T t_val;.*" \ + ".*U u_val;.*" \ + ".*int i_val;.*" \ + ".*float f_val;.*" \ + ".*A\\(void\\);.*" \ + ".*T tfunc\\(T, U\\);.*" \ + ".*int ifunc\\(int, T\\);.*" \ + ".*float ffunc\\(float, U\\);.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype a.t_val" "type = T" +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype a.u_val" "type = U" +gdb_test "ptype a.i_val" "type = int" +gdb_test "ptype a.f_val" "type = float" + +set val "{t_val = 1, u_val = 2, i_val = 3, f_val = 4}" +gdb_test "print a" "$val" + +# Test same target type float. +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype b" \ + [multi_line "type = struct A \\\[with T = float, U = float\\\] {" \ + ".*T t_val;.*" \ + ".*U u_val;.*" \ + ".*int i_val;.*" \ + ".*float f_val;.*" \ + ".*A\\(void\\);.*" \ + ".*T tfunc\\(T, U\\);.*" \ + ".*int ifunc\\(int, T\\);.*" \ + ".*float ffunc\\(float, U\\);.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype b.t_val" "type = T" +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype b.u_val" "type = U" +gdb_test "ptype b.i_val" "type = int" +gdb_test "ptype b.f_val" "type = float" + +gdb_test "print b" "$val" + +# Test different target types. +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype c" \ + [multi_line "type = struct A \\\[with T = float, U = int\\\] {" \ + ".*T t_val;.*" \ + ".*U u_val;.*" \ + ".*int i_val;.*" \ + ".*float f_val;.*" \ + ".*A\\(void\\);.*" \ + ".*T tfunc\\(T, U\\);.*" \ + ".*int ifunc\\(int, T\\);.*" \ + ".*float ffunc\\(float, U\\);.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype c.t_val" "type = T" +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype c.u_val" "type = U" +gdb_test "ptype c.i_val" "type = int" +gdb_test "ptype c.f_val" "type = float" + +gdb_test "print c" "$val" + +# Test nested template types: d +gdb_test "ptype d" \ + [multi_line "type = struct A, A > \\\[with T = A, U = A\\\] {" \ + ".*T t_val;.*" \ + ".*U u_val;.*" \ + ".*int i_val;.*" \ + ".*float f_val;.*" \ + ".*A\\(void\\);.*" \ + ".*T tfunc\\(T, U\\);.*" \ + ".*int ifunc\\(int, T\\);.*" \ + ".*float ffunc\\(float, U\\);.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype d.t_val" "type = T" +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype d.u_val" "type = U" +gdb_test "ptype d.i_val" "type = int" +gdb_test "ptype d.f_val" "type = float" + +gdb_test "print d" "{t_val = $val, u_val = $val, i_val = 3, f_val = 4}" + +# Test nested template types: e +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype e" \ + [multi_line "type = struct A, A > \\\[with T = A, U = A\\\] {" \ + ".*T t_val;.*" \ + ".*U u_val;.*" \ + ".*int i_val;.*" \ + ".*float f_val;.*" \ + ".*A\\(void\\);.*" \ + ".*T tfunc\\(T, U\\);.*" \ + ".*int ifunc\\(int, T\\);.*" \ + ".*float ffunc\\(float, U\\);.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype e.t_val" "type = T" +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype e.u_val" "type = U" +gdb_test "ptype e.i_val" "type = int" +gdb_test "ptype e.f_val" "type = float" + +gdb_test "print e" "{t_val = $val, u_val = $val, i_val = 3, f_val = 4}" + +gdb_test "ptype f" \ + [multi_line "type = struct B \\\[with T = int\\\] {" \ + ".*T t_val;.*" \ + ".*B::C c;.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype f.t_val" "type = T" + +gdb_test "ptype f.c" \ + [multi_line "type = struct B::C \\\[with U = int\\\] {" \ + ".*U u_val;.*" ] + +gdb_test "ptype g" \ + [multi_line "type = struct B > \\\[with T = B\\\] {" \ + ".*T t_val;.*" \ + ".*B::C c;.*" ] + +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype g.t_val" "type = T" + +gdb_test "ptype g.c" \ + [multi_line "type = struct B >::C > \\\[with U = B\\\] {" \ + ".*U u_val;.*" ] + diff --git a/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc b/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc index 56d9f490fe2..881617f8a63 100644 --- a/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc +++ b/gdb/testsuite/gdb.dwarf2/template-type-resolution.cc @@ -15,10 +15,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -template +template struct A { T me_t; + int me_int; + U me_u; + float me_float; T t_func (T tval) { @@ -27,7 +30,9 @@ struct A }; -A var = {0}; +A var = {0, 0, 0.0f, 0.0f}; +A, A> nestedvar + = {{0.0f, 0, 0.0f, 0.0f}, 0, {0.0f, 0, 0.0f, 0.0f}, 0.0f}; int main () diff --git a/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp b/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp index 4e9cc70d0fe..82788bdfda2 100644 --- a/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp +++ b/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp @@ -57,16 +57,21 @@ if { ![runto_main] } { } set int_size [get_sizeof "int" -1] +set float_size [get_sizeof "float" -1] set asm_file1 [standard_output_file $srcfile2] Dwarf::assemble $asm_file1 { - global int_size + global int_size float_size cu {} { DW_TAG_compile_unit { DW_AT_language @DW_LANG_C_plus_plus } { - declare_labels int - declare_labels A template_type_int template_pointer1 + declare_labels int float + declare_labels A template_type_float template_type_int + declare_labels template_pointer1 template_pointer2 template_pointer3 + declare_labels nestedvar_type template_type_floatfloat + declare_labels template_type_float2 template_type_float3 + declare_labels template_type_float4 template_type_float5 int: DW_TAG_base_type { DW_AT_name "int" @@ -74,22 +79,44 @@ Dwarf::assemble $asm_file1 { DW_AT_encoding @DW_ATE_signed } + float: DW_TAG_base_type { + DW_AT_name "float" + DW_AT_byte_size 4 DW_FORM_sdata + DW_AT_encoding @DW_ATE_float + } + DW_TAG_subprogram { MACRO_AT_func "main" } A: DW_TAG_structure_type { DW_AT_name "A" - DW_AT_byte_size $int_size DW_FORM_sdata + DW_AT_byte_size 2*$int_size+2*$float_size DW_FORM_sdata } { template_type_int: DW_TAG_template_type_param { DW_AT_type :$int DW_AT_name "T" } + template_type_float: DW_TAG_template_type_param { + DW_AT_type :$float + DW_AT_name "U" + } DW_TAG_member { DW_AT_name "me_t" DW_AT_type :$template_type_int } + DW_TAG_member { + DW_AT_name "me_int" + DW_AT_type :$int + } + DW_TAG_member { + DW_AT_name "me_u" + DW_AT_type :$template_type_float + } + DW_TAG_member { + DW_AT_name "me_float" + DW_AT_type :$float + } DW_TAG_subprogram { DW_AT_external 1 DW_FORM_flag @@ -109,6 +136,7 @@ Dwarf::assemble $asm_file1 { } template_pointer1: DW_TAG_pointer_type { + DW_AT_byte_size 8 DW_FORM_data8 DW_AT_type :$A } @@ -120,6 +148,117 @@ Dwarf::assemble $asm_file1 { } SPECIAL_expr DW_AT_external 1 DW_FORM_flag } + + template_type_floatfloat: DW_TAG_structure_type { + DW_AT_name "A" + DW_AT_byte_size 2*$int_size+2*$float_size DW_FORM_sdata + } { + template_type_float2: DW_TAG_template_type_param { + DW_AT_type :$float + DW_AT_name "T" + } + template_type_float3: DW_TAG_template_type_param { + DW_AT_type :$float + DW_AT_name "U" + } + DW_TAG_member { + DW_AT_name "me_t" + DW_AT_type :$template_type_float2 + } + DW_TAG_member { + DW_AT_name "me_int" + DW_AT_type :$int + } + DW_TAG_member { + DW_AT_name "me_u" + DW_AT_type :$template_type_float3 + } + DW_TAG_member { + DW_AT_name "me_float" + DW_AT_type :$float + } + + DW_TAG_subprogram { + DW_AT_external 1 DW_FORM_flag + DW_AT_name "t_func" + DW_AT_type :$template_type_float2 + DW_AT_declaration 1 DW_FORM_flag + } { + DW_TAG_formal_parameter { + DW_AT_type :$template_pointer2 + DW_AT_artificial 1 DW_FORM_flag + } + + DW_TAG_formal_parameter { + DW_AT_type :$template_type_float2 + } + } + } + + template_pointer2: DW_TAG_pointer_type { + DW_AT_byte_size 8 DW_FORM_data8 + DW_AT_type :$template_type_floatfloat + } + + nestedvar_type: DW_TAG_structure_type { + DW_AT_name "A" + DW_AT_byte_size 2*$int_size+2*$float_size DW_FORM_sdata + } { + template_type_float4: DW_TAG_template_type_param { + DW_AT_type :$template_type_floatfloat + DW_AT_name "T" + } + template_type_float5: DW_TAG_template_type_param { + DW_AT_type :$template_type_floatfloat + DW_AT_name "U" + } + DW_TAG_member { + DW_AT_name "me_t" + DW_AT_type :$template_type_float4 + } + DW_TAG_member { + DW_AT_name "me_int" + DW_AT_type :$int + } + DW_TAG_member { + DW_AT_name "me_u" + DW_AT_type :$template_type_float5 + } + DW_TAG_member { + DW_AT_name "me_float" + DW_AT_type :$float + } + + DW_TAG_subprogram { + DW_AT_external 1 DW_FORM_flag + DW_AT_name "t_func" + DW_AT_type :$template_type_float4 + DW_AT_declaration 1 DW_FORM_flag + } { + DW_TAG_formal_parameter { + DW_AT_type :$template_pointer3 + DW_AT_artificial 1 DW_FORM_flag + } + + DW_TAG_formal_parameter { + DW_AT_type :$template_type_float4 + } + } + } + + template_pointer3: DW_TAG_pointer_type { + DW_AT_byte_size 8 DW_FORM_data8 + DW_AT_type :$nestedvar_type + } + + DW_TAG_variable { + DW_AT_name "nestedvar" + DW_AT_type :$nestedvar_type + DW_AT_location { + DW_OP_addr [gdb_target_symbol "nestedvar"] + } SPECIAL_expr + DW_AT_external 1 DW_FORM_flag + } } } } @@ -133,12 +272,196 @@ if { ![runto_main] } { return } +# Setup strings used in the tests below. +set var "{me_t = 0, me_int = 0, me_u = 0, me_float = 0}" +set tfloatfloat "A" + gdb_test "ptype var" [multi_line \ - "type = struct A \\\[with T = int\\\] {" \ - " T me_t;.*" \ +"type = struct A \\\[with T = int, U = float\\\] {" \ + " T me_t;" \ + " int me_int;" \ + " U me_u;" \ + " float me_float;.*" \ " T t_func\\\(T\\\);.*" \ - "}"] +"}"] gdb_test "ptype var.me_t" "type = T" -gdb_test "print var" "\\\{me_t = 0\\\}" +gdb_test "ptype var.me_int" "type = int" +gdb_test "ptype var.me_u" "type = U" +gdb_test "ptype var.me_float" "type = float" + +gdb_test "print var" "$var" + +gdb_test "ptype nestedvar" [multi_line \ + "type = struct A<$tfloatfloat, $tfloatfloat > \\\[with T = $tfloatfloat, U = $tfloatfloat\\\] {" \ + " T me_t;" \ + " int me_int;" \ + " U me_u;" \ + " float me_float;.*" \ + " T t_func\\\(T\\\);.*" \ +"}"] +gdb_test "ptype nestedvar.me_t" "type = T" +gdb_test "ptype nestedvar.me_int" "type = int" +gdb_test "ptype nestedvar.me_u" "type = U" +gdb_test "ptype nestedvar.me_float" "type = float" + +gdb_test "print nestedvar" "{me_t = $var, me_int = 0, me_u = $var, me_float = 0}" + +# Tests for unnamed_var1-unnamed_var3 are basically the same as in +# missing-type-name-for-template, but with the DWARF format described above. + +set asm_file_unnamed_templates [standard_output_file $srcfile2] +Dwarf::assemble $asm_file_unnamed_templates { + global int_size float_size + cu {} { + DW_TAG_compile_unit { + DW_AT_language @DW_LANG_C_plus_plus + } { + declare_labels int float + declare_labels template_var1 template_type_float1 template_type_int1 + declare_labels template_var2 template_type_float2 template_type_int2 + declare_labels template_var3 template_type_float3 template_type_int3 + + int: DW_TAG_base_type { + DW_AT_name "int" + DW_AT_byte_size 4 DW_FORM_data1 + DW_AT_encoding @DW_ATE_signed + } + + float: DW_TAG_base_type { + DW_AT_name "float" + DW_AT_byte_size 4 DW_FORM_sdata + DW_AT_encoding @DW_ATE_float + } + + DW_TAG_subprogram { + MACRO_AT_func "main" + } + + # A variable whose type is a template instantiation with two + # template parameters, one unnamed. + template_var1: DW_TAG_structure_type { + DW_AT_name "template_var1" + DW_AT_byte_size $int_size+$float_size DW_FORM_sdata + } { + template_type_int1: DW_TAG_template_type_param { + DW_AT_type :$int + } + DW_TAG_member { + DW_AT_name "me" + DW_AT_type :$template_type_int1 + } + template_type_float1: DW_TAG_template_type_param { + DW_AT_name "second" + DW_AT_type :$float + } + DW_TAG_member { + DW_AT_name "me2" + DW_AT_type :$template_type_float1 + } + } + DW_TAG_variable { + DW_AT_name "unnamed_var1" + DW_AT_type :$template_var1 + } + + # A variable whose type is a template instantiation with two + # template parameters, both unnamed. + template_var2: DW_TAG_class_type { + DW_AT_name "template_var2" + DW_AT_byte_size $int_size+$float_size DW_FORM_sdata + } { + template_type_int2: DW_TAG_template_type_param { + DW_AT_type :$int + } + DW_TAG_member { + DW_AT_name "me" + DW_AT_type :$template_type_int2 + } + template_type_float2: DW_TAG_template_type_param { + DW_AT_type :$float + } + DW_TAG_member { + DW_AT_name "me2" + DW_AT_type :$template_type_float2 + } + } + DW_TAG_variable { + DW_AT_name "unnamed_var2" + DW_AT_type :$template_var2 + } + + # A variable whose type is a template instantiation with four + # template arguments, two types, two values, all unnamed. + template_var3: DW_TAG_structure_type { + DW_AT_name "template_var3" + DW_AT_byte_size $int_size+$float_size DW_FORM_sdata + } { + DW_TAG_member { + DW_AT_name "me" + DW_AT_type :$template_type_int3 + } + DW_TAG_template_value_param { + DW_AT_type :$int + DW_AT_const_value 0 DW_FORM_sdata + } + template_type_int3: DW_TAG_template_type_param { + DW_AT_type :$int + } + DW_TAG_template_value_param { + DW_AT_type :$int + DW_AT_const_value 11 DW_FORM_sdata + } + template_type_float3: DW_TAG_template_type_param { + DW_AT_type :$float + } + DW_TAG_member { + DW_AT_name "me2" + DW_AT_type :$template_type_float3 + } + } + DW_TAG_variable { + DW_AT_name "unnamed_var3" + DW_AT_type :$template_var3 + } + } + } +} + +set srcfile3 [file join $srcdir $subdir "missing-type-name-for-templates.cc"] + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile3 $asm_file_unnamed_templates] {debug c++}] } { + return +} + +if { ![runto_main] } { + return +} + +gdb_test "ptype unnamed_var1" [multi_line \ + "type = struct template_var1 \\\[with = int, second = float\\\] {" \ + " me;" \ + " second me2;" \ + "}"] + +gdb_test "ptype unnamed_var1.me" "type = " +gdb_test "ptype unnamed_var1.me2" "type = second" + +gdb_test "ptype unnamed_var2" [multi_line \ + "type = class template_var2 \\\[with = int, = float\\\] {" \ + " me;" \ + " me2;" \ + "}"] + +gdb_test "ptype unnamed_var2.me" "type = " +gdb_test "ptype unnamed_var2.me2" "type = " + +gdb_test "ptype unnamed_var3" [multi_line \ + "type = struct template_var3<0, int, 11, float> \\\[with = 0, = int, = 11, = float\\\] {" \ + " me;" \ + " me2;" \ + "}"] +gdb_test "ptype unnamed_var3.me" "type = " +gdb_test "ptype unnamed_var3.me2" "type = " diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 4ba7a1aabfb..a30fe37edc8 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -224,12 +224,11 @@ typedef_hash_table::add_template_parameters (struct type *t) tf = XOBNEW (&m_storage, struct decl_field); tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name (); type *arg_type = TYPE_TEMPLATE_ARGUMENT (t, i)->type (); + + /* Skip self-referential template type parameters for the + hashmap based substitution of template type parameters. */ if (arg_type == nullptr) - { - /* Skip self-referential template type parameters for the - hashmap based substitution of template type parameters. */ - continue; - } + continue; tf->type = arg_type; diff --git a/gdb/typeprint.h b/gdb/typeprint.h index 21931e7a589..d0d6397070f 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -119,7 +119,14 @@ extern const struct type_print_options type_print_raw_options; /* A hash table holding decl_field objects. This is more complicated than an ordinary hash because it must also track the lifetime of some -- but not all - -- of the contained objects. */ + -- of the contained objects. + Once common compilers such as gcc and clang support DWARF format with DIE + type references describing source entities referring to the formal template + parameter that reference the DW_TAG_template_type_parameter, the usage of + this table for template type parameters is obsolete and can be removed. + However, as long as such DIE type references reference the underlying type + DIE this table can still be used, but will result in the issue desribed in + https://sourceware.org/bugzilla/show_bug.cgi?id=20540. */ class typedef_hash_table { From patchwork Mon Dec 29 15:15:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 127190 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 410CF4BA2E38 for ; Mon, 29 Dec 2025 15:19:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 410CF4BA2E38 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=lFsOjQvn X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) by sourceware.org (Postfix) with ESMTPS id 8479A4BA2E31 for ; Mon, 29 Dec 2025 15:16:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8479A4BA2E31 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8479A4BA2E31 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021394; cv=none; b=iyyFA46VOMNxIf3oYNStpw6KjR9Zotl0PcnOM4cK6BuJuRIaTPJfhuU4DgBgVrT1kfKR3M6pPesxCSMdTLQMTPq18+SHUEiwNZQXkUNNhSBCWbLfp/WPyQ4VgWMeYkA+UlDDDEe6aDaqqTU+h9mRBFxIF2FqplBByjV6wvxN+pM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021394; c=relaxed/simple; bh=mrAFnaV7h9vud9XAA/Apc0vRNvdktlYtsuJ1tfRThkU=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-Id: MIME-Version; b=h1hKDqOb/2RAuXG6tc0wsW+oy8KZZ1LH47D0Kbbhl22ubmlq6CtcDWoT+SQtacLtDhOPh4uqTyGg6czn9TuELco6UVVonv/3VGFChVqRV2s/mHv8jCUsTBHh9uX/VowpblY/i9st/o/I0WCrYZAPDTOWxMq6aCxwBTNb0FGBwHo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8479A4BA2E31 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1767021395; x=1798557395; h=from:to:subject:date:message-id:in-reply-to:references; bh=mrAFnaV7h9vud9XAA/Apc0vRNvdktlYtsuJ1tfRThkU=; b=lFsOjQvnhR4lh1fLpLcvs0plypgUpP+TGUr6fPWPi2+jZOYbIMgyIWTl uOg/b5qQZBHEFqtz0PIuRDruQux/RCM9dHhF0fUKvvQXXAogReS8h/FOc uVGBLyZZj3qeDuVG3RHwqirTdj+FDjBjcL9GaDwB2IekegCWo0bHJGlE3 5ByD0SJkBLvLie7pHBf7mJxr+tNT3I/5BN04ZI3OyfPFFNJPymRSiyerm M7C+eqtn/zBmwsq7Krgv/4PBpMkxGzyzTy6Hj2IViQW1rFfONj9yMe5S2 agjctoHPkW+p8bnNKrRlOe2Ln1Deq9zwaKsU8je3kNg9Mo3gnaudkvsKp w==; X-CSE-ConnectionGUID: 5WnYtT7gQfOCvAvrN0ossA== X-CSE-MsgGUID: CmWj65FwS2StpYRNxw12BQ== X-IronPort-AV: E=McAfee;i="6800,10657,11656"; a="56199824" X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="56199824" MIME-Version: 1.0 Received: from orviesa006.jf.intel.com ([10.64.159.146]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:34 -0800 X-CSE-ConnectionGUID: GQjbb/LYQBe7sKMhBnjmrA== X-CSE-MsgGUID: aQRgDn1fTHazkrASTrM0Zw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="200066838" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:33 -0800 From: Christina Schimpe To: gdb-patches@sourceware.org Subject: [PATCH 4/5] gdb: Print target type and name of template members. Date: Mon, 29 Dec 2025 15:15:17 +0000 Message-Id: <20251229151518.475440-5-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251229151518.475440-1-christina.schimpe@intel.com> References: <20251229151518.475440-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org Since commit "gdb: Enable correct template type resolution." GDB is able to resolve template type parameters correctly in case the DWARF provides this information. Currently, when printing the type of a templated class/struct member GDB shows only the template parameter name (e.g. T) but is missing the resolved target type. In contrast, printing the type of entire class/struct shows both. This patch changes this for templated members by adding the target type iformation in a similar style we use already for printing the type of entire structs or classes. Example template class: ~~~ template struct A { T t_val; int i_val; }; int main () { A a; return 0; } ~~~ with good DWARF support as described above, is currently printes as follows: ~~~ (gdb) ptype a type = struct A [with T = int] { T t_val; int i_val; (gdb) ptype a.t_val type = T ~~~ Note that for the second ptype command the target type information is missing. This patch changes this as follows: ~~~ (gdb) ptype a.t_val type = T [with T = int] ~~~ For incomplete DWARF (as generated by current GCC/Clang versions), we still print the underlying type only (e.g. int): ~~~ (gdb) ptype a.t_val type = int ~~~ --- gdb/c-lang.c | 6 +++ gdb/c-lang.h | 9 ++++ gdb/c-typeprint.c | 41 +++++++++++++++++++ .../gdb.cp/template-type-parameters.exp | 28 +++++++------ .../gdb.dwarf2/self-referential-templates.exp | 2 +- .../gdb.dwarf2/template-type-resolution.exp | 20 ++++----- 6 files changed, 83 insertions(+), 23 deletions(-) diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 59db4c4ab6d..045e3cf1244 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -964,6 +964,12 @@ class cplus_language : public language_defn const struct type_print_options *flags) const override { c_print_type (type, varstring, stream, show, level, la_language, flags); + + /* Print target type of TYPE if it is a template type parameter. + For struct/class/unions we print it in + c_type_print_base_struct_union. */ + if (type->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM) + c_type_print_template_type_parameter (type, flags, la_language, stream); } /* See language.h. */ diff --git a/gdb/c-lang.h b/gdb/c-lang.h index 48b3f114d50..e9a29e3547c 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -135,4 +135,13 @@ extern int c_textual_element_type (struct type *, char); extern gdb::unique_xmalloc_ptr c_canonicalize_name (const char *name); +/* Display template type parameter TYPE in the style [with T = ...] based + on FLAGS and LANGUAGE on STREAM. */ + +extern void c_type_print_template_type_parameter + (const type *type, + const type_print_options *flags, + const language language, + ui_file *stream); + #endif /* GDB_C_LANG_H */ diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 50dbb47b82c..b22068ce9ee 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -787,10 +787,41 @@ c_type_print_varspec_suffix (struct type *type, } } +/* See c-lang.h. */ + +void +c_type_print_template_type_parameter (const type *type, + const type_print_options *flags, + const language language, + ui_file *stream) +{ + + gdb_assert (type->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM); + + /* For unnamed templates GDB adds a default name. */ + gdb_assert (type->name () != nullptr); + + if (flags->raw) + return; + + stream->wrap_here (4); + gdb_printf (stream, _(" [with %ps = "), + styled_string (variable_name_style.style (), type->name ())); + + if (type->target_type () == nullptr) + fprintf_styled (stream, metadata_style.style (), _("")); + else + c_print_type (type->target_type (), "", stream, -1, 0, language, flags); + + gdb_puts (_("]"), stream); +} + + /* A helper for c_type_print_base_struct_union that displays template parameters. TYPE is the type whose template arguments are being displayed. + It must be a struct, class or union type. STREAM is the stream on which to print. */ @@ -799,6 +830,10 @@ c_type_print_template_args (const struct type_print_options *flags, struct type *type, struct ui_file *stream, enum language language) { + gdb_assert (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION + || type->is_declared_class ()); + if (flags->raw || TYPE_N_TEMPLATE_ARGUMENTS (type) == 0) return; @@ -1550,6 +1585,12 @@ c_type_print_base_1 (struct type *type, struct ui_file *stream, gdb_puts (type->name (), stream); break; + case TYPE_CODE_TEMPLATE_TYPE_PARAM: + /* For unnamed templates GDB adds a default name. */ + gdb_assert (type->name () != nullptr); + c_print_type (type, "", stream, -1, 0, language, flags); + break; + default: /* Handle types not explicitly handled by the other cases, such as fundamental types. For these, just print whatever the diff --git a/gdb/testsuite/gdb.cp/template-type-parameters.exp b/gdb/testsuite/gdb.cp/template-type-parameters.exp index 173a09f4b3c..92ddbded065 100644 --- a/gdb/testsuite/gdb.cp/template-type-parameters.exp +++ b/gdb/testsuite/gdb.cp/template-type-parameters.exp @@ -73,9 +73,9 @@ gdb_test "ptype a" \ ".*float ffunc\\(float, U\\);.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype a.t_val" "type = T" +gdb_test "ptype a.t_val" "type = T \\\[with T = int\\\]" setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype a.u_val" "type = U" +gdb_test "ptype a.u_val" "type = U \\\[with U = int\\\]" gdb_test "ptype a.i_val" "type = int" gdb_test "ptype a.f_val" "type = float" @@ -96,9 +96,9 @@ gdb_test "ptype b" \ ".*float ffunc\\(float, U\\);.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype b.t_val" "type = T" +gdb_test "ptype b.t_val" "type = T \\\[with T = float\\\]" setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype b.u_val" "type = U" +gdb_test "ptype b.u_val" "type = U \\\[with U = float\\\]" gdb_test "ptype b.i_val" "type = int" gdb_test "ptype b.f_val" "type = float" @@ -118,9 +118,9 @@ gdb_test "ptype c" \ ".*float ffunc\\(float, U\\);.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype c.t_val" "type = T" +gdb_test "ptype c.t_val" "type = T \\\[with T = float\\\]" setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype c.u_val" "type = U" +gdb_test "ptype c.u_val" "type = U \\\[with U = int\\\]" gdb_test "ptype c.i_val" "type = int" gdb_test "ptype c.f_val" "type = float" @@ -139,9 +139,9 @@ gdb_test "ptype d" \ ".*float ffunc\\(float, U\\);.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype d.t_val" "type = T" +gdb_test "ptype d.t_val" "type = T \\\[with T = A\\\]" setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype d.u_val" "type = U" +gdb_test "ptype d.u_val" "type = U \\\[with U = A\\\]" gdb_test "ptype d.i_val" "type = int" gdb_test "ptype d.f_val" "type = float" @@ -161,9 +161,9 @@ gdb_test "ptype e" \ ".*float ffunc\\(float, U\\);.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype e.t_val" "type = T" +gdb_test "ptype e.t_val" "type = T \\\[with T = A\\\]" setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype e.u_val" "type = U" +gdb_test "ptype e.u_val" "type = U \\\[with U = A\\\]" gdb_test "ptype e.i_val" "type = int" gdb_test "ptype e.f_val" "type = float" @@ -175,7 +175,7 @@ gdb_test "ptype f" \ ".*B::C c;.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype f.t_val" "type = T" +gdb_test "ptype f.t_val" "type = T \\\[with T = int\\\]" gdb_test "ptype f.c" \ [multi_line "type = struct B::C \\\[with U = int\\\] {" \ @@ -187,9 +187,13 @@ gdb_test "ptype g" \ ".*B::C c;.*" ] setup_xfail gcc/57006 "*-*-*" -gdb_test "ptype g.t_val" "type = T" +gdb_test "ptype g.t_val" "type = T \\\[with T = B\\\]" gdb_test "ptype g.c" \ [multi_line "type = struct B >::C > \\\[with U = B\\\] {" \ ".*U u_val;.*" ] +setup_xfail gcc/57006 "*-*-*" +gdb_test "ptype func" \ + "type = T \\\(T, U\\\) \\\[with T = int, U = float\\\]" + diff --git a/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp b/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp index fbe6cad1c00..cdd45bda7e1 100644 --- a/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp +++ b/gdb/testsuite/gdb.dwarf2/self-referential-templates.exp @@ -110,7 +110,7 @@ with_test_prefix "self-referential template types" { " T me_t;.*" \ " T t_func\\\(T\\\);.*" \ "}"] - gdb_test "ptype var.me_t" "type = T" + gdb_test "ptype var.me_t" "type = T \\\[with T = \\\]" gdb_test "print var" "{me_t = $str_unknown}" gdb_test "print var.me_t" "$str_unknown" diff --git a/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp b/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp index 82788bdfda2..2f805d7882d 100644 --- a/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp +++ b/gdb/testsuite/gdb.dwarf2/template-type-resolution.exp @@ -285,9 +285,9 @@ gdb_test "ptype var" [multi_line \ " T t_func\\\(T\\\);.*" \ "}"] -gdb_test "ptype var.me_t" "type = T" +gdb_test "ptype var.me_t" "type = T \\\[with T = int\\\]" gdb_test "ptype var.me_int" "type = int" -gdb_test "ptype var.me_u" "type = U" +gdb_test "ptype var.me_u" "type = U \\\[with U = float\\\]" gdb_test "ptype var.me_float" "type = float" gdb_test "print var" "$var" @@ -300,9 +300,9 @@ gdb_test "ptype nestedvar" [multi_line \ " float me_float;.*" \ " T t_func\\\(T\\\);.*" \ "}"] -gdb_test "ptype nestedvar.me_t" "type = T" +gdb_test "ptype nestedvar.me_t" "type = T \\\[with T = $tfloatfloat\\\]" gdb_test "ptype nestedvar.me_int" "type = int" -gdb_test "ptype nestedvar.me_u" "type = U" +gdb_test "ptype nestedvar.me_u" "type = U \\\[with U = $tfloatfloat\\\]" gdb_test "ptype nestedvar.me_float" "type = float" gdb_test "print nestedvar" "{me_t = $var, me_int = 0, me_u = $var, me_float = 0}" @@ -445,8 +445,8 @@ gdb_test "ptype unnamed_var1" [multi_line \ " second me2;" \ "}"] -gdb_test "ptype unnamed_var1.me" "type = " -gdb_test "ptype unnamed_var1.me2" "type = second" +gdb_test "ptype unnamed_var1.me" "type = \\\[with = int\\\]" +gdb_test "ptype unnamed_var1.me2" "type = second \\\[with second = float\\\]" gdb_test "ptype unnamed_var2" [multi_line \ "type = class template_var2 \\\[with = int, = float\\\] {" \ @@ -454,8 +454,8 @@ gdb_test "ptype unnamed_var2" [multi_line \ " me2;" \ "}"] -gdb_test "ptype unnamed_var2.me" "type = " -gdb_test "ptype unnamed_var2.me2" "type = " +gdb_test "ptype unnamed_var2.me" "type = \\\[with = int\\\]" +gdb_test "ptype unnamed_var2.me2" "type = \\\[with = float\\\]" gdb_test "ptype unnamed_var3" [multi_line \ "type = struct template_var3<0, int, 11, float> \\\[with = 0, = int, = 11, = float\\\] {" \ @@ -463,5 +463,5 @@ gdb_test "ptype unnamed_var3" [multi_line \ " me2;" \ "}"] -gdb_test "ptype unnamed_var3.me" "type = " -gdb_test "ptype unnamed_var3.me2" "type = " +gdb_test "ptype unnamed_var3.me" "type = \\\[with = int\\\]" +gdb_test "ptype unnamed_var3.me2" "type = \\\[with = float\\\]" From patchwork Mon Dec 29 15:15:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 127187 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 71AEF4BA2E07 for ; Mon, 29 Dec 2025 15:17:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 71AEF4BA2E07 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=cLzhEr/Q X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) by sourceware.org (Postfix) with ESMTPS id 469AF4BA2E29 for ; Mon, 29 Dec 2025 15:16:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 469AF4BA2E29 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 469AF4BA2E29 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021404; cv=none; b=cL3u++ELgLylMgsDdqmXdhvm/KwMetGrlYyoB7L9xSOCzqP3bdF9FVrOywMqTQCLrXSrzcM0LlsU7ZTcxbt3ot+GxCY7AM6+ByaLfsjCqo90eruVsueTNYMS6yPq0NBhzi7W0+rhWPcjC4MFxX2E0EJwLfviL0ji228kOiTx51M= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767021404; c=relaxed/simple; bh=5q46XX0Ue+jeS0Y4u7KEbVAJWBk14ji+eWZKTS3An5Y=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-Id: MIME-Version; b=QA/vY0HQu/YzfeRZwbo+ndmbaKvC0e3jrSJo4mupr2T9qmySGeVQqDx82golWRQV8N3LRkmu6al88mfsMeJzMAr4nRYqYACmfpbc84zvEdt1D+4oliuvJ6lAlNpPXf+poRweKwtwmcqYH76LDgobFn25h3uNYrpllCWi9nMsUOY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 469AF4BA2E29 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1767021404; x=1798557404; h=from:to:subject:date:message-id:in-reply-to:references; bh=5q46XX0Ue+jeS0Y4u7KEbVAJWBk14ji+eWZKTS3An5Y=; b=cLzhEr/QUEC/vZ5wDxh8zkbCwZyfjkcXSQHrjT8r/0e31EAmcrS9qlMx 613F8e/f6HinxijkQ4OKdGTLTpgi6/qFbWLyZ5nxHBF/1dqVDWF96lETc T1WQ11LotAfA6edFLTnos5HYZOHSq+a21NS4zvN5VH8XmecLJSxfcNa7f aAdZ7mx/FM2fUoaUc7FYn11aNKNcnvsO8YWAR9n4W6uVdvgFxBjlgZFyS j/Scr6ubcd1lKgTdOX+ZNrNkHovKnWiGvn2A+BOONmVYj0E/OQiNQ95qi Ec7KtKhQxP9vZqsyiGNo6wwOyXEes5KV3DWVW2B708Z3KgS5JGmTj9CmF Q==; X-CSE-ConnectionGUID: h1RaFja7SMWyXQUaj+d0gQ== X-CSE-MsgGUID: K7IfZ1SFRJWSQTe2/bJq0w== X-IronPort-AV: E=McAfee;i="6800,10657,11656"; a="56199833" X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="56199833" MIME-Version: 1.0 Received: from orviesa006.jf.intel.com ([10.64.159.146]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:41 -0800 X-CSE-ConnectionGUID: K49NQ0D6RPipFzanENWsvA== X-CSE-MsgGUID: wNrfxOK3TGS5oqPKYZH1qA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,186,1763452800"; d="scan'208";a="200066846" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2025 07:16:40 -0800 From: Christina Schimpe To: gdb-patches@sourceware.org Subject: [PATCH 5/5] gdb: Print template arguments of function templates. Date: Mon, 29 Dec 2025 15:15:18 +0000 Message-Id: <20251229151518.475440-6-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251229151518.475440-1-christina.schimpe@intel.com> References: <20251229151518.475440-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, KAM_SHORT, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patchwork=sourceware.org@sourceware.org For function templates currently no template arguments are printed. Add the list of template arguments to function types and print them, similar to struct, class or union types. From now on we print template functions as follows: ~~~ (gdb) ptype func type = int (int, float) [with T = int, U = float] (gdb) print func $6 = {int (int, float) [with T = int, U = float]} 0x4012a0 (int, float)> ~~~ In case of the new DWARF format as described in the former commit "gdb: Support new DWARF for template type parameters.", we can display the correct relationship, too: ~~~ (gdb) ptype func type = T (T, U) [with T = int, U = float] (gdb) print func $6 = {T (T, U) [with T = int, U = float]} 0x4012a0 (int, float)> ~~~ Extend the test gdb.cp/template-type-parameters.exp for function templates and add the apprioriate xfails which refer to the compiler ticket for the new DWARF format: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57006. Fix the existing tests for template functions to expect the new output. --- gdb/c-lang.c | 8 ++-- gdb/c-lang.h | 11 +++++ gdb/c-typeprint.c | 36 +++++++++------ gdb/dwarf2/read.c | 18 ++++++++ gdb/gdbtypes.c | 3 +- gdb/testsuite/gdb.cp/cp-relocate.exp | 4 +- gdb/testsuite/gdb.cp/cpexprs.exp.tcl | 46 +++++++++---------- .../gdb.cp/template-type-parameters.cc | 10 +++- .../gdb.cp/template-type-parameters.exp | 7 ++- .../template-specification-full-name.exp | 3 +- 10 files changed, 99 insertions(+), 47 deletions(-) diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 045e3cf1244..0a2d1e2f949 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -965,11 +965,13 @@ class cplus_language : public language_defn { c_print_type (type, varstring, stream, show, level, la_language, flags); - /* Print target type of TYPE if it is a template type parameter. - For struct/class/unions we print it in - c_type_print_base_struct_union. */ + /* Print target type or template arguments if TYPE it is a template type + parameter or function template, respecively. For struct/class/unions + we print it in c_type_print_base_struct_union. */ if (type->code () == TYPE_CODE_TEMPLATE_TYPE_PARAM) c_type_print_template_type_parameter (type, flags, la_language, stream); + else if (type->code () == TYPE_CODE_FUNC) + c_type_print_template_args (type, flags, la_language, stream); } /* See language.h. */ diff --git a/gdb/c-lang.h b/gdb/c-lang.h index e9a29e3547c..7ae8285a2c7 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -144,4 +144,15 @@ extern void c_type_print_template_type_parameter const language language, ui_file *stream); +/* Display template arguments of TYPE in the style [with T = ..., U = ...] + based on FLAGS and LANGUAGE on STREAM. + TYPE is the type whose template arguments are being displayed. + It can be a struct/class/union or a function. */ + +extern void c_type_print_template_args + (const type *type, + const type_print_options *flags, + const language language, + ui_file *stream); + #endif /* GDB_C_LANG_H */ diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index b22068ce9ee..8899dc864f8 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -816,28 +816,29 @@ c_type_print_template_type_parameter (const type *type, gdb_puts (_("]"), stream); } +/* See c-lang.h. */ -/* A helper for c_type_print_base_struct_union that displays template - parameters. - - TYPE is the type whose template arguments are being displayed. - It must be a struct, class or union type. - - STREAM is the stream on which to print. */ - -static void -c_type_print_template_args (const struct type_print_options *flags, - struct type *type, struct ui_file *stream, - enum language language) +void +c_type_print_template_args (const type *type, + const type_print_options *flags, + const language language, + ui_file *stream) { gdb_assert (type->code () == TYPE_CODE_STRUCT || type->code () == TYPE_CODE_UNION - || type->is_declared_class ()); + || type->is_declared_class () + || type->code () == TYPE_CODE_FUNC); if (flags->raw || TYPE_N_TEMPLATE_ARGUMENTS (type) == 0) return; stream->wrap_here (4); + + /* For functions we have to add a space here, for struct/class/unions + this is already taken care of in c_type_print_base_struct_union. */ + if (type->code () == TYPE_CODE_FUNC) + gdb_puts (" ", stream); + gdb_printf (stream, _("[with ")); for (int i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (type); ++i) @@ -872,7 +873,12 @@ c_type_print_template_args (const struct type_print_options *flags, print_variable_value (sym, {}, stream, 0, language_def (language)); } - gdb_puts (_("] "), stream); + gdb_puts (_("]"), stream); + + /* For struct/class/unions printing of the type is not complete yet, so + we have to add a space here. */ + if (type->code () != TYPE_CODE_FUNC) + gdb_puts (" ", stream); } /* Use 'print_spaces', but take into consideration the @@ -1003,7 +1009,7 @@ c_type_print_base_struct_union (struct type *type, struct ui_file *stream, struct type *basetype; int vptr_fieldno; - c_type_print_template_args (&local_flags, type, stream, language); + c_type_print_template_args (type, &local_flags, language, stream); if (local_flags.local_typedefs != nullptr && !HAS_TEMPLATE_TYPE_MEMBER (type)) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 297e01a343b..10ef8a89f59 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -8710,6 +8710,24 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) symbols go in the file symbol list. */ if (cu->get_builder ()->outermost_context_p ()) cu->list_in_scope = cu->get_builder ()->get_file_symbols (); + + /* In case of C++ functions, add template parameters to the type, similar + to class/struct/union types handled in process_structure_scope. */ + if (!template_args.empty () && cu->lang () == language_cplus) + { + struct type *type = get_die_type (die, cu); + gdb_assert (type != nullptr && type->code () == TYPE_CODE_FUNC); + + ALLOCATE_CPLUS_STRUCT_TYPE (type); + TYPE_N_TEMPLATE_ARGUMENTS (type) = template_args.size (); + TYPE_TEMPLATE_ARGUMENTS (type) + = XOBNEWVEC (&objfile->objfile_obstack, + struct symbol *, + TYPE_N_TEMPLATE_ARGUMENTS (type)); + memcpy (TYPE_TEMPLATE_ARGUMENTS (type), + template_args.data (), + (TYPE_N_TEMPLATE_ARGUMENTS (type) * sizeof (struct symbol *))); + } } /* Process all the DIES contained within a lexical block scope. Start diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 0bee3fe1bc1..84e57fb9154 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1948,7 +1948,8 @@ set_type_vptr_fieldno (struct type *type, int fieldno) { type = check_typedef (type); gdb_assert (type->code () == TYPE_CODE_STRUCT - || type->code () == TYPE_CODE_UNION); + || type->code () == TYPE_CODE_UNION + || type->code () == TYPE_CODE_FUNC); if (!HAVE_CPLUS_STRUCT (type)) ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_RAW_CPLUS_SPECIFIC (type)->vptr_fieldno = fieldno; diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp index 836f5fb6158..76d4b8d1b4e 100644 --- a/gdb/testsuite/gdb.cp/cp-relocate.exp +++ b/gdb/testsuite/gdb.cp/cp-relocate.exp @@ -54,11 +54,11 @@ gdb_file_cmd ${binfile} set func1_name "" set func2_name "" gdb_test_multiple "info functions func<.>" "info functions" { - -re "\tint (\[^\r\]*func<1>\[^\r]*);" { + -re "\tint (\[^\r\]*func<1>\[^\r]*) \\\[with X = 1\\\];" { set func1_name $expect_out(1,string) exp_continue } - -re "\tint (\[^\r\]*func<2>\[^\r]*);" { + -re "\tint (\[^\r\]*func<2>\[^\r]*) \\\[with X = 2\\\];" { set func2_name $expect_out(1,string) exp_continue } diff --git a/gdb/testsuite/gdb.cp/cpexprs.exp.tcl b/gdb/testsuite/gdb.cp/cpexprs.exp.tcl index 6766ccea19c..d1b8ab67451 100644 --- a/gdb/testsuite/gdb.cp/cpexprs.exp.tcl +++ b/gdb/testsuite/gdb.cp/cpexprs.exp.tcl @@ -449,95 +449,95 @@ add {tclass::do_something} \ - \ - add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = int, E = int]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = int, E = short]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = int, E = long]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = int, E = char]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = short, E = int]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = short, E = short]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = short, E = long]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = short, E = char]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = long, E = int]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = long, E = short]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = long, E = long]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = long, E = char]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = char, E = int]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = char, E = short]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = char, E = long]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = int, D = char, E = char]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = short, D = int, E = int]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = short, D = int, E = short]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = short, D = int, E = long]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = short, D = int, E = char]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = int, B = int, C = short, D = short, E = int]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = short, B = int, C = short, D = int, E = short]} \ - \ flubber add {flubber} \ - {void (void)} \ + {void (void) [with A = long, B = short, C = long, D = short, E = long]} \ - \ flubber add {tclass::do_something} \ diff --git a/gdb/testsuite/gdb.cp/template-type-parameters.cc b/gdb/testsuite/gdb.cp/template-type-parameters.cc index 9cb0a25062b..cf270663dc5 100644 --- a/gdb/testsuite/gdb.cp/template-type-parameters.cc +++ b/gdb/testsuite/gdb.cp/template-type-parameters.cc @@ -52,6 +52,12 @@ struct B { C c; }; +template +static T func (T tval, U uval) +{ + return tval; +} + int main () { @@ -91,5 +97,7 @@ main () B> g; g.t_val = f; - return 0; /* Break here. */ + int retval = func (0, 4.0f); + + return retval; /* Break here. */ } diff --git a/gdb/testsuite/gdb.cp/template-type-parameters.exp b/gdb/testsuite/gdb.cp/template-type-parameters.exp index 92ddbded065..97c212f860d 100644 --- a/gdb/testsuite/gdb.cp/template-type-parameters.exp +++ b/gdb/testsuite/gdb.cp/template-type-parameters.exp @@ -193,7 +193,12 @@ gdb_test "ptype g.c" \ [multi_line "type = struct B >::C > \\\[with U = B\\\] {" \ ".*U u_val;.*" ] +set func_temargs "\\\[with T = int, U = float\\\]" + setup_xfail gcc/57006 "*-*-*" gdb_test "ptype func" \ - "type = T \\\(T, U\\\) \\\[with T = int, U = float\\\]" + "type = T \\\(T, U\\\) $func_temargs" +setup_xfail gcc/57006 "*-*-*" +gdb_test "print func" \ + " = {T \\\(T, U\\\) $func_temargs} $hex \\\(int, float\\\)>" diff --git a/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp b/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp index 010be287289..b4fd46f111b 100644 --- a/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp +++ b/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp @@ -81,4 +81,5 @@ if {![runto_main]} { } # Just a sanity check to make sure GDB slurped the symbols correctly. -gdb_test "print apply" " = {void \\(void\\)} $hex \\(\\)>" +gdb_test "print apply" \ + " = {void \\(void\\) \\\[with T = int\\\]} $hex \\(\\)>"