diff options
37 files changed, 475 insertions, 154 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d1fe7ca..85cd3f9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,72 @@ 2017-09-04 Pedro Alves <palves@redhat.com> + * ada-lang.c (ada_evaluate_subexp) <TYPE_CODE_FUNC>: Don't handle + TYPE_GNU_IFUNC specially here. Throw error if return type is + unknown. + * ada-typeprint.c (print_func_type): Handle functions with unknown + return type. + * c-typeprint.c (c_type_print_base): Handle functions and methods + with unknown return type. + * compile/compile-c-symbols.c (convert_symbol_bmsym) + <mst_text_gnu_ifunc>: Use nodebug_text_gnu_ifunc_symbol. + * compile/compile-c-types.c: Include "objfiles.h". + (convert_func): For functions with unknown return type, warn and + default to int. + * compile/compile-object-run.c (compile_object_run): Adjust call + to call_function_by_hand_dummy. + * elfread.c (elf_gnu_ifunc_resolve_addr): Adjust call to + call_function_by_hand. + * eval.c (evaluate_subexp_standard): Adjust calls to + call_function_by_hand. Handle functions and methods with unknown + return type. Pass expect_type to call_function_by_hand. + * f-typeprint.c (f_type_print_base): Handle functions with unknown + return type. + * gcore.c (call_target_sbrk): Adjust call to + call_function_by_hand. + * gdbtypes.c (objfile_type): Leave nodebug text symbol with NULL + return type instead of int. Make nodebug_text_gnu_ifunc_symbol be + an integer address type instead of nodebug. + * guile/scm-value.c (gdbscm_value_call): Adjust call to + call_function_by_hand. + * infcall.c (error_call_unknown_return_type): New function. + (call_function_by_hand): New "default_return_type" parameter. + Pass it down. + (call_function_by_hand_dummy): New "default_return_type" + parameter. Use it instead of defaulting to int. If there's no + default and the return type is unknown, throw an error. If + there's a default return type, and the called function has no + debug info, then assume the function is prototyped. + * infcall.h (call_function_by_hand, call_function_by_hand_dummy): + New "default_return_type" parameter. + (error_call_unknown_return_type): New declaration. + * linux-fork.c (call_lseek): Cast return type of lseek. + (inferior_call_waitpid, checkpoint_command): Adjust calls to + call_function_by_hand. + * linux-tdep.c (linux_infcall_mmap, linux_infcall_munmap): Adjust + calls to call_function_by_hand. + * m2-typeprint.c (m2_procedure): Handle functions with unknown + return type. + * objc-lang.c (lookup_objc_class, lookup_child_selector) + (value_nsstring, print_object_command): Adjust calls to + call_function_by_hand. + * p-typeprint.c (pascal_type_print_varspec_prefix): Handle + functions with unknown return type. + (pascal_type_print_func_varspec_suffix): New function. + (pascal_type_print_varspec_suffix) <TYPE_CODE_FUNC, + TYPE_CODE_METHOD>: Use it. + * python/py-value.c (valpy_call): Adjust call to + call_function_by_hand. + * rust-lang.c (rust_evaluate_funcall): Adjust call to + call_function_by_hand. + * valarith.c (value_x_binop, value_x_unop): Adjust calls to + call_function_by_hand. + * valops.c (value_allocate_space_in_inferior): Adjust call to + call_function_by_hand. + * typeprint.c (type_print_unknown_return_type): New function. + * typeprint.h (type_print_unknown_return_type): New declaration. + +2017-09-04 Pedro Alves <palves@redhat.com> + * gdbtypes.c (lookup_function_type_with_arguments): Mark function types with more than one parameter as prototyped. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index b4e193c..519dfb1 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -10789,13 +10789,11 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, case TYPE_CODE_FUNC: if (noside == EVAL_AVOID_SIDE_EFFECTS) { - struct type *rtype = TYPE_TARGET_TYPE (type); - - if (TYPE_GNU_IFUNC (type)) - return allocate_value (TYPE_TARGET_TYPE (rtype)); - return allocate_value (rtype); + if (TYPE_TARGET_TYPE (type) == NULL) + error_call_unknown_return_type (NULL); + return allocate_value (TYPE_TARGET_TYPE (type)); } - return call_function_by_hand (argvec[0], nargs, argvec + 1); + return call_function_by_hand (argvec[0], NULL, nargs, argvec + 1); case TYPE_CODE_INTERNAL_FUNCTION: if (noside == EVAL_AVOID_SIDE_EFFECTS) /* We don't know anything about what the internal diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c index 8392513..2224bb3 100644 --- a/gdb/ada-typeprint.c +++ b/gdb/ada-typeprint.c @@ -773,7 +773,8 @@ print_func_type (struct type *type, struct ui_file *stream, const char *name, { int i, len = TYPE_NFIELDS (type); - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID) + if (TYPE_TARGET_TYPE (type) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID) fprintf_filtered (stream, "procedure"); else fprintf_filtered (stream, "function"); @@ -798,7 +799,9 @@ print_func_type (struct type *type, struct ui_file *stream, const char *name, fprintf_filtered (stream, ")"); } - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) + if (TYPE_TARGET_TYPE (type) == NULL) + fprintf_filtered (stream, " return <unknown return type>"); + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) { fprintf_filtered (stream, " return "); ada_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 0, flags); diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 890888b..f752300 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -893,13 +893,19 @@ c_type_print_base (struct type *type, struct ui_file *stream, fprintf_filtered (stream, _("<unnamed typedef>")); break; + case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: + if (TYPE_TARGET_TYPE (type) == NULL) + type_print_unknown_return_type (stream); + else + c_type_print_base (TYPE_TARGET_TYPE (type), + stream, show, level, flags); + break; case TYPE_CODE_ARRAY: case TYPE_CODE_PTR: case TYPE_CODE_MEMBERPTR: case TYPE_CODE_REF: case TYPE_CODE_RVALUE_REF: - case TYPE_CODE_FUNC: - case TYPE_CODE_METHOD: case TYPE_CODE_METHODPTR: c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level, flags); diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c index 1cdea85..ee21cf1 100644 --- a/gdb/compile/compile-c-symbols.c +++ b/gdb/compile/compile-c-symbols.c @@ -376,9 +376,7 @@ convert_symbol_bmsym (struct compile_c_instance *context, break; case mst_text_gnu_ifunc: - /* nodebug_text_gnu_ifunc_symbol would cause: - function return type cannot be function */ - type = objfile_type (objfile)->nodebug_text_symbol; + type = objfile_type (objfile)->nodebug_text_gnu_ifunc_symbol; kind = GCC_C_SYMBOL_FUNCTION; addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr); break; diff --git a/gdb/compile/compile-c-types.c b/gdb/compile/compile-c-types.c index dc6391c..2bfa72d 100644 --- a/gdb/compile/compile-c-types.c +++ b/gdb/compile/compile-c-types.c @@ -21,6 +21,8 @@ #include "defs.h" #include "gdbtypes.h" #include "compile-internal.h" +#include "objfiles.h" + /* An object that maps a gdb type to a gcc type. */ struct type_map_instance @@ -233,9 +235,25 @@ convert_func (struct compile_c_instance *context, struct type *type) struct gcc_type_array array; int is_varargs = TYPE_VARARGS (type) || !TYPE_PROTOTYPED (type); + struct type *target_type = TYPE_TARGET_TYPE (type); + + /* Functions with no debug info have no return type. Ideally we'd + want to fallback to the type of the cast just before the + function, like GDB's built-in expression parser, but we don't + have access to that type here. For now, fallback to int, like + GDB's parser used to do. */ + if (target_type == NULL) + { + if (TYPE_OBJFILE_OWNED (type)) + target_type = objfile_type (TYPE_OWNER (type).objfile)->builtin_int; + else + target_type = builtin_type (TYPE_OWNER (type).gdbarch)->builtin_int; + warning (_("function has unknown return type; assuming int")); + } + /* This approach means we can't make self-referential function types. Those are impossible in C, though. */ - return_type = convert_type (context, TYPE_TARGET_TYPE (type)); + return_type = convert_type (context, target_type); array.n_elements = TYPE_NFIELDS (type); array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type)); diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c index de5fa16..43da59f 100644 --- a/gdb/compile/compile-object-run.c +++ b/gdb/compile/compile-object-run.c @@ -172,7 +172,8 @@ compile_object_run (struct compile_module *module) ++current_arg; } gdb_assert (current_arg == TYPE_NFIELDS (func_type)); - call_function_by_hand_dummy (func_val, TYPE_NFIELDS (func_type), vargs, + call_function_by_hand_dummy (func_val, + NULL, TYPE_NFIELDS (func_type), vargs, do_module_cleanup, data); } CATCH (ex, RETURN_MASK_ERROR) diff --git a/gdb/elfread.c b/gdb/elfread.c index cad7aa8..ae84e43 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -877,7 +877,7 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) target_auxv_search (¤t_target, AT_HWCAP, &hwcap); hwcap_val = value_from_longest (builtin_type (gdbarch) ->builtin_unsigned_long, hwcap); - address_val = call_function_by_hand (function, 1, &hwcap_val); + address_val = call_function_by_hand (function, NULL, 1, &hwcap_val); address = value_as_address (address_val); address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, ¤t_target); @@ -1147,12 +1147,12 @@ evaluate_subexp_standard (struct type *expect_type, argvec[3] = value_from_longest (long_type, selector); argvec[4] = 0; - ret = call_function_by_hand (argvec[0], 3, argvec + 1); + ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1); if (gnu_runtime) { /* Function objc_msg_lookup returns a pointer. */ argvec[0] = ret; - ret = call_function_by_hand (argvec[0], 3, argvec + 1); + ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1); } if (value_as_long (ret) == 0) error (_("Target does not respond to this message selector.")); @@ -1169,11 +1169,11 @@ evaluate_subexp_standard (struct type *expect_type, argvec[3] = value_from_longest (long_type, selector); argvec[4] = 0; - ret = call_function_by_hand (argvec[0], 3, argvec + 1); + ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1); if (gnu_runtime) { argvec[0] = ret; - ret = call_function_by_hand (argvec[0], 3, argvec + 1); + ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1); } /* ret should now be the selector. */ @@ -1315,10 +1315,10 @@ evaluate_subexp_standard (struct type *expect_type, deprecated_set_value_type (argvec[0], lookup_pointer_type (lookup_function_type (value_type (argvec[0])))); argvec[0] - = call_function_by_hand (argvec[0], nargs + 2, argvec + 1); + = call_function_by_hand (argvec[0], NULL, nargs + 2, argvec + 1); } - ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1); + ret = call_function_by_hand (argvec[0], NULL, nargs + 2, argvec + 1); return ret; } break; @@ -1705,12 +1705,9 @@ evaluate_subexp_standard (struct type *expect_type, error (_("Cannot evaluate function -- may be inlined")); if (noside == EVAL_AVOID_SIDE_EFFECTS) { - /* If the return type doesn't look like a function type, call an - error. This can happen if somebody tries to turn a variable into - a function call. This is here because people often want to - call, eg, strcmp, which gdb doesn't know is a function. If - gdb isn't asked for it's opinion (ie. through "whatis"), - it won't offer it. */ + /* If the return type doesn't look like a function type, + call an error. This can happen if somebody tries to turn + a variable into a function call. */ struct type *ftype = value_type (argvec[0]); @@ -1731,10 +1728,19 @@ evaluate_subexp_standard (struct type *expect_type, error (_("Xmethod is missing return type.")); return value_zero (return_type, not_lval); } - else if (TYPE_GNU_IFUNC (ftype)) - return allocate_value (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype))); - else if (TYPE_TARGET_TYPE (ftype)) - return allocate_value (TYPE_TARGET_TYPE (ftype)); + else if (TYPE_CODE (ftype) == TYPE_CODE_FUNC + || TYPE_CODE (ftype) == TYPE_CODE_METHOD) + { + struct type *return_type = TYPE_TARGET_TYPE (ftype); + + if (return_type == NULL) + return_type = expect_type; + + if (return_type == NULL) + error_call_unknown_return_type (NULL); + + return allocate_value (return_type); + } else error (_("Expression of type other than " "\"Function returning ...\" used as function")); @@ -1747,7 +1753,8 @@ evaluate_subexp_standard (struct type *expect_type, case TYPE_CODE_XMETHOD: return call_xmethod (argvec[0], nargs, argvec + 1); default: - return call_function_by_hand (argvec[0], nargs, argvec + 1); + return call_function_by_hand (argvec[0], + expect_type, nargs, argvec + 1); } /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve. */ diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c index 7dbe093..2a858aa 100644 --- a/gdb/f-typeprint.c +++ b/gdb/f-typeprint.c @@ -304,9 +304,14 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_ARRAY: - case TYPE_CODE_FUNC: f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); break; + case TYPE_CODE_FUNC: + if (TYPE_TARGET_TYPE (type) == NULL) + type_print_unknown_return_type (stream); + else + f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); + break; case TYPE_CODE_PTR: fprintf_filtered (stream, "PTR TO -> ( "); diff --git a/gdb/gcore.c b/gdb/gcore.c index 50aff2c..07c1997 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -303,7 +303,7 @@ call_target_sbrk (int sbrk_arg) target_sbrk_arg = value_from_longest (builtin_type (gdbarch)->builtin_int, sbrk_arg); gdb_assert (target_sbrk_arg); - ret = call_function_by_hand (sbrk_fn, 1, &target_sbrk_arg); + ret = call_function_by_hand (sbrk_fn, NULL, 1, &target_sbrk_arg); if (ret == NULL) return (bfd_vma) 0; diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index ceb4f0c..a22f0ca 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -5312,13 +5312,13 @@ objfile_type (struct objfile *objfile) objfile_type->nodebug_text_symbol = init_type (objfile, TYPE_CODE_FUNC, 1, "<text variable, no debug info>"); - TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol) - = objfile_type->builtin_int; objfile_type->nodebug_text_gnu_ifunc_symbol = init_type (objfile, TYPE_CODE_FUNC, 1, "<text gnu-indirect-function variable, no debug info>"); + /* Ifunc resolvers return a function address. */ TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol) - = objfile_type->nodebug_text_symbol; + = init_integer_type (objfile, gdbarch_addr_bit (gdbarch), 1, + "__IFUNC_RESOLVER_RET"); TYPE_GNU_IFUNC (objfile_type->nodebug_text_gnu_ifunc_symbol) = 1; objfile_type->nodebug_got_plt_symbol = init_pointer_type (objfile, gdbarch_addr_bit (gdbarch), diff --git a/gdb/guile/scm-value.c b/gdb/guile/scm-value.c index f631032..0dc6630 100644 --- a/gdb/guile/scm-value.c +++ b/gdb/guile/scm-value.c @@ -864,7 +864,7 @@ gdbscm_value_call (SCM self, SCM args) struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark); struct value *return_value; - return_value = call_function_by_hand (function, args_count, vargs); + return_value = call_function_by_hand (function, NULL, args_count, vargs); result = vlscm_scm_from_value (return_value); do_cleanups (cleanup); } diff --git a/gdb/infcall.c b/gdb/infcall.c index 9e434a9..cd3eedf 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -340,6 +340,20 @@ push_dummy_code (struct gdbarch *gdbarch, regcache); } +/* See infcall.h. */ + +void +error_call_unknown_return_type (const char *func_name) +{ + if (func_name != NULL) + error (_("'%s' has unknown return type; " + "cast the call to its declared return type"), + func_name); + else + error (_("function has unknown return type; " + "cast the call to its declared return type")); +} + /* Fetch the name of the function at FUNADDR. This is used in printing an error message for call_function_by_hand. BUF is used to print FUNADDR in hex if the function name cannot be @@ -673,9 +687,12 @@ cleanup_delete_std_terminate_breakpoint (void *ignore) /* See infcall.h. */ struct value * -call_function_by_hand (struct value *function, int nargs, struct value **args) +call_function_by_hand (struct value *function, + type *default_return_type, + int nargs, struct value **args) { - return call_function_by_hand_dummy (function, nargs, args, NULL, NULL); + return call_function_by_hand_dummy (function, default_return_type, + nargs, args, NULL, NULL); } /* All this stuff with a dummy frame may seem unnecessarily complicated @@ -698,6 +715,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) struct value * call_function_by_hand_dummy (struct value *function, + type *default_return_type, int nargs, struct value **args, dummy_frame_dtor_ftype *dummy_dtor, void *dummy_dtor_data) @@ -850,8 +868,16 @@ call_function_by_hand_dummy (struct value *function, } funaddr = find_function_addr (function, &values_type); - if (!values_type) - values_type = builtin_type (gdbarch)->builtin_int; + if (values_type == NULL) + values_type = default_return_type; + if (values_type == NULL) + { + const char *name = get_function_name (funaddr, + name_buf, sizeof (name_buf)); + error (_("'%s' has unknown return type; " + "cast the call to its declared return type"), + name); + } values_type = check_typedef (values_type); @@ -955,6 +981,21 @@ call_function_by_hand_dummy (struct value *function, prototyped. Can we respect TYPE_VARARGS? Probably not. */ if (TYPE_CODE (ftype) == TYPE_CODE_METHOD) prototyped = 1; + if (TYPE_TARGET_TYPE (ftype) == NULL && TYPE_NFIELDS (ftype) == 0 + && default_return_type != NULL) + { + /* Calling a no-debug function with the return type + explicitly cast. Assume the function is prototyped, + with a prototype matching the types of the arguments. + E.g., with: + float mult (float v1, float v2) { return v1 * v2; } + This: + (gdb) p (float) mult (2.0f, 3.0f) + Is a simpler alternative to: + (gdb) p ((float (*) (float, float)) mult) (2.0f, 3.0f) + */ + prototyped = 1; + } else if (i < TYPE_NFIELDS (ftype)) prototyped = TYPE_PROTOTYPED (ftype); else diff --git a/gdb/infcall.h b/gdb/infcall.h index cbaa943..a456d92 100644 --- a/gdb/infcall.h +++ b/gdb/infcall.h @@ -35,9 +35,15 @@ extern CORE_ADDR find_function_addr (struct value *function, representing what the function returned. May fail to return, if a breakpoint or signal is hit during the execution of the function. + DFEAULT_RETURN_TYPE is used as function return type if the return + type is unknown. This is used when calling functions with no debug + info. + ARGS is modified to contain coerced values. */ -extern struct value *call_function_by_hand (struct value *function, int nargs, +extern struct value *call_function_by_hand (struct value *function, + type *default_return_type, + int nargs, struct value **args); /* Similar to call_function_by_hand and additional call @@ -45,9 +51,18 @@ extern struct value *call_function_by_hand (struct value *function, int nargs, created inferior call dummy frame. */ extern struct value * - call_function_by_hand_dummy (struct value *function, int nargs, + call_function_by_hand_dummy (struct value *function, + type *default_return_type, + int nargs, struct value **args, dummy_frame_dtor_ftype *dummy_dtor, void *dummy_dtor_data); +/* Throw an error indicating that the user tried to call a function + that has unknown return type. FUNC_NAME is the name of the + function to be included in the error message; may be NULL, in which + case the error message doesn't include a function name. */ + +extern void error_call_unknown_return_type (const char *func_name); + #endif diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c index 573a3e9..16403c9 100644 --- a/gdb/linux-fork.c +++ b/gdb/linux-fork.c @@ -248,7 +248,7 @@ call_lseek (int fd, off_t offset, int whence) { char exp[80]; - snprintf (&exp[0], sizeof (exp), "lseek (%d, %ld, %d)", + snprintf (&exp[0], sizeof (exp), "(long) lseek (%d, %ld, %d)", fd, (long) offset, whence); return (off_t) parse_and_eval_long (&exp[0]); } @@ -492,7 +492,7 @@ inferior_call_waitpid (ptid_t pptid, int pid) argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); argv[3] = 0; - retv = call_function_by_hand (waitpid_fn, 3, argv); + retv = call_function_by_hand (waitpid_fn, NULL, 3, argv); if (value_as_long (retv) < 0) goto out; @@ -707,7 +707,7 @@ checkpoint_command (char *args, int from_tty) scoped_restore save_pid = make_scoped_restore (&checkpointing_pid, ptid_get_pid (inferior_ptid)); - ret = call_function_by_hand (fork_fn, 0, &ret); + ret = call_function_by_hand (fork_fn, NULL, 0, &ret); } if (!ret) /* Probably can't happen. */ diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index f5389a0..eb44659 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -2448,7 +2448,7 @@ linux_infcall_mmap (CORE_ADDR size, unsigned prot) arg[ARG_FD] = value_from_longest (builtin_type (gdbarch)->builtin_int, -1); arg[ARG_OFFSET] = value_from_longest (builtin_type (gdbarch)->builtin_int64, 0); - addr_val = call_function_by_hand (mmap_val, ARG_LAST, arg); + addr_val = call_function_by_hand (mmap_val, NULL, ARG_LAST, arg); retval = value_as_address (addr_val); if (retval == (CORE_ADDR) -1) error (_("Failed inferior mmap call for %s bytes, errno is changed."), @@ -2477,7 +2477,7 @@ linux_infcall_munmap (CORE_ADDR addr, CORE_ADDR size) /* Assuming sizeof (unsigned long) == sizeof (size_t). */ arg[ARG_LENGTH] = value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_long, size); - retval_val = call_function_by_hand (munmap_val, ARG_LAST, arg); + retval_val = call_function_by_hand (munmap_val, NULL, ARG_LAST, arg); retval = value_as_long (retval_val); if (retval != 0) warning (_("Failed inferior munmap call at %s for %s bytes, " diff --git a/gdb/m2-typeprint.c b/gdb/m2-typeprint.c index 4cf1569..0dd6f19 100644 --- a/gdb/m2-typeprint.c +++ b/gdb/m2-typeprint.c @@ -280,7 +280,8 @@ m2_procedure (struct type *type, struct ui_file *stream, { fprintf_filtered (stream, "PROCEDURE "); m2_type_name (type, stream); - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) + if (TYPE_TARGET_TYPE (type) == NULL + || TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) { int i, len = TYPE_NFIELDS (type); @@ -294,11 +295,11 @@ m2_procedure (struct type *type, struct ui_file *stream, } m2_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0, flags); } + fprintf_filtered (stream, ") : "); if (TYPE_TARGET_TYPE (type) != NULL) - { - fprintf_filtered (stream, " : "); - m2_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 0, flags); - } + m2_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 0, flags); + else + type_print_unknown_return_type (stream); } } diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index bd08514..624310e 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -130,7 +130,8 @@ lookup_objc_class (struct gdbarch *gdbarch, const char *classname) classval = value_string (classname, strlen (classname) + 1, char_type); classval = value_coerce_array (classval); - return (CORE_ADDR) value_as_long (call_function_by_hand (function, + return (CORE_ADDR) value_as_long (call_function_by_hand (function, + NULL, 1, &classval)); } @@ -160,7 +161,7 @@ lookup_child_selector (struct gdbarch *gdbarch, const char *selname) selstring = value_coerce_array (value_string (selname, strlen (selname) + 1, char_type)); - return value_as_long (call_function_by_hand (function, 1, &selstring)); + return value_as_long (call_function_by_hand (function, NULL, 1, &selstring)); } struct value * @@ -181,12 +182,13 @@ value_nsstring (struct gdbarch *gdbarch, char *ptr, int len) if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0).minsym) { function = find_function_in_inferior("_NSNewStringFromCString", NULL); - nsstringValue = call_function_by_hand(function, 1, &stringValue[2]); + nsstringValue = call_function_by_hand(function, + NULL, 1, &stringValue[2]); } else if (lookup_minimal_symbol("istr", 0, 0).minsym) { function = find_function_in_inferior("istr", NULL); - nsstringValue = call_function_by_hand(function, 1, &stringValue[2]); + nsstringValue = call_function_by_hand(function, NULL, 1, &stringValue[2]); } else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0).minsym) { @@ -198,7 +200,7 @@ value_nsstring (struct gdbarch *gdbarch, char *ptr, int len) (type, lookup_objc_class (gdbarch, "NSString")); stringValue[1] = value_from_longest (type, lookup_child_selector (gdbarch, "stringWithCString:")); - nsstringValue = call_function_by_hand(function, 3, &stringValue[0]); + nsstringValue = call_function_by_hand(function, NULL, 3, &stringValue[0]); } else error (_("NSString: internal error -- no way to create new NSString")); @@ -1209,7 +1211,7 @@ print_object_command (char *args, int from_tty) if (function == NULL) error (_("Unable to locate _NSPrintForDebugger in child process")); - description = call_function_by_hand (function, 1, &object); + description = call_function_by_hand (function, NULL, 1, &object); string_addr = value_as_long (description); if (string_addr == 0) diff --git a/gdb/p-typeprint.c b/gdb/p-typeprint.c index d08f6f7..33b4992 100644 --- a/gdb/p-typeprint.c +++ b/gdb/p-typeprint.c @@ -227,7 +227,8 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_METHOD: if (passed_a_ptr) fprintf_filtered (stream, "("); - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) + if (TYPE_TARGET_TYPE (type) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) { fprintf_filtered (stream, "function "); } @@ -255,7 +256,8 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream, if (passed_a_ptr) fprintf_filtered (stream, "("); - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) + if (TYPE_TARGET_TYPE (type) != NULL + && TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) { fprintf_filtered (stream, "function "); } @@ -334,6 +336,33 @@ pascal_print_func_args (struct type *type, struct ui_file *stream, } } +/* Helper for pascal_type_print_varspec_suffix to print the suffix of + a function or method. */ + +static void +pascal_type_print_func_varspec_suffix (struct type *type, struct ui_file *stream, + int show, int passed_a_ptr, + int demangled_args, + const struct type_print_options *flags) +{ + if (TYPE_TARGET_TYPE (type) == NULL + || TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) + { + fprintf_filtered (stream, " : "); + pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), + stream, 0, 0, flags); + + if (TYPE_TARGET_TYPE (type) == NULL) + type_print_unknown_return_type (stream); + else + pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0, + flags); + + pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, + passed_a_ptr, 0, flags); + } +} + /* Print any array sizes, function arguments or close parentheses needed after the variable name (to describe its type). Args work like pascal_type_print_varspec_prefix. */ @@ -365,16 +394,8 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream, pascal_type_print_method_args ("", "", stream); - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) - { - fprintf_filtered (stream, " : "); - pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), - stream, 0, 0, flags); - pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0, - flags); - pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr, 0, flags); - } + pascal_type_print_func_varspec_suffix (type, stream, show, + passed_a_ptr, 0, flags); break; case TYPE_CODE_PTR: @@ -388,16 +409,8 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream, fprintf_filtered (stream, ")"); if (!demangled_args) pascal_print_func_args (type, stream, flags); - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID) - { - fprintf_filtered (stream, " : "); - pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), - stream, 0, 0, flags); - pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0, - flags); - pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr, 0, flags); - } + pascal_type_print_func_varspec_suffix (type, stream, show, + passed_a_ptr, 0, flags); break; case TYPE_CODE_UNDEF: diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index b5a0ef8..cbbb936 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -925,7 +925,8 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords) scoped_value_mark free_values; struct value *return_value; - return_value = call_function_by_hand (function, args_count, vargs); + return_value = call_function_by_hand (function, NULL, + args_count, vargs); result = value_to_value_object (return_value); } CATCH (except, RETURN_MASK_ALL) diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 817976a..c5764bf 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -1290,7 +1290,7 @@ rust_evaluate_funcall (struct expression *exp, int *pos, enum noside noside) if (noside == EVAL_AVOID_SIDE_EFFECTS) result = value_zero (TYPE_TARGET_TYPE (fn_type), not_lval); else - result = call_function_by_hand (function, num_args + 1, args.data ()); + result = call_function_by_hand (function, NULL, num_args + 1, args.data ()); return result; } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 35c5928..c00c300 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,29 @@ 2017-09-04 Pedro Alves <palves@redhat.com> + * gdb.base/break-main-file-remove-fail.exp (test_remove_bp): Cast + return type of munmap in infcall. + * gdb.base/break-probes.exp: Cast return type of foo in infcall. + * gdb.base/checkpoint.exp: Simplify using for loop. Cast return + type of ftell in infcall. + * gdb.base/dprintf-detach.exp (dprintf_detach_test): Cast return + type of getpid in infcall. + * gdb.base/infcall-exec.exp: Cast return type of execlp in + infcall. + * gdb.base/info-os.exp: Cast return type of getpid in infcall. + Bail on failure to extract the pid. + * gdb.base/nodebug.c: #include <stdint.h>. + (multf, multf_noproto, mult, mult_noproto, add8, add8_noproto): + New functions. + * gdb.base/nodebug.exp (test_call_promotion): New procedure. + Change expected output of print/whatis/ptype with functions with + no debug info. Test all supported languages. Call + test_call_promotion. + * gdb.compile/compile.exp: Adjust expected output to expect + warning. + * gdb.threads/siginfo-threads.exp: Likewise. + +2017-09-04 Pedro Alves <palves@redhat.com> + * gdb.base/callfuncs.exp (do_function_calls): New parameter "prototypes". Test calling float functions via prototyped and unprototyped function pointers. diff --git a/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp b/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp index eba72bc..080d193 100644 --- a/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp +++ b/gdb/testsuite/gdb.base/break-main-file-remove-fail.exp @@ -88,7 +88,7 @@ proc test_remove_bp { initial_load } { # should warn the user about it. set pagesize [get_integer_valueof "pg_size" 0] set align_addr [expr $bp_addr - $bp_addr % $pagesize] - set munmap [get_integer_valueof "munmap ($align_addr, $pagesize)" -1] + set munmap [get_integer_valueof "(int) munmap ($align_addr, $pagesize)" -1] if {$munmap != 0} { unsupported "can't munmap foo's page" diff --git a/gdb/testsuite/gdb.base/break-probes.exp b/gdb/testsuite/gdb.base/break-probes.exp index 929509a..318a219 100644 --- a/gdb/testsuite/gdb.base/break-probes.exp +++ b/gdb/testsuite/gdb.base/break-probes.exp @@ -86,5 +86,5 @@ if { $using_probes } { } # Call something to ensure that relocation occurred - gdb_test "call foo(23)" "\\\$.* = 31.*\\\M.*" + gdb_test "call (int) foo(23)" "\\\$.* = 31.*\\\M.*" } diff --git a/gdb/testsuite/gdb.base/checkpoint.exp b/gdb/testsuite/gdb.base/checkpoint.exp index 12c1d8a..677c389 100644 --- a/gdb/testsuite/gdb.base/checkpoint.exp +++ b/gdb/testsuite/gdb.base/checkpoint.exp @@ -224,45 +224,11 @@ gdb_test "shell diff $pi_txt $copy1_txt" \ delete_breakpoints gdb_breakpoint $break2_loc -gdb_test "restart 1" "if .c == EOF.*" "restart 1 three" -gdb_test "continue" "breakpoint 2.*" "break2 1 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 1" - -gdb_test "restart 2" "if .c == EOF.*" "restart 2 three" -gdb_test "continue" "breakpoint 2.*" "break2 2 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 2" - -gdb_test "restart 3" "if .c == EOF.*" "restart 3 three" -gdb_test "continue" "breakpoint 2.*" "break2 3 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 3" - -gdb_test "restart 4" "if .c == EOF.*" "restart 4 three" -gdb_test "continue" "breakpoint 2.*" "break2 4 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 4" - -gdb_test "restart 5" "if .c == EOF.*" "restart 5 three" -gdb_test "continue" "breakpoint 2.*" "break2 5 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 5" - -gdb_test "restart 6" "if .c == EOF.*" "restart 6 three" -gdb_test "continue" "breakpoint 2.*" "break2 6 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 6" - -gdb_test "restart 7" "if .c == EOF.*" "restart 7 three" -gdb_test "continue" "breakpoint 2.*" "break2 7 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 7" - -gdb_test "restart 8" "if .c == EOF.*" "restart 8 three" -gdb_test "continue" "breakpoint 2.*" "break2 8 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 8" - -gdb_test "restart 9" "if .c == EOF.*" "restart 9 three" -gdb_test "continue" "breakpoint 2.*" "break2 9 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 9" - -gdb_test "restart 10" "if .c == EOF.*" "restart 10 three" -gdb_test "continue" "breakpoint 2.*" "break2 10 one" -gdb_test "print ftell (out) > 100000" " = 1.*" "outfile still open 10" +for {set num 1} {$num <= 10} {incr num} { + gdb_test "restart $num" "if .c == EOF.*" "restart $num three" + gdb_test "continue" "breakpoint 2.*" "break2 $num one" + gdb_test "print (long) ftell (out) > 100000" " = 1.*" "outfile still open $num" +} # # Now confirm that if one fork exits, we automatically switch to another one. diff --git a/gdb/testsuite/gdb.base/dprintf-detach.exp b/gdb/testsuite/gdb.base/dprintf-detach.exp index 4c6ef1c..940a9ef 100644 --- a/gdb/testsuite/gdb.base/dprintf-detach.exp +++ b/gdb/testsuite/gdb.base/dprintf-detach.exp @@ -53,7 +53,7 @@ proc dprintf_detach_test { breakpoint_always_inserted dprintf_style disconnected # Get PID of test program. set inferior_pid -1 set test "get inferior process ID" - gdb_test_multiple "call getpid ()" $test { + gdb_test_multiple "call (int) getpid ()" $test { -re ".* = ($decimal).*$gdb_prompt $" { set inferior_pid $expect_out(1,string) pass $test diff --git a/gdb/testsuite/gdb.base/infcall-exec.exp b/gdb/testsuite/gdb.base/infcall-exec.exp index 3984076..8419905 100644 --- a/gdb/testsuite/gdb.base/infcall-exec.exp +++ b/gdb/testsuite/gdb.base/infcall-exec.exp @@ -44,5 +44,5 @@ append expected_result "\[\r\n\]+.*" append expected_result "Breakpoint 1, main .*at .*$srcfile2:$decimal" append expected_result ".*" -gdb_test "call execlp \(\"$binfile2\", \"$binfile2\", \(char \*\)0\)" \ +gdb_test "call (int) execlp \(\"$binfile2\", \"$binfile2\", \(char \*\)0\)" \ $expected_result "call execlp" diff --git a/gdb/testsuite/gdb.base/info-os.exp b/gdb/testsuite/gdb.base/info-os.exp index 0168ccb..574da26 100644 --- a/gdb/testsuite/gdb.base/info-os.exp +++ b/gdb/testsuite/gdb.base/info-os.exp @@ -39,14 +39,18 @@ if ![runto_main] then { } # Get PID of test program. -set inferior_pid -1 +set inferior_pid "" set test "get inferior process ID" -gdb_test_multiple "call getpid()" $test { +gdb_test_multiple "call (int) getpid()" $test { -re ".* = ($decimal).*$gdb_prompt $" { set inferior_pid $expect_out(1,string) pass $test } } +if {$inferior_pid == ""} { + untested "failed to get pid" + return +} gdb_breakpoint ${srcfile}:[gdb_get_line_number "Set breakpoint here"] gdb_continue_to_breakpoint "Set breakpoint here" diff --git a/gdb/testsuite/gdb.base/nodebug.c b/gdb/testsuite/gdb.base/nodebug.c index eb5d661..99641e8 100644 --- a/gdb/testsuite/gdb.base/nodebug.c +++ b/gdb/testsuite/gdb.base/nodebug.c @@ -1,4 +1,6 @@ #include <stdlib.h> +#include <stdint.h> + /* Test that things still (sort of) work when compiled without -g. */ int dataglobal = 3; /* Should go in global data */ @@ -43,3 +45,42 @@ int array_index (char *arr, int i) free (x); return retval; } + +float +multf (float v1, float v2) +{ + return v1 * v2; +} + +float +multf_noproto (v1, v2) + float v1, v2; +{ + return v1 * v2; +} + +double +mult (double v1, double v2) +{ + return v1 * v2; +} + +double +mult_noproto (v1, v2) + double v1, v2; +{ + return v1 * v2; +} + +uint8_t +add8 (uint8_t v1, uint8_t v2) +{ + return v1 + v2; +} + +uint8_t +add8_noproto (v1, v2) + uint8_t v1, v2; +{ + return v1 + v2; +} diff --git a/gdb/testsuite/gdb.base/nodebug.exp b/gdb/testsuite/gdb.base/nodebug.exp index a54e5bb..7bdf9ad 100644 --- a/gdb/testsuite/gdb.base/nodebug.exp +++ b/gdb/testsuite/gdb.base/nodebug.exp @@ -39,6 +39,40 @@ if { [gdb_compile $srcdir/$subdir/$srcfile $binfile executable $exec_opts] != " clean_restart $binfile +# Test calling no-debug functions involving argument types that may +# require coercion/promotion, both prototyped and unprototyped, both +# return-type-cast style, and function-pointer-cast styles. +proc test_call_promotion {} { + if [target_info exists gdb,cannot_call_functions] { + return + } + + # Call prototyped function with float parameters via both + # return-type cast and function-pointer cast. This checks that + # GDB doesn't do float->double coercion. + gdb_test "p (float) multf(2.0f, 3.0f)" " = 6" + gdb_test "p ((float (*) (float, float)) multf)(2, 3)" " = 6" + gdb_test "p ((float (*) (float, float)) multf)(2.0f, 3.0f)" " = 6" + + # Call unprototyped function with float parameters via + # function-pointer cast, only. return-type cast assumes + # protototyped. Check that GDB does float->double coercion. + gdb_test "p ((float (*) ()) multf_noproto)(2.0f, 3.0f)" " = 6" + gdb_test "p ((float (*) ()) multf_noproto)(2.0, 3.0)" " = 6" + + # Same, but for double. + gdb_test "p (double) mult (2.0, 3.0)" " = 6" + gdb_test "p ((double (*) (double, double)) mult)(2.0f, 3.0f)" " = 6" + gdb_test "p ((double (*) (double, double)) mult)(2, 3)" " = 6" + gdb_test "p ((double (*) ()) mult_noproto)(2.0f, 3.0f)" " = 6" + gdb_test "p ((double (*) ()) mult_noproto)(2.0, 3.0)" " = 6" + + # Check that GDB promotes char->int correctly. + gdb_test "p /d (uint8) add8((uint8) 2, (uint8) 3)" " = 5" + gdb_test "p /d ((uint8 (*) (uint8, uint8)) add8)((uint8) 2, (uint8) 3)" " = 5" + gdb_test "p /d ((uint8 (*) ()) add8_noproto)((uint8) 2, (uint8) 3)" " = 5" +} + if [runto inner] then { # Expect to find global/local symbols in each of text/data/bss. @@ -59,18 +93,66 @@ if [runto inner] then { # out debugging info for non-aggregate return values of functions # even without -g, which should be accepted. - gdb_test "p top" \ - "\{(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))\} \[0-9a-fx]* <\\.?top(\\(int\\)|)>" - gdb_test "whatis top" \ - "(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))" - gdb_test "ptype top" "(short|int) \\((|void|int|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)" - - gdb_test "p middle" \ - "\{(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))\} \[0-9a-fx]* <\\.?middle(\\(int\\)|)>" - gdb_test "whatis middle" \ - "(<(text variable|function), no debug info>|short \\(int\\)|short \\(\\))" - gdb_test "ptype middle" "(short|int) \\((|void|int|<non-float parameter>|<non-float parameter>, <non-float parameter>)\\)" - + with_test_prefix "func" { + # Most languages default to printing like C. + set c_print_re " = \\{<text variable, no debug info>\\} $hex <top>" + set c_whatis_re " = <text variable, no debug info>" + set c_ptype_re "= <unknown return type> \\(\\)" + + set cxx_ptype_re "= <unknown return type> \\(void\\)" + + set ada_ptype_re " = function return <unknown return type>" + + set m2_print_re " = \\{PROCEDURE <text variable, no debug info> \\(\\) : <unknown return type>\\} $hex <top>" + set m2_whatis_re "PROCEDURE <text variable, no debug info> \\(\\) : <unknown return type>" + set m2_ptype_re $m2_whatis_re + + # Rust can't access minsyms? + set rust_nosym "No symbol 'top' in current context" + + set pascal_ptype_re "type = procedure : <unknown return type>" + + #LANG #PRINT #WHATIS #PTYPE + foreach lang_line { + {"ada" $c_print_re $c_whatis_re $ada_ptype_re} + {"asm" $c_print_re $c_whatis_re $c_ptype_re} + {"c" $c_print_re $c_whatis_re $c_ptype_re} + {"c++" $c_print_re $c_whatis_re $cxx_ptype_re} + {"d" $c_print_re $c_whatis_re $c_ptype_re} + {"fortran" $c_print_re $c_whatis_re $c_ptype_re} + {"go" $c_print_re $c_whatis_re $c_ptype_re} + {"minimal" $c_print_re $c_whatis_re $c_ptype_re} + {"modula-2" $m2_print_re $m2_whatis_re $m2_ptype_re} + {"objective-c" $c_print_re $c_whatis_re $c_ptype_re} + {"opencl" $c_print_re $c_whatis_re $c_ptype_re} + {"pascal" $c_print_re $c_whatis_re $pascal_ptype_re} + {"rust" $rust_nosym $rust_nosym $rust_nosym} + } { + set lang [lindex $lang_line 0] + set print_re [lindex $lang_line 1] + set whatis_re [lindex $lang_line 2] + set ptype_re [lindex $lang_line 3] + + set print_re [subst "$print_re"] + set whatis_re [subst "$whatis_re"] + set ptype_re [subst "$ptype_re"] + + with_test_prefix "$lang" { + gdb_test_no_output "set language $lang" + gdb_test "p top" $print_re + gdb_test "whatis top" $whatis_re + gdb_test "ptype top" $ptype_re + } + } + } + + gdb_test_no_output "set language auto" + + # We can't rely on uintXX_t being available/known to GDB because + # we may or may not have debug info for those (depending on + # whether we have debug info for the C runtime, for example). + gdb_test_no_output "macro define uint8 unsigned char" + gdb_test "p dataglobal" "= 3" gdb_test "whatis dataglobal" \ "<(data variable|variable), no debug info>|int" @@ -122,17 +204,27 @@ if [runto inner] then { # This test is not as obscure as it might look. `p getenv ("TERM")' # is a real-world example, at least on many systems. + + gdb_test {p/c array_index("abcdef",2)} \ + "'array_index' has unknown return type; cast the call to its declared return type" + gdb_test {ptype array_index("abcdef",2)} \ + "function has unknown return type; cast the call to its declared return type" + gdb_test {whatis array_index("abcdef",2)} \ + "function has unknown return type; cast the call to its declared return type" + if [target_info exists gdb,cannot_call_functions] { - unsupported "p/c array_index(\"abcdef\",2)" + unsupported "p/c (int) array_index(\"abcdef\",2)" } else { # We need to up this because this can be really slow on some boards. # (malloc() is called as part of the test). set prev_timeout $timeout set timeout 60 - gdb_test {p/c array_index("abcdef",2)} " = 99 'c'" + gdb_test {p/c (int) array_index("abcdef",2)} " = 99 'c'" set timeout $prev_timeout } - + + test_call_promotion + # Now, try that we can give names of file-local symbols which happen # to be unique, and have it still work if [runto middle] then { diff --git a/gdb/testsuite/gdb.compile/compile.exp b/gdb/testsuite/gdb.compile/compile.exp index b221870..c23ff6a 100644 --- a/gdb/testsuite/gdb.compile/compile.exp +++ b/gdb/testsuite/gdb.compile/compile.exp @@ -296,12 +296,14 @@ gdb_test "p globalvar" " = 77" "expect 77" # Test reference to minimal_symbol, not (full) symbol. -gdb_test_no_output "compile code globalvar = func_nodebug (75);" \ +gdb_test "compile code globalvar = func_nodebug (75);" \ + "warning: function has unknown return type; assuming int" \ "call func_nodebug" gdb_test "p globalvar" " = -75" "expect -75" -gdb_test_no_output \ - "compile code int (*funcp) (int) = func_nodebug; globalvar = funcp (76);" \ - "call func_nodebug indirectly" +gdb_test \ + "compile code int (*funcp) (int) = func_nodebug; globalvar = funcp (76);" \ + "warning: function has unknown return type; assuming int" \ + "call func_nodebug indirectly" gdb_test "p globalvar" " = -76" "expect -76" diff --git a/gdb/testsuite/gdb.threads/siginfo-threads.exp b/gdb/testsuite/gdb.threads/siginfo-threads.exp index 328168c..8ee4c36 100644 --- a/gdb/testsuite/gdb.threads/siginfo-threads.exp +++ b/gdb/testsuite/gdb.threads/siginfo-threads.exp @@ -40,12 +40,17 @@ gdb_test "handle SIGUSR2 stop print pass" \ gdb_breakpoint [gdb_get_line_number "break-at-exit"] set test "get pid" -gdb_test_multiple "p getpid ()" $test { +set pid "" +gdb_test_multiple "p (int) getpid ()" $test { -re " = (\[0-9\]+)\r\n$gdb_prompt $" { set pid $expect_out(1,string) pass $test } } +if {$pid == ""} { + untested "failed to get pid" + return +} for {set sigcount 0} {$sigcount < 4} {incr sigcount} { set test "catch signal $sigcount" diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 045271a..8e58bf9 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -386,6 +386,14 @@ type_to_string (struct type *type) return {}; } +/* See typeprint.h. */ + +void +type_print_unknown_return_type (struct ui_file *stream) +{ + fprintf_filtered (stream, _("<unknown return type>")); +} + /* Print type of EXP, or last thing in value history if EXP == NULL. show is passed to type_print. */ @@ -757,4 +765,3 @@ val_print_not_associated (struct ui_file *stream) { fprintf_filtered (stream, _("<not associated>")); } - diff --git a/gdb/typeprint.h b/gdb/typeprint.h index 72da7f4..d4e19e5 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -74,6 +74,10 @@ void c_type_print_varspec_suffix (struct type *, struct ui_file *, int, void c_type_print_args (struct type *, struct ui_file *, int, enum language, const struct type_print_options *); +/* Print <unknown return type> to stream STREAM. */ + +void type_print_unknown_return_type (struct ui_file *stream); + extern void val_print_not_allocated (struct ui_file *stream); extern void val_print_not_associated (struct ui_file *stream); diff --git a/gdb/valarith.c b/gdb/valarith.c index 9724aca..bcc5ff6 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -505,7 +505,7 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op, = TYPE_TARGET_TYPE (check_typedef (value_type (argvec[0]))); return value_zero (return_type, VALUE_LVAL (arg1)); } - return call_function_by_hand (argvec[0], 2 - static_memfuncp, + return call_function_by_hand (argvec[0], NULL, 2 - static_memfuncp, argvec + 1); } throw_error (NOT_FOUND_ERROR, @@ -624,7 +624,7 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside) = TYPE_TARGET_TYPE (check_typedef (value_type (argvec[0]))); return value_zero (return_type, VALUE_LVAL (arg1)); } - return call_function_by_hand (argvec[0], nargs, argvec + 1); + return call_function_by_hand (argvec[0], NULL, nargs, argvec + 1); } throw_error (NOT_FOUND_ERROR, _("member function %s not found"), tstr); diff --git a/gdb/valops.c b/gdb/valops.c index c1bb937..f5e3aab 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -192,7 +192,7 @@ value_allocate_space_in_inferior (int len) struct value *blocklen; blocklen = value_from_longest (builtin_type (gdbarch)->builtin_int, len); - val = call_function_by_hand (val, 1, &blocklen); + val = call_function_by_hand (val, NULL, 1, &blocklen); if (value_logical_not (val)) { if (!target_has_execution) |