@@ -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. */
@@ -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 */
@@ -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))
@@ -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
@@ -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;
@@ -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
}
@@ -449,95 +449,95 @@ add {tclass<base>::do_something} \
- \
-
add {flubber<int, int, int, int, int>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = int, E = int]} \
- \
flubber
add {flubber<int, int, int, int, short>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = int, E = short]} \
- \
flubber
add {flubber<int, int, int, int, long>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = int, E = long]} \
- \
flubber
add {flubber<int, int, int, int, char>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = int, E = char]} \
- \
flubber
add {flubber<int, int, int, short, int>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = short, E = int]} \
- \
flubber
add {flubber<int, int, int, short, short>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = short, E = short]} \
- \
flubber
add {flubber<int, int, int, short, long>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = short, E = long]} \
- \
flubber
add {flubber<int, int, int, short, char>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = short, E = char]} \
- \
flubber
add {flubber<int, int, int, long, int>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = long, E = int]} \
- \
flubber
add {flubber<int, int, int, long, short>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = long, E = short]} \
- \
flubber
add {flubber<int, int, int, long, long>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = long, E = long]} \
- \
flubber
add {flubber<int, int, int, long, char>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = long, E = char]} \
- \
flubber
add {flubber<int, int, int, char, int>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = char, E = int]} \
- \
flubber
add {flubber<int, int, int, char, short>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = char, E = short]} \
- \
flubber
add {flubber<int, int, int, char, long>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = char, E = long]} \
- \
flubber
add {flubber<int, int, int, char, char>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = int, D = char, E = char]} \
- \
flubber
add {flubber<int, int, short, int, int>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = short, D = int, E = int]} \
- \
flubber
add {flubber<int, int, short, int, short>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = short, D = int, E = short]} \
- \
flubber
add {flubber<int, int, short, int, long>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = short, D = int, E = long]} \
- \
flubber
add {flubber<int, int, short, int, char>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = short, D = int, E = char]} \
- \
flubber
add {flubber<int, int, short, short, int>} \
- {void (void)} \
+ {void (void) [with A = int, B = int, C = short, D = short, E = int]} \
- \
flubber
add {flubber<short, int, short, int, short>} \
- {void (void)} \
+ {void (void) [with A = short, B = int, C = short, D = int, E = short]} \
- \
flubber
add {flubber<long, short, long, short, long>} \
- {void (void)} \
+ {void (void) [with A = long, B = short, C = long, D = short, E = long]} \
- \
flubber
add {tclass<base>::do_something} \
@@ -52,6 +52,12 @@ struct B {
C<T> c;
};
+template<typename T, typename U>
+static T func (T tval, U uval)
+{
+ return tval;
+}
+
int
main ()
{
@@ -91,5 +97,7 @@ main ()
B<B<int>> g;
g.t_val = f;
- return 0; /* Break here. */
+ int retval = func<int, float> (0, 4.0f);
+
+ return retval; /* Break here. */
}
@@ -193,7 +193,12 @@ gdb_test "ptype g.c" \
[multi_line "type = struct B<B<int> >::C<B<int> > \\\[with U = B<int>\\\] {" \
".*U u_val;.*" ]
+set func_temargs "\\\[with T = int, U = float\\\]"
+
setup_xfail gcc/57006 "*-*-*"
gdb_test "ptype func<int, float>" \
- "type = T \\\(T, U\\\) \\\[with T = int, U = float\\\]"
+ "type = T \\\(T, U\\\) $func_temargs"
+setup_xfail gcc/57006 "*-*-*"
+gdb_test "print func<int, float>" \
+ " = {T \\\(T, U\\\) $func_temargs} $hex <func<int, float>\\\(int, float\\\)>"
@@ -81,4 +81,5 @@ if {![runto_main]} {
}
# Just a sanity check to make sure GDB slurped the symbols correctly.
-gdb_test "print apply<int>" " = {void \\(void\\)} $hex <apply<int>\\(\\)>"
+gdb_test "print apply<int>" \
+ " = {void \\(void\\) \\\[with T = int\\\]} $hex <apply<int>\\(\\)>"