GNU Binutils with patches for OS216
Révision | ba18742c3a1b62ff218db99bee47bb932af6dab9 (tree) |
---|---|
l'heure | 2018-01-07 23:25:32 |
Auteur | Simon Marchi <simon.marchi@poly...> |
Commiter | Simon Marchi |
C++ify xmethod_worker, get rid of VEC(xmethod_worker_ptr)
The initial goal of this patch was to remove the usage of
VEC(xmethod_worker_ptr) and corresponding cleanups. I ended up having
to C++ify the xmethod_worker code, to be able to have xmethod_workers
free their data in destructors, and therefore be able to use vectors of
xmethod_worker unique_ptr.
The operations in extension_language_ops that act on one instance of
xmethod_worker (get result type, get args type, invoke) are transformed
to methods of xmethod_worker. xmethod_worker becomes an abstract base
class with virtual pure methods which python_xmethod_worker implements.
The only xmethod-related operation left in extension_language_ops is
get_matching_xmethod_workers, which returns a list of xmethod_workers.
The changes are relatively straightforward, but here are some notes on
things that may raise eyebrows:
gdb/ChangeLog:
* extension-priv.h (enum ext_lang_rc): Remove, move to extension.h.
(struct extension_language_ops) <clone_xmethod_worker_data>: Remove.
<free_xmethod_worker_data>: Remove.
<get_matching_xmethod_workers>: Chance VEC to std::vector.
<get_xmethod_arg_types>: Remove.
<get_xmethod_result_type>: Remove.
<invoke_xmethod>: Remove.
* extension.c (new_xmethod_worker): Remove.
(clone_xmethod_worker): Remove.
(get_matching_xmethod_workers): Return void, pass std::vector by
pointer.
(get_xmethod_arg_types): Rename to...
(xmethod_worker::get_arg_types): ... this, and adjust.
(get_xmethod_result_type): Rename to...
(xmethod_worker::get_result_type): ... this, and adjust.
(invoke_xmethod): Remove.
(free_xmethod_worker): Remove.
(free_xmethod_worker_vec): Remove.
* extension.h (enum ext_lang_rc): Move here from
extension-priv.h.
(struct xmethod_worker): Add constructor and destructor.
<data>: Remove.
<value>: Remove.
<invoke, clone, do_get_result_type, do_get_arg_types>: New
virtual pure methods.
<get_arg_types, get_result_type>: New methods.
(xmethod_worker_ptr): Remove typedef.
(DEF_VEC_P (xmethod_worker_ptr)): Remove.
(xmethod_worker_vec): Remove typedef.
(xmethod_worker_up): New typedef.
(invoke_xmethod): Remove.
(clone_xmethod_worker): Remove.
(free_xmethod_worker): Remove.
(free_xmethod_worker_vec): Remove.
(get_xmethod_arg_types): Remove.
(get_xmethod_result_type): Remove.
* valops.c (find_method_list): Use std::vector, don't use
intermediate vector.
(value_find_oload_method_list): Use std::vector.
(find_overload_match): Use std::vector.
(find_oload_champ): Use std::vector.
* value.c (value_free): Use operator delete.
(value_of_xmethod): Rename to...
(value_from_xmethod): ... this. Don't assign
xmethod_worker::value, take rvalue-reference.
(result_type_of_xmethod): Adjust.
(call_xmethod): Adjust.
* value.h: Include extension.h.
(struct xmethod_worker): Don't forward-declare.
(value_of_xmethod): Rename to...
(value_from_xmethod): ... this, take rvalue-reference.
* python/py-xmethods.c (struct gdbpy_worker_data): Rename to...
(struct python_xmethod_worker): ... this, add constructor and
destructor.
<invoke, clone, do_get_arg_types, do_get_result_type>: Implement.
(gdbpy_free_xmethod_worker_data): Rename to...
(python_xmethod_worker::~python_xmethod_worker): ... this and
adjust.
(gdbpy_clone_xmethod_worker_data): Rename to...
(python_xmethod_worker::clone): ... this and adjust.
(gdbpy_get_matching_xmethod_workers): Use std::vector, don't use
temporary vector.
(gdbpy_get_xmethod_arg_types): Rename to...
(python_xmethod_worker::do_get_arg_types): ... this and adjust.
(gdbpy_get_xmethod_result_type): Rename to...
(python_xmethod_worker::do_get_result_type): ... this and
adjust.
(gdbpy_invoke_xmethod): Rename to...
(python_xmethod_worker::invoke): ... this and adjust.
(new_python_xmethod_worker): Rename to...
(python_xmethod_worker::python_xmethod_worker): ... this and
adjust.
* python/python-internal.h (gdbpy_clone_xmethod_worker_data):
Remove.
(gdbpy_free_xmethod_worker_data): Remove.
(gdbpy_get_matching_xmethod_workers): Use std::vector.
(gdbpy_get_xmethod_arg_types): Remove.
(gdbpy_get_xmethod_result_type): Remove.
(gdbpy_invoke_xmethod): Remove.
* python/python.c (python_extension_ops): Remove obsolete
callbacks.
@@ -1,3 +1,87 @@ | ||
1 | +2018-01-07 Simon Marchi <simon.marchi@polymtl.ca> | |
2 | + | |
3 | + * extension-priv.h (enum ext_lang_rc): Remove, move to extension.h. | |
4 | + (struct extension_language_ops) <clone_xmethod_worker_data>: Remove. | |
5 | + <free_xmethod_worker_data>: Remove. | |
6 | + <get_matching_xmethod_workers>: Chance VEC to std::vector. | |
7 | + <get_xmethod_arg_types>: Remove. | |
8 | + <get_xmethod_result_type>: Remove. | |
9 | + <invoke_xmethod>: Remove. | |
10 | + * extension.c (new_xmethod_worker): Remove. | |
11 | + (clone_xmethod_worker): Remove. | |
12 | + (get_matching_xmethod_workers): Return void, pass std::vector by | |
13 | + pointer. | |
14 | + (get_xmethod_arg_types): Rename to... | |
15 | + (xmethod_worker::get_arg_types): ... this, and adjust. | |
16 | + (get_xmethod_result_type): Rename to... | |
17 | + (xmethod_worker::get_result_type): ... this, and adjust. | |
18 | + (invoke_xmethod): Remove. | |
19 | + (free_xmethod_worker): Remove. | |
20 | + (free_xmethod_worker_vec): Remove. | |
21 | + * extension.h (enum ext_lang_rc): Move here from | |
22 | + extension-priv.h. | |
23 | + (struct xmethod_worker): Add constructor and destructor. | |
24 | + <data>: Remove. | |
25 | + <value>: Remove. | |
26 | + <invoke, clone, do_get_result_type, do_get_arg_types>: New | |
27 | + virtual pure methods. | |
28 | + <get_arg_types, get_result_type>: New methods. | |
29 | + (xmethod_worker_ptr): Remove typedef. | |
30 | + (DEF_VEC_P (xmethod_worker_ptr)): Remove. | |
31 | + (xmethod_worker_vec): Remove typedef. | |
32 | + (xmethod_worker_up): New typedef. | |
33 | + (invoke_xmethod): Remove. | |
34 | + (clone_xmethod_worker): Remove. | |
35 | + (free_xmethod_worker): Remove. | |
36 | + (free_xmethod_worker_vec): Remove. | |
37 | + (get_xmethod_arg_types): Remove. | |
38 | + (get_xmethod_result_type): Remove. | |
39 | + * valops.c (find_method_list): Use std::vector, don't use | |
40 | + intermediate vector. | |
41 | + (value_find_oload_method_list): Use std::vector. | |
42 | + (find_overload_match): Use std::vector. | |
43 | + (find_oload_champ): Use std::vector. | |
44 | + * value.c (value_free): Use operator delete. | |
45 | + (value_of_xmethod): Rename to... | |
46 | + (value_from_xmethod): ... this. Don't assign | |
47 | + xmethod_worker::value, take rvalue-reference. | |
48 | + (result_type_of_xmethod): Adjust. | |
49 | + (call_xmethod): Adjust. | |
50 | + * value.h: Include extension.h. | |
51 | + (struct xmethod_worker): Don't forward-declare. | |
52 | + (value_of_xmethod): Rename to... | |
53 | + (value_from_xmethod): ... this, take rvalue-reference. | |
54 | + * python/py-xmethods.c (struct gdbpy_worker_data): Rename to... | |
55 | + (struct python_xmethod_worker): ... this, add constructor and | |
56 | + destructor. | |
57 | + <invoke, clone, do_get_arg_types, do_get_result_type>: Implement. | |
58 | + (gdbpy_free_xmethod_worker_data): Rename to... | |
59 | + (python_xmethod_worker::~python_xmethod_worker): ... this and | |
60 | + adjust. | |
61 | + (gdbpy_clone_xmethod_worker_data): Rename to... | |
62 | + (python_xmethod_worker::clone): ... this and adjust. | |
63 | + (gdbpy_get_matching_xmethod_workers): Use std::vector, don't use | |
64 | + temporary vector. | |
65 | + (gdbpy_get_xmethod_arg_types): Rename to... | |
66 | + (python_xmethod_worker::do_get_arg_types): ... this and adjust. | |
67 | + (gdbpy_get_xmethod_result_type): Rename to... | |
68 | + (python_xmethod_worker::do_get_result_type): ... this and | |
69 | + adjust. | |
70 | + (gdbpy_invoke_xmethod): Rename to... | |
71 | + (python_xmethod_worker::invoke): ... this and adjust. | |
72 | + (new_python_xmethod_worker): Rename to... | |
73 | + (python_xmethod_worker::python_xmethod_worker): ... this and | |
74 | + adjust. | |
75 | + * python/python-internal.h (gdbpy_clone_xmethod_worker_data): | |
76 | + Remove. | |
77 | + (gdbpy_free_xmethod_worker_data): Remove. | |
78 | + (gdbpy_get_matching_xmethod_workers): Use std::vector. | |
79 | + (gdbpy_get_xmethod_arg_types): Remove. | |
80 | + (gdbpy_get_xmethod_result_type): Remove. | |
81 | + (gdbpy_invoke_xmethod): Remove. | |
82 | + * python/python.c (python_extension_ops): Remove obsolete | |
83 | + callbacks. | |
84 | + | |
1 | 85 | 2018-01-05 Pedro Alves <palves@redhat.com> |
2 | 86 | |
3 | 87 | PR gdb/18653 |
@@ -25,26 +25,6 @@ | ||
25 | 25 | #include <signal.h> |
26 | 26 | #include "cli/cli-script.h" |
27 | 27 | |
28 | -/* The return code for some API calls. */ | |
29 | - | |
30 | -enum ext_lang_rc | |
31 | - { | |
32 | - /* The operation completed successfully. */ | |
33 | - EXT_LANG_RC_OK, | |
34 | - | |
35 | - /* The operation was not performed (e.g., no pretty-printer). */ | |
36 | - EXT_LANG_RC_NOP, | |
37 | - | |
38 | - /* There was an error (e.g., Python error while printing a value). | |
39 | - When an error occurs no further extension languages are tried. | |
40 | - This is to preserve existing behaviour, and because it's convenient | |
41 | - for Python developers. | |
42 | - Note: This is different than encountering a memory error trying to read | |
43 | - a value for pretty-printing. Here we're referring to, e.g., programming | |
44 | - errors that trigger an exception in the extension language. */ | |
45 | - EXT_LANG_RC_ERROR | |
46 | - }; | |
47 | - | |
48 | 28 | /* High level description of an extension/scripting language. |
49 | 29 | An entry for each is compiled into GDB regardless of whether the support |
50 | 30 | is present. This is done so that we can issue meaningful errors if the |
@@ -261,63 +241,18 @@ struct extension_language_ops | ||
261 | 241 | enum ext_lang_rc (*before_prompt) (const struct extension_language_defn *, |
262 | 242 | const char *current_gdb_prompt); |
263 | 243 | |
264 | - /* xmethod support: | |
265 | - clone_xmethod_worker_data, free_xmethod_worker_data, | |
266 | - get_matching_xmethod_workers, get_xmethod_arg_types, | |
267 | - get_xmethod_return_type, invoke_xmethod. | |
268 | - These methods are optional and may be NULL, but if one of them is | |
269 | - implemented then they all must be. */ | |
270 | - | |
271 | - /* Clone DATA and return a new but identical xmethod worker data | |
272 | - object for this extension language. */ | |
273 | - void * (*clone_xmethod_worker_data) | |
274 | - (const struct extension_language_defn *extlang, void *data); | |
275 | - | |
276 | - /* Free the DATA object of this extension language. */ | |
277 | - void (*free_xmethod_worker_data) | |
278 | - (const struct extension_language_defn *extlang, void *data); | |
279 | - | |
280 | 244 | /* Return a vector of matching xmethod workers defined in this |
281 | 245 | extension language. The workers service methods with name |
282 | 246 | METHOD_NAME on objects of type OBJ_TYPE. The vector is returned |
283 | - in DM_VEC. */ | |
247 | + in DM_VEC. | |
248 | + | |
249 | + This field may be NULL if the extension language does not support | |
250 | + xmethods. */ | |
284 | 251 | enum ext_lang_rc (*get_matching_xmethod_workers) |
285 | 252 | (const struct extension_language_defn *extlang, |
286 | 253 | struct type *obj_type, |
287 | 254 | const char *method_name, |
288 | - xmethod_worker_vec **dm_vec); | |
289 | - | |
290 | - /* Given a WORKER servicing a particular method, return the types | |
291 | - of the arguments the method takes. The number of arguments is | |
292 | - returned in NARGS, and their types are returned in the array | |
293 | - ARGTYPES. */ | |
294 | - enum ext_lang_rc (*get_xmethod_arg_types) | |
295 | - (const struct extension_language_defn *extlang, | |
296 | - struct xmethod_worker *worker, | |
297 | - int *nargs, | |
298 | - struct type ***arg_types); | |
299 | - | |
300 | - /* Given a WORKER servicing a particular method, fetch the type of the | |
301 | - result of the method. OBJECT, ARGS, NARGS are the same as for | |
302 | - invoke_xmethod. The result type is stored in *RESULT_TYPE. | |
303 | - For backward compatibility with 7.9, which did not support getting the | |
304 | - result type, if the get_result_type operation is not provided by WORKER | |
305 | - then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE. */ | |
306 | - enum ext_lang_rc (*get_xmethod_result_type) | |
307 | - (const struct extension_language_defn *extlang, | |
308 | - struct xmethod_worker *worker, | |
309 | - struct value *object, struct value **args, int nargs, | |
310 | - struct type **result_type); | |
311 | - | |
312 | - /* Invoke the xmethod serviced by WORKER. The xmethod is invoked | |
313 | - on OBJECT with arguments in the array ARGS. NARGS is the length of | |
314 | - this array. Returns the value returned by the xmethod. */ | |
315 | - struct value * (*invoke_xmethod) | |
316 | - (const struct extension_language_defn *extlang, | |
317 | - struct xmethod_worker *worker, | |
318 | - struct value *object, | |
319 | - struct value **args, | |
320 | - int nargs); | |
255 | + std::vector<xmethod_worker_up> *dm_vec); | |
321 | 256 | }; |
322 | 257 | |
323 | 258 | /* State necessary to restore a signal handler to its previous value. */ |
@@ -850,68 +850,18 @@ check_quit_flag (void) | ||
850 | 850 | |
851 | 851 | return result; |
852 | 852 | } |
853 | - | |
854 | -/* xmethod support. */ | |
855 | - | |
856 | -/* The xmethod API routines do not have "ext_lang" in the name because | |
857 | - the name "xmethod" implies that this routine deals with extension | |
858 | - languages. Plus some of the methods take a xmethod_foo * "self/this" | |
859 | - arg, not an extension_language_defn * arg. */ | |
860 | - | |
861 | -/* Returns a new xmethod_worker with EXTLANG and DATA. Space for the | |
862 | - result must be freed with free_xmethod_worker. */ | |
863 | - | |
864 | -struct xmethod_worker * | |
865 | -new_xmethod_worker (const struct extension_language_defn *extlang, void *data) | |
866 | -{ | |
867 | - struct xmethod_worker *worker = XCNEW (struct xmethod_worker); | |
868 | - | |
869 | - worker->extlang = extlang; | |
870 | - worker->data = data; | |
871 | - worker->value = NULL; | |
872 | - | |
873 | - return worker; | |
874 | -} | |
875 | - | |
876 | -/* Clones WORKER and returns a new but identical worker. | |
877 | - The function get_matching_xmethod_workers (see below), returns a | |
878 | - vector of matching workers. If a particular worker is selected by GDB | |
879 | - to invoke a method, then this function can help in cloning the | |
880 | - selected worker and freeing up the vector via a cleanup. | |
881 | - | |
882 | - Space for the result must be freed with free_xmethod_worker. */ | |
883 | - | |
884 | -struct xmethod_worker * | |
885 | -clone_xmethod_worker (struct xmethod_worker *worker) | |
886 | -{ | |
887 | - struct xmethod_worker *new_worker; | |
888 | - const struct extension_language_defn *extlang = worker->extlang; | |
889 | - | |
890 | - gdb_assert (extlang->ops->clone_xmethod_worker_data != NULL); | |
891 | - | |
892 | - new_worker = new_xmethod_worker | |
893 | - (extlang, | |
894 | - extlang->ops->clone_xmethod_worker_data (extlang, worker->data)); | |
895 | 853 | |
896 | - return new_worker; | |
897 | -} | |
898 | - | |
899 | -/* If a method with name METHOD_NAME is to be invoked on an object of type | |
900 | - TYPE, then all entension languages are searched for implementations of | |
901 | - methods with name METHOD. All matches found are returned as a vector | |
902 | - of 'xmethod_worker_ptr' objects. If no matching methods are | |
903 | - found, NULL is returned. */ | |
854 | +/* See extension.h. */ | |
904 | 855 | |
905 | -VEC (xmethod_worker_ptr) * | |
906 | -get_matching_xmethod_workers (struct type *type, const char *method_name) | |
856 | +void | |
857 | +get_matching_xmethod_workers (struct type *type, const char *method_name, | |
858 | + std::vector<xmethod_worker_up> *workers) | |
907 | 859 | { |
908 | - VEC (xmethod_worker_ptr) *workers = NULL; | |
909 | 860 | int i; |
910 | 861 | const struct extension_language_defn *extlang; |
911 | 862 | |
912 | 863 | ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang) |
913 | 864 | { |
914 | - VEC (xmethod_worker_ptr) *lang_workers, *new_vec; | |
915 | 865 | enum ext_lang_rc rc; |
916 | 866 | |
917 | 867 | /* If an extension language does not support xmethods, ignore |
@@ -921,115 +871,45 @@ get_matching_xmethod_workers (struct type *type, const char *method_name) | ||
921 | 871 | |
922 | 872 | rc = extlang->ops->get_matching_xmethod_workers (extlang, |
923 | 873 | type, method_name, |
924 | - &lang_workers); | |
874 | + workers); | |
925 | 875 | if (rc == EXT_LANG_RC_ERROR) |
926 | - { | |
927 | - free_xmethod_worker_vec (workers); | |
928 | - error (_("Error while looking for matching xmethod workers " | |
929 | - "defined in %s."), extlang->capitalized_name); | |
930 | - } | |
931 | - | |
932 | - new_vec = VEC_merge (xmethod_worker_ptr, workers, lang_workers); | |
933 | - /* Free only the vectors and not the elements as NEW_VEC still | |
934 | - contains them. */ | |
935 | - VEC_free (xmethod_worker_ptr, workers); | |
936 | - VEC_free (xmethod_worker_ptr, lang_workers); | |
937 | - workers = new_vec; | |
876 | + error (_("Error while looking for matching xmethod workers " | |
877 | + "defined in %s."), extlang->capitalized_name); | |
938 | 878 | } |
939 | - | |
940 | - return workers; | |
941 | 879 | } |
942 | 880 | |
943 | -/* Return the arg types of the xmethod encapsulated in WORKER. | |
944 | - An array of arg types is returned. The length of the array is returned in | |
945 | - NARGS. The type of the 'this' object is returned as the first element of | |
946 | - array. */ | |
881 | +/* See extension.h. */ | |
947 | 882 | |
948 | -struct type ** | |
949 | -get_xmethod_arg_types (struct xmethod_worker *worker, int *nargs) | |
883 | +type ** | |
884 | +xmethod_worker::get_arg_types (int *nargs) | |
950 | 885 | { |
951 | - enum ext_lang_rc rc; | |
952 | - struct type **type_array = NULL; | |
953 | - const struct extension_language_defn *extlang = worker->extlang; | |
954 | - | |
955 | - gdb_assert (extlang->ops->get_xmethod_arg_types != NULL); | |
886 | + type **type_array = NULL; | |
956 | 887 | |
957 | - rc = extlang->ops->get_xmethod_arg_types (extlang, worker, nargs, | |
958 | - &type_array); | |
888 | + ext_lang_rc rc = do_get_arg_types (nargs, &type_array); | |
959 | 889 | if (rc == EXT_LANG_RC_ERROR) |
960 | - { | |
961 | - error (_("Error while looking for arg types of a xmethod worker " | |
962 | - "defined in %s."), extlang->capitalized_name); | |
963 | - } | |
890 | + error (_("Error while looking for arg types of a xmethod worker " | |
891 | + "defined in %s."), m_extlang->capitalized_name); | |
964 | 892 | |
965 | 893 | return type_array; |
966 | 894 | } |
967 | 895 | |
968 | -/* Return the type of the result of the xmethod encapsulated in WORKER. | |
969 | - OBJECT, ARGS, NARGS are the same as for invoke_xmethod. */ | |
896 | +/* See extension.h. */ | |
970 | 897 | |
971 | 898 | struct type * |
972 | -get_xmethod_result_type (struct xmethod_worker *worker, | |
973 | - struct value *object, struct value **args, int nargs) | |
899 | +xmethod_worker::get_result_type (value *object, value **args, int nargs) | |
974 | 900 | { |
975 | - enum ext_lang_rc rc; | |
976 | - struct type *result_type; | |
977 | - const struct extension_language_defn *extlang = worker->extlang; | |
978 | - | |
979 | - gdb_assert (extlang->ops->get_xmethod_arg_types != NULL); | |
901 | + type *result_type; | |
980 | 902 | |
981 | - rc = extlang->ops->get_xmethod_result_type (extlang, worker, | |
982 | - object, args, nargs, | |
983 | - &result_type); | |
903 | + ext_lang_rc rc = do_get_result_type (object, args, nargs, &result_type); | |
984 | 904 | if (rc == EXT_LANG_RC_ERROR) |
985 | 905 | { |
986 | 906 | error (_("Error while fetching result type of an xmethod worker " |
987 | - "defined in %s."), extlang->capitalized_name); | |
907 | + "defined in %s."), m_extlang->capitalized_name); | |
988 | 908 | } |
989 | 909 | |
990 | 910 | return result_type; |
991 | 911 | } |
992 | 912 | |
993 | -/* Invokes the xmethod encapsulated in WORKER and returns the result. | |
994 | - The method is invoked on OBJ with arguments in the ARGS array. NARGS is | |
995 | - the length of the this array. */ | |
996 | - | |
997 | -struct value * | |
998 | -invoke_xmethod (struct xmethod_worker *worker, struct value *obj, | |
999 | - struct value **args, int nargs) | |
1000 | -{ | |
1001 | - gdb_assert (worker->extlang->ops->invoke_xmethod != NULL); | |
1002 | - | |
1003 | - return worker->extlang->ops->invoke_xmethod (worker->extlang, worker, | |
1004 | - obj, args, nargs); | |
1005 | -} | |
1006 | - | |
1007 | -/* Frees the xmethod worker WORKER. */ | |
1008 | - | |
1009 | -void | |
1010 | -free_xmethod_worker (struct xmethod_worker *worker) | |
1011 | -{ | |
1012 | - gdb_assert (worker->extlang->ops->free_xmethod_worker_data != NULL); | |
1013 | - worker->extlang->ops->free_xmethod_worker_data (worker->extlang, | |
1014 | - worker->data); | |
1015 | - xfree (worker); | |
1016 | -} | |
1017 | - | |
1018 | -/* Frees a vector of xmethod_workers VEC. */ | |
1019 | - | |
1020 | -void | |
1021 | -free_xmethod_worker_vec (void *vec) | |
1022 | -{ | |
1023 | - int i; | |
1024 | - struct xmethod_worker *worker; | |
1025 | - VEC (xmethod_worker_ptr) *v = (VEC (xmethod_worker_ptr) *) vec; | |
1026 | - | |
1027 | - for (i = 0; VEC_iterate (xmethod_worker_ptr, v, i, worker); i++) | |
1028 | - free_xmethod_worker (worker); | |
1029 | - | |
1030 | - VEC_free (xmethod_worker_ptr, v); | |
1031 | -} | |
1032 | - | |
1033 | 913 | /* Called via an observer before gdb prints its prompt. |
1034 | 914 | Iterate over the extension languages giving them a chance to |
1035 | 915 | change the prompt. The first one to change the prompt wins, |
@@ -146,26 +146,85 @@ struct ext_lang_type_printers | ||
146 | 146 | void *py_type_printers; |
147 | 147 | }; |
148 | 148 | |
149 | +/* The return code for some API calls. */ | |
150 | + | |
151 | +enum ext_lang_rc | |
152 | +{ | |
153 | + /* The operation completed successfully. */ | |
154 | + EXT_LANG_RC_OK, | |
155 | + | |
156 | + /* The operation was not performed (e.g., no pretty-printer). */ | |
157 | + EXT_LANG_RC_NOP, | |
158 | + | |
159 | + /* There was an error (e.g., Python error while printing a value). | |
160 | + When an error occurs no further extension languages are tried. | |
161 | + This is to preserve existing behaviour, and because it's convenient | |
162 | + for Python developers. | |
163 | + Note: This is different than encountering a memory error trying to read | |
164 | + a value for pretty-printing. Here we're referring to, e.g., programming | |
165 | + errors that trigger an exception in the extension language. */ | |
166 | + EXT_LANG_RC_ERROR | |
167 | +}; | |
168 | + | |
149 | 169 | /* A type which holds its extension language specific xmethod worker data. */ |
150 | 170 | |
151 | 171 | struct xmethod_worker |
152 | 172 | { |
153 | - /* The language the xmethod worker is implemented in. */ | |
154 | - const struct extension_language_defn *extlang; | |
173 | + xmethod_worker (const extension_language_defn *extlang) | |
174 | + : m_extlang (extlang) | |
175 | + {} | |
176 | + | |
177 | + virtual ~xmethod_worker () = default; | |
178 | + | |
179 | + /* Invoke the xmethod encapsulated in this worker and return the result. | |
180 | + The method is invoked on OBJ with arguments in the ARGS array. NARGS is | |
181 | + the length of the this array. */ | |
182 | + | |
183 | + virtual value *invoke (value *obj, value **args, int nargs) = 0; | |
184 | + | |
185 | + /* Clone this worker, returns a new but identical worker. | |
186 | + The function get_matching_xmethod_workers returns a vector of matching | |
187 | + workers. If a particular worker is selected by GDB to invoke a method, | |
188 | + then this function can help in cloning the selected worker. */ | |
189 | + | |
190 | + virtual std::unique_ptr<xmethod_worker> clone () = 0; | |
191 | + | |
192 | + /* Return the arg types of the xmethod encapsulated in this worker. | |
193 | + An array of arg types is returned. The length of the array is returned in | |
194 | + NARGS. The type of the 'this' object is returned as the first element of | |
195 | + array. */ | |
196 | + | |
197 | + type **get_arg_types (int *nargs); | |
198 | + | |
199 | + /* Return the type of the result of the xmethod encapsulated in this worker. | |
200 | + OBJECT, ARGS, NARGS are the same as for invoke. */ | |
155 | 201 | |
156 | - /* The extension language specific data for this xmethod worker. */ | |
157 | - void *data; | |
202 | + type *get_result_type (value *object, value **args, int nargs); | |
158 | 203 | |
159 | - /* The TYPE_CODE_XMETHOD value corresponding to this worker. | |
160 | - Always use value_of_xmethod to access it. */ | |
161 | - struct value *value; | |
204 | +private: | |
205 | + | |
206 | + /* Return the types of the arguments the method takes. The number of | |
207 | + arguments is returned in NARGS, and their types are returned in the array | |
208 | + ARGTYPES. */ | |
209 | + | |
210 | + virtual enum ext_lang_rc do_get_arg_types | |
211 | + (int *nargs, struct type ***arg_types) = 0; | |
212 | + | |
213 | + /* Fetch the type of the result of the method implemented by this worker. | |
214 | + OBJECT, ARGS, NARGS are the same as for the invoked method. The result | |
215 | + type is stored in *RESULT_TYPE. */ | |
216 | + | |
217 | + virtual enum ext_lang_rc do_get_result_type | |
218 | + (struct value *obj, struct value **args, int nargs, | |
219 | + struct type **result_type_ptr) = 0; | |
220 | + | |
221 | + /* The language the xmethod worker is implemented in. */ | |
222 | + | |
223 | + const extension_language_defn *m_extlang; | |
162 | 224 | }; |
163 | 225 | |
164 | -typedef struct xmethod_worker *xmethod_worker_ptr; | |
165 | -DEF_VEC_P (xmethod_worker_ptr); | |
166 | -typedef VEC (xmethod_worker_ptr) xmethod_worker_vec; | |
226 | +typedef std::unique_ptr<xmethod_worker> xmethod_worker_up; | |
167 | 227 | |
168 | - | |
169 | 228 | /* The interface for gdb's own extension(/scripting) language. */ |
170 | 229 | extern const struct extension_language_defn extension_language_gdb; |
171 | 230 |
@@ -242,26 +301,13 @@ extern const struct extension_language_defn *get_breakpoint_cond_ext_lang | ||
242 | 301 | |
243 | 302 | extern int breakpoint_ext_lang_cond_says_stop (struct breakpoint *); |
244 | 303 | |
245 | -extern struct value *invoke_xmethod (struct xmethod_worker *, | |
246 | - struct value *, | |
247 | - struct value **, int nargs); | |
248 | - | |
249 | -extern struct xmethod_worker *clone_xmethod_worker (struct xmethod_worker *); | |
250 | - | |
251 | -extern struct xmethod_worker *new_xmethod_worker | |
252 | - (const struct extension_language_defn *extlang, void *data); | |
253 | - | |
254 | -extern void free_xmethod_worker (struct xmethod_worker *); | |
255 | - | |
256 | -extern void free_xmethod_worker_vec (void *vec); | |
257 | - | |
258 | -extern xmethod_worker_vec *get_matching_xmethod_workers | |
259 | - (struct type *, const char *); | |
260 | - | |
261 | -extern struct type **get_xmethod_arg_types (struct xmethod_worker *, int *); | |
304 | +/* If a method with name METHOD_NAME is to be invoked on an object of type | |
305 | + TYPE, then all extension languages are searched for implementations of | |
306 | + methods with name METHOD_NAME. All matches found are appended to the WORKERS | |
307 | + vector. */ | |
262 | 308 | |
263 | -extern struct type *get_xmethod_result_type (struct xmethod_worker *, | |
264 | - struct value *object, | |
265 | - struct value **args, int nargs); | |
309 | +extern void get_matching_xmethod_workers | |
310 | + (struct type *type, const char *method_name, | |
311 | + std::vector<xmethod_worker_up> *workers); | |
266 | 312 | |
267 | 313 | #endif /* EXTENSION_H */ |
@@ -37,54 +37,60 @@ static const char matchers_attr_str[] = "xmethods"; | ||
37 | 37 | static PyObject *py_match_method_name = NULL; |
38 | 38 | static PyObject *py_get_arg_types_method_name = NULL; |
39 | 39 | |
40 | -struct gdbpy_worker_data | |
40 | +struct python_xmethod_worker : xmethod_worker | |
41 | 41 | { |
42 | - PyObject *worker; | |
43 | - PyObject *this_type; | |
44 | -}; | |
42 | + python_xmethod_worker (PyObject *worker, PyObject *this_type); | |
43 | + ~python_xmethod_worker (); | |
45 | 44 | |
46 | -static struct xmethod_worker *new_python_xmethod_worker (PyObject *item, | |
47 | - PyObject *py_obj_type); | |
45 | + DISABLE_COPY_AND_ASSIGN (python_xmethod_worker); | |
48 | 46 | |
49 | -/* Implementation of free_xmethod_worker_data for Python. */ | |
47 | + /* Implementation of xmethod_worker::invoke for Python. */ | |
50 | 48 | |
51 | -void | |
52 | -gdbpy_free_xmethod_worker_data (const struct extension_language_defn *extlang, | |
53 | - void *data) | |
54 | -{ | |
55 | - struct gdbpy_worker_data *worker_data = (struct gdbpy_worker_data *) data; | |
49 | + value *invoke (value *obj, value **args, int nargs) override; | |
50 | + | |
51 | + /* Implementation of xmethod_worker::clone for Python. */ | |
52 | + | |
53 | + xmethod_worker_up clone () override; | |
54 | + | |
55 | + /* Implementation of xmethod_worker::do_get_arg_types for Python. */ | |
56 | + | |
57 | + ext_lang_rc do_get_arg_types (int *nargs, type ***arg_types) override; | |
58 | + | |
59 | + /* Implementation of xmethod_worker::do_get_result_type for Python. | |
56 | 60 | |
57 | - gdb_assert (worker_data->worker != NULL && worker_data->this_type != NULL); | |
61 | + For backward compatibility with 7.9, which did not support getting the | |
62 | + result type, if the get_result_type operation is not provided by WORKER | |
63 | + then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE. */ | |
58 | 64 | |
65 | + ext_lang_rc do_get_result_type (value *obj, value **args, int nargs, | |
66 | + type **result_type_ptr) override; | |
67 | + | |
68 | +private: | |
69 | + | |
70 | + PyObject *m_py_worker; | |
71 | + PyObject *m_this_type; | |
72 | +}; | |
73 | + | |
74 | +python_xmethod_worker::~python_xmethod_worker () | |
75 | +{ | |
59 | 76 | /* We don't do much here, but we still need the GIL. */ |
60 | 77 | gdbpy_enter enter_py (get_current_arch (), current_language); |
61 | 78 | |
62 | - Py_DECREF (worker_data->worker); | |
63 | - Py_DECREF (worker_data->this_type); | |
64 | - xfree (worker_data); | |
79 | + Py_DECREF (m_py_worker); | |
80 | + Py_DECREF (m_this_type); | |
65 | 81 | } |
66 | 82 | |
67 | -/* Implementation of clone_xmethod_worker_data for Python. */ | |
83 | +/* See declaration. */ | |
68 | 84 | |
69 | -void * | |
70 | -gdbpy_clone_xmethod_worker_data (const struct extension_language_defn *extlang, | |
71 | - void *data) | |
85 | +xmethod_worker_up | |
86 | +python_xmethod_worker::clone () | |
72 | 87 | { |
73 | - struct gdbpy_worker_data *worker_data | |
74 | - = (struct gdbpy_worker_data *) data, *new_data; | |
75 | - | |
76 | - gdb_assert (worker_data->worker != NULL && worker_data->this_type != NULL); | |
77 | - | |
78 | 88 | /* We don't do much here, but we still need the GIL. */ |
79 | 89 | gdbpy_enter enter_py (get_current_arch (), current_language); |
80 | 90 | |
81 | - new_data = XCNEW (struct gdbpy_worker_data); | |
82 | - new_data->worker = worker_data->worker; | |
83 | - new_data->this_type = worker_data->this_type; | |
84 | - Py_INCREF (new_data->worker); | |
85 | - Py_INCREF (new_data->this_type); | |
91 | + xmethod_worker *worker = new python_xmethod_worker (m_py_worker, m_this_type); | |
86 | 92 | |
87 | - return new_data; | |
93 | + return xmethod_worker_up (worker); | |
88 | 94 | } |
89 | 95 | |
90 | 96 | /* Invoke the "match" method of the MATCHER and return a new reference |
@@ -130,10 +136,9 @@ enum ext_lang_rc | ||
130 | 136 | gdbpy_get_matching_xmethod_workers |
131 | 137 | (const struct extension_language_defn *extlang, |
132 | 138 | struct type *obj_type, const char *method_name, |
133 | - xmethod_worker_vec **dm_vec) | |
139 | + std::vector<xmethod_worker_up> *dm_vec) | |
134 | 140 | { |
135 | 141 | struct objfile *objfile; |
136 | - VEC (xmethod_worker_ptr) *worker_vec = NULL; | |
137 | 142 | PyObject *py_progspace; |
138 | 143 | |
139 | 144 | gdb_assert (obj_type != NULL && method_name != NULL); |
@@ -282,39 +287,33 @@ gdbpy_get_matching_xmethod_workers | ||
282 | 287 | break; |
283 | 288 | } |
284 | 289 | |
285 | - worker = new_python_xmethod_worker (py_worker.get (), | |
290 | + worker = new python_xmethod_worker (py_worker.get (), | |
286 | 291 | py_type.get ()); |
287 | - VEC_safe_push (xmethod_worker_ptr, worker_vec, worker); | |
292 | + | |
293 | + dm_vec->emplace_back (worker); | |
288 | 294 | } |
289 | 295 | } |
290 | 296 | else |
291 | 297 | { |
292 | 298 | struct xmethod_worker *worker; |
293 | 299 | |
294 | - worker = new_python_xmethod_worker (match_result.get (), | |
300 | + worker = new python_xmethod_worker (match_result.get (), | |
295 | 301 | py_type.get ()); |
296 | - VEC_safe_push (xmethod_worker_ptr, worker_vec, worker); | |
302 | + dm_vec->emplace_back (worker); | |
297 | 303 | } |
298 | 304 | } |
299 | 305 | |
300 | - *dm_vec = worker_vec; | |
301 | - | |
302 | 306 | return EXT_LANG_RC_OK; |
303 | 307 | } |
304 | 308 | |
305 | -/* Implementation of get_xmethod_arg_types for Python. */ | |
309 | +/* See declaration. */ | |
306 | 310 | |
307 | -enum ext_lang_rc | |
308 | -gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, | |
309 | - struct xmethod_worker *worker, | |
310 | - int *nargs, struct type ***arg_types) | |
311 | +ext_lang_rc | |
312 | +python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types) | |
311 | 313 | { |
312 | 314 | /* The gdbpy_enter object needs to be placed first, so that it's the last to |
313 | 315 | be destroyed. */ |
314 | 316 | gdbpy_enter enter_py (get_current_arch (), current_language); |
315 | - struct gdbpy_worker_data *worker_data | |
316 | - = (struct gdbpy_worker_data *) worker->data; | |
317 | - PyObject *py_worker = worker_data->worker; | |
318 | 317 | struct type *obj_type; |
319 | 318 | int i = 1, arg_count; |
320 | 319 | gdbpy_ref<> list_iter; |
@@ -324,7 +323,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, | ||
324 | 323 | *nargs = -1; |
325 | 324 | |
326 | 325 | gdbpy_ref<> get_arg_types_method |
327 | - (PyObject_GetAttrString (py_worker, get_arg_types_method_name)); | |
326 | + (PyObject_GetAttrString (m_py_worker, get_arg_types_method_name)); | |
328 | 327 | if (get_arg_types_method == NULL) |
329 | 328 | { |
330 | 329 | gdbpy_print_stack (); |
@@ -332,7 +331,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, | ||
332 | 331 | } |
333 | 332 | |
334 | 333 | gdbpy_ref<> py_argtype_list |
335 | - (PyObject_CallMethodObjArgs (py_worker, py_get_arg_types_method_name, | |
334 | + (PyObject_CallMethodObjArgs (m_py_worker, py_get_arg_types_method_name, | |
336 | 335 | NULL)); |
337 | 336 | if (py_argtype_list == NULL) |
338 | 337 | { |
@@ -418,7 +417,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, | ||
418 | 417 | /* Add the type of 'this' as the first argument. The 'this' pointer should |
419 | 418 | be a 'const' value. Hence, create a 'const' variant of the 'this' pointer |
420 | 419 | type. */ |
421 | - obj_type = type_object_to_type (worker_data->this_type); | |
420 | + obj_type = type_object_to_type (m_this_type); | |
422 | 421 | (type_array.get ())[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type), |
423 | 422 | NULL); |
424 | 423 | *nargs = i; |
@@ -427,18 +426,12 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, | ||
427 | 426 | return EXT_LANG_RC_OK; |
428 | 427 | } |
429 | 428 | |
430 | -/* Implementation of get_xmethod_result_type for Python. */ | |
429 | +/* See declaration. */ | |
431 | 430 | |
432 | -enum ext_lang_rc | |
433 | -gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, | |
434 | - struct xmethod_worker *worker, | |
435 | - struct value *obj, | |
436 | - struct value **args, int nargs, | |
437 | - struct type **result_type_ptr) | |
431 | +ext_lang_rc | |
432 | +python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs, | |
433 | + type **result_type_ptr) | |
438 | 434 | { |
439 | - struct gdbpy_worker_data *worker_data | |
440 | - = (struct gdbpy_worker_data *) worker->data; | |
441 | - PyObject *py_worker = worker_data->worker; | |
442 | 435 | struct type *obj_type, *this_type; |
443 | 436 | int i; |
444 | 437 |
@@ -447,7 +440,7 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, | ||
447 | 440 | /* First see if there is a get_result_type method. |
448 | 441 | If not this could be an old xmethod (pre 7.9.1). */ |
449 | 442 | gdbpy_ref<> get_result_type_method |
450 | - (PyObject_GetAttrString (py_worker, get_result_type_method_name)); | |
443 | + (PyObject_GetAttrString (m_py_worker, get_result_type_method_name)); | |
451 | 444 | if (get_result_type_method == NULL) |
452 | 445 | { |
453 | 446 | PyErr_Clear (); |
@@ -456,7 +449,7 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, | ||
456 | 449 | } |
457 | 450 | |
458 | 451 | obj_type = check_typedef (value_type (obj)); |
459 | - this_type = check_typedef (type_object_to_type (worker_data->this_type)); | |
452 | + this_type = check_typedef (type_object_to_type (m_this_type)); | |
460 | 453 | if (TYPE_CODE (obj_type) == TYPE_CODE_PTR) |
461 | 454 | { |
462 | 455 | struct type *this_ptr = lookup_pointer_type (this_type); |
@@ -528,24 +521,20 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, | ||
528 | 521 | return EXT_LANG_RC_OK; |
529 | 522 | } |
530 | 523 | |
531 | -/* Implementation of invoke_xmethod for Python. */ | |
524 | +/* See declaration. */ | |
532 | 525 | |
533 | 526 | struct value * |
534 | -gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, | |
535 | - struct xmethod_worker *worker, | |
536 | - struct value *obj, struct value **args, int nargs) | |
527 | +python_xmethod_worker::invoke (struct value *obj, struct value **args, | |
528 | + int nargs) | |
537 | 529 | { |
530 | + gdbpy_enter enter_py (get_current_arch (), current_language); | |
531 | + | |
538 | 532 | int i; |
539 | 533 | struct type *obj_type, *this_type; |
540 | 534 | struct value *res = NULL; |
541 | - struct gdbpy_worker_data *worker_data | |
542 | - = (struct gdbpy_worker_data *) worker->data; | |
543 | - PyObject *xmethod_worker = worker_data->worker; | |
544 | - | |
545 | - gdbpy_enter enter_py (get_current_arch (), current_language); | |
546 | 535 | |
547 | 536 | obj_type = check_typedef (value_type (obj)); |
548 | - this_type = check_typedef (type_object_to_type (worker_data->this_type)); | |
537 | + this_type = check_typedef (type_object_to_type (m_this_type)); | |
549 | 538 | if (TYPE_CODE (obj_type) == TYPE_CODE_PTR) |
550 | 539 | { |
551 | 540 | struct type *this_ptr = lookup_pointer_type (this_type); |
@@ -597,7 +586,7 @@ gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, | ||
597 | 586 | PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg); |
598 | 587 | } |
599 | 588 | |
600 | - gdbpy_ref<> py_result (PyObject_CallObject (xmethod_worker, | |
589 | + gdbpy_ref<> py_result (PyObject_CallObject (m_py_worker, | |
601 | 590 | py_arg_tuple.get ())); |
602 | 591 | if (py_result == NULL) |
603 | 592 | { |
@@ -623,24 +612,15 @@ gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, | ||
623 | 612 | return res; |
624 | 613 | } |
625 | 614 | |
626 | -/* Creates a new Python xmethod_worker object. | |
627 | - The new object has data of type 'struct gdbpy_worker_data' composed | |
628 | - with the components PY_WORKER and THIS_TYPE. */ | |
629 | - | |
630 | -static struct xmethod_worker * | |
631 | -new_python_xmethod_worker (PyObject *py_worker, PyObject *this_type) | |
615 | +python_xmethod_worker::python_xmethod_worker (PyObject *py_worker, | |
616 | + PyObject *this_type) | |
617 | +: xmethod_worker (&extension_language_python), | |
618 | + m_py_worker (py_worker), m_this_type (this_type) | |
632 | 619 | { |
633 | - struct gdbpy_worker_data *data; | |
634 | - | |
635 | - gdb_assert (py_worker != NULL && this_type != NULL); | |
620 | + gdb_assert (m_py_worker != NULL && m_this_type != NULL); | |
636 | 621 | |
637 | - data = XCNEW (struct gdbpy_worker_data); | |
638 | - data->worker = py_worker; | |
639 | - data->this_type = this_type; | |
640 | 622 | Py_INCREF (py_worker); |
641 | 623 | Py_INCREF (this_type); |
642 | - | |
643 | - return new_xmethod_worker (&extension_language_python, data); | |
644 | 624 | } |
645 | 625 | |
646 | 626 | int |
@@ -463,28 +463,11 @@ extern enum ext_lang_bp_stop gdbpy_breakpoint_cond_says_stop | ||
463 | 463 | extern int gdbpy_breakpoint_has_cond (const struct extension_language_defn *, |
464 | 464 | struct breakpoint *b); |
465 | 465 | |
466 | -extern void *gdbpy_clone_xmethod_worker_data | |
467 | - (const struct extension_language_defn *extlang, void *data); | |
468 | -extern void gdbpy_free_xmethod_worker_data | |
469 | - (const struct extension_language_defn *extlang, void *data); | |
470 | 466 | extern enum ext_lang_rc gdbpy_get_matching_xmethod_workers |
471 | 467 | (const struct extension_language_defn *extlang, |
472 | 468 | struct type *obj_type, const char *method_name, |
473 | - xmethod_worker_vec **dm_vec); | |
474 | -extern enum ext_lang_rc gdbpy_get_xmethod_arg_types | |
475 | - (const struct extension_language_defn *extlang, | |
476 | - struct xmethod_worker *worker, | |
477 | - int *nargs, | |
478 | - struct type ***arg_types); | |
479 | -extern enum ext_lang_rc gdbpy_get_xmethod_result_type | |
480 | - (const struct extension_language_defn *extlang, | |
481 | - struct xmethod_worker *worker, | |
482 | - struct value *object, struct value **args, int nargs, | |
483 | - struct type **result_type); | |
484 | -extern struct value *gdbpy_invoke_xmethod | |
485 | - (const struct extension_language_defn *extlang, | |
486 | - struct xmethod_worker *worker, | |
487 | - struct value *obj, struct value **args, int nargs); | |
469 | + std::vector<xmethod_worker_up> *dm_vec); | |
470 | + | |
488 | 471 | |
489 | 472 | PyObject *gdbpy_history (PyObject *self, PyObject *args); |
490 | 473 | PyObject *gdbpy_breakpoints (PyObject *, PyObject *); |
@@ -190,12 +190,7 @@ const struct extension_language_ops python_extension_ops = | ||
190 | 190 | |
191 | 191 | gdbpy_before_prompt_hook, |
192 | 192 | |
193 | - gdbpy_clone_xmethod_worker_data, | |
194 | - gdbpy_free_xmethod_worker_data, | |
195 | 193 | gdbpy_get_matching_xmethod_workers, |
196 | - gdbpy_get_xmethod_arg_types, | |
197 | - gdbpy_get_xmethod_result_type, | |
198 | - gdbpy_invoke_xmethod | |
199 | 194 | }; |
200 | 195 | |
201 | 196 | /* Architecture and language to be used in callbacks from |
@@ -68,7 +68,8 @@ int find_oload_champ_namespace_loop (struct value **, int, | ||
68 | 68 | const int no_adl); |
69 | 69 | |
70 | 70 | static int find_oload_champ (struct value **, int, int, |
71 | - struct fn_field *, VEC (xmethod_worker_ptr) *, | |
71 | + struct fn_field *, | |
72 | + const std::vector<xmethod_worker_up> *, | |
72 | 73 | struct symbol **, struct badness_vector **); |
73 | 74 | |
74 | 75 | static int oload_method_static_p (struct fn_field *, int); |
@@ -98,7 +99,7 @@ static struct value *cast_into_complex (struct type *, struct value *); | ||
98 | 99 | |
99 | 100 | static void find_method_list (struct value **, const char *, |
100 | 101 | LONGEST, struct type *, struct fn_field **, int *, |
101 | - VEC (xmethod_worker_ptr) **, | |
102 | + std::vector<xmethod_worker_up> *, | |
102 | 103 | struct type **, LONGEST *); |
103 | 104 | |
104 | 105 | #if 0 |
@@ -2282,12 +2283,11 @@ static void | ||
2282 | 2283 | find_method_list (struct value **argp, const char *method, |
2283 | 2284 | LONGEST offset, struct type *type, |
2284 | 2285 | struct fn_field **fn_list, int *num_fns, |
2285 | - VEC (xmethod_worker_ptr) **xm_worker_vec, | |
2286 | + std::vector<xmethod_worker_up> *xm_worker_vec, | |
2286 | 2287 | struct type **basetype, LONGEST *boffset) |
2287 | 2288 | { |
2288 | 2289 | int i; |
2289 | 2290 | struct fn_field *f = NULL; |
2290 | - VEC (xmethod_worker_ptr) *worker_vec = NULL, *new_vec = NULL; | |
2291 | 2291 | |
2292 | 2292 | gdb_assert (fn_list != NULL && xm_worker_vec != NULL); |
2293 | 2293 | type = check_typedef (type); |
@@ -2328,12 +2328,7 @@ find_method_list (struct value **argp, const char *method, | ||
2328 | 2328 | and hence there is no point restricting them with something like method |
2329 | 2329 | hiding. Moreover, if hiding is done for xmethods as well, then we will |
2330 | 2330 | have to provide a mechanism to un-hide (like the 'using' construct). */ |
2331 | - worker_vec = get_matching_xmethod_workers (type, method); | |
2332 | - new_vec = VEC_merge (xmethod_worker_ptr, *xm_worker_vec, worker_vec); | |
2333 | - | |
2334 | - VEC_free (xmethod_worker_ptr, *xm_worker_vec); | |
2335 | - VEC_free (xmethod_worker_ptr, worker_vec); | |
2336 | - *xm_worker_vec = new_vec; | |
2331 | + get_matching_xmethod_workers (type, method, xm_worker_vec); | |
2337 | 2332 | |
2338 | 2333 | /* If source methods are not found in current class, look for them in the |
2339 | 2334 | base classes. We also have to go through the base classes to gather |
@@ -2382,7 +2377,7 @@ static void | ||
2382 | 2377 | value_find_oload_method_list (struct value **argp, const char *method, |
2383 | 2378 | LONGEST offset, struct fn_field **fn_list, |
2384 | 2379 | int *num_fns, |
2385 | - VEC (xmethod_worker_ptr) **xm_worker_vec, | |
2380 | + std::vector<xmethod_worker_up> *xm_worker_vec, | |
2386 | 2381 | struct type **basetype, LONGEST *boffset) |
2387 | 2382 | { |
2388 | 2383 | struct type *t; |
@@ -2409,7 +2404,7 @@ value_find_oload_method_list (struct value **argp, const char *method, | ||
2409 | 2404 | /* Clear the lists. */ |
2410 | 2405 | *fn_list = NULL; |
2411 | 2406 | *num_fns = 0; |
2412 | - *xm_worker_vec = NULL; | |
2407 | + xm_worker_vec->clear (); | |
2413 | 2408 | |
2414 | 2409 | find_method_list (argp, method, 0, t, fn_list, num_fns, xm_worker_vec, |
2415 | 2410 | basetype, boffset); |
@@ -2488,8 +2483,8 @@ find_overload_match (struct value **args, int nargs, | ||
2488 | 2483 | struct fn_field *fns_ptr = NULL; |
2489 | 2484 | /* For non-methods, the list of overloaded function symbols. */ |
2490 | 2485 | struct symbol **oload_syms = NULL; |
2491 | - /* For xmethods, the VEC of xmethod workers. */ | |
2492 | - VEC (xmethod_worker_ptr) *xm_worker_vec = NULL; | |
2486 | + /* For xmethods, the vector of xmethod workers. */ | |
2487 | + std::vector<xmethod_worker_up> xm_worker_vec; | |
2493 | 2488 | /* Number of overloaded instances being considered. */ |
2494 | 2489 | int num_fns = 0; |
2495 | 2490 | struct type *basetype = NULL; |
@@ -2534,8 +2529,8 @@ find_overload_match (struct value **args, int nargs, | ||
2534 | 2529 | value_find_oload_method_list (&temp, name, 0, &fns_ptr, &num_fns, |
2535 | 2530 | &xm_worker_vec, &basetype, &boffset); |
2536 | 2531 | /* If this is a method only search, and no methods were found |
2537 | - the search has faild. */ | |
2538 | - if (method == METHOD && (!fns_ptr || !num_fns) && !xm_worker_vec) | |
2532 | + the search has failed. */ | |
2533 | + if (method == METHOD && (!fns_ptr || !num_fns) && xm_worker_vec.empty ()) | |
2539 | 2534 | error (_("Couldn't find method %s%s%s"), |
2540 | 2535 | obj_type_name, |
2541 | 2536 | (obj_type_name && *obj_type_name) ? "::" : "", |
@@ -2558,15 +2553,14 @@ find_overload_match (struct value **args, int nargs, | ||
2558 | 2553 | make_cleanup (xfree, src_method_badness); |
2559 | 2554 | } |
2560 | 2555 | |
2561 | - if (VEC_length (xmethod_worker_ptr, xm_worker_vec) > 0) | |
2556 | + if (!xm_worker_vec.empty ()) | |
2562 | 2557 | { |
2563 | 2558 | ext_method_oload_champ = find_oload_champ (args, nargs, |
2564 | - 0, NULL, xm_worker_vec, | |
2559 | + 0, NULL, &xm_worker_vec, | |
2565 | 2560 | NULL, &ext_method_badness); |
2566 | 2561 | ext_method_match_quality = classify_oload_match (ext_method_badness, |
2567 | 2562 | nargs, 0); |
2568 | 2563 | make_cleanup (xfree, ext_method_badness); |
2569 | - make_cleanup (free_xmethod_worker_vec, xm_worker_vec); | |
2570 | 2564 | } |
2571 | 2565 | |
2572 | 2566 | if (src_method_oload_champ >= 0 && ext_method_oload_champ >= 0) |
@@ -2783,11 +2777,8 @@ find_overload_match (struct value **args, int nargs, | ||
2783 | 2777 | basetype, boffset); |
2784 | 2778 | } |
2785 | 2779 | else |
2786 | - { | |
2787 | - *valp = value_of_xmethod (clone_xmethod_worker | |
2788 | - (VEC_index (xmethod_worker_ptr, xm_worker_vec, | |
2789 | - ext_method_oload_champ))); | |
2790 | - } | |
2780 | + *valp = value_from_xmethod | |
2781 | + (xm_worker_vec[ext_method_oload_champ]->clone ()); | |
2791 | 2782 | } |
2792 | 2783 | else |
2793 | 2784 | *symp = oload_syms[func_oload_champ]; |
@@ -2992,12 +2983,11 @@ find_oload_champ_namespace_loop (struct value **args, int nargs, | ||
2992 | 2983 | static int |
2993 | 2984 | find_oload_champ (struct value **args, int nargs, |
2994 | 2985 | int num_fns, struct fn_field *fns_ptr, |
2995 | - VEC (xmethod_worker_ptr) *xm_worker_vec, | |
2986 | + const std::vector<xmethod_worker_up> *xm_worker_vec, | |
2996 | 2987 | struct symbol **oload_syms, |
2997 | 2988 | struct badness_vector **oload_champ_bv) |
2998 | 2989 | { |
2999 | 2990 | int ix; |
3000 | - int fn_count; | |
3001 | 2991 | /* A measure of how good an overloaded instance is. */ |
3002 | 2992 | struct badness_vector *bv; |
3003 | 2993 | /* Index of best overloaded function. */ |
@@ -3014,9 +3004,8 @@ find_oload_champ (struct value **args, int nargs, | ||
3014 | 3004 | |
3015 | 3005 | *oload_champ_bv = NULL; |
3016 | 3006 | |
3017 | - fn_count = (xm_worker_vec != NULL | |
3018 | - ? VEC_length (xmethod_worker_ptr, xm_worker_vec) | |
3019 | - : num_fns); | |
3007 | + int fn_count = xm_worker_vec != NULL ? xm_worker_vec->size () : num_fns; | |
3008 | + | |
3020 | 3009 | /* Consider each candidate in turn. */ |
3021 | 3010 | for (ix = 0; ix < fn_count; ix++) |
3022 | 3011 | { |
@@ -3024,12 +3013,11 @@ find_oload_champ (struct value **args, int nargs, | ||
3024 | 3013 | int static_offset = 0; |
3025 | 3014 | int nparms; |
3026 | 3015 | struct type **parm_types; |
3027 | - struct xmethod_worker *worker = NULL; | |
3028 | 3016 | |
3029 | 3017 | if (xm_worker_vec != NULL) |
3030 | 3018 | { |
3031 | - worker = VEC_index (xmethod_worker_ptr, xm_worker_vec, ix); | |
3032 | - parm_types = get_xmethod_arg_types (worker, &nparms); | |
3019 | + xmethod_worker *worker = (*xm_worker_vec)[ix].get (); | |
3020 | + parm_types = worker->get_arg_types (&nparms); | |
3033 | 3021 | } |
3034 | 3022 | else |
3035 | 3023 | { |
@@ -1627,7 +1627,7 @@ value_free (struct value *val) | ||
1627 | 1627 | funcs->free_closure (val); |
1628 | 1628 | } |
1629 | 1629 | else if (VALUE_LVAL (val) == lval_xcallable) |
1630 | - free_xmethod_worker (val->location.xm_worker); | |
1630 | + delete val->location.xm_worker; | |
1631 | 1631 | |
1632 | 1632 | xfree (val->contents); |
1633 | 1633 | VEC_free (range_s, val->unavailable); |
@@ -2697,23 +2697,20 @@ show_convenience (const char *ignore, int from_tty) | ||
2697 | 2697 | } |
2698 | 2698 | } |
2699 | 2699 | |
2700 | -/* Return the TYPE_CODE_XMETHOD value corresponding to WORKER. */ | |
2700 | + | |
2701 | +/* See value.h. */ | |
2701 | 2702 | |
2702 | 2703 | struct value * |
2703 | -value_of_xmethod (struct xmethod_worker *worker) | |
2704 | +value_from_xmethod (xmethod_worker_up &&worker) | |
2704 | 2705 | { |
2705 | - if (worker->value == NULL) | |
2706 | - { | |
2707 | - struct value *v; | |
2706 | + struct value *v; | |
2708 | 2707 | |
2709 | - v = allocate_value (builtin_type (target_gdbarch ())->xmethod); | |
2710 | - v->lval = lval_xcallable; | |
2711 | - v->location.xm_worker = worker; | |
2712 | - v->modifiable = 0; | |
2713 | - worker->value = v; | |
2714 | - } | |
2708 | + v = allocate_value (builtin_type (target_gdbarch ())->xmethod); | |
2709 | + v->lval = lval_xcallable; | |
2710 | + v->location.xm_worker = worker.release (); | |
2711 | + v->modifiable = 0; | |
2715 | 2712 | |
2716 | - return worker->value; | |
2713 | + return v; | |
2717 | 2714 | } |
2718 | 2715 | |
2719 | 2716 | /* Return the type of the result of TYPE_CODE_XMETHOD value METHOD. */ |
@@ -2724,8 +2721,8 @@ result_type_of_xmethod (struct value *method, int argc, struct value **argv) | ||
2724 | 2721 | gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD |
2725 | 2722 | && method->lval == lval_xcallable && argc > 0); |
2726 | 2723 | |
2727 | - return get_xmethod_result_type (method->location.xm_worker, | |
2728 | - argv[0], argv + 1, argc - 1); | |
2724 | + return method->location.xm_worker->get_result_type | |
2725 | + (argv[0], argv + 1, argc - 1); | |
2729 | 2726 | } |
2730 | 2727 | |
2731 | 2728 | /* Call the xmethod corresponding to the TYPE_CODE_XMETHOD value METHOD. */ |
@@ -2736,8 +2733,7 @@ call_xmethod (struct value *method, int argc, struct value **argv) | ||
2736 | 2733 | gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD |
2737 | 2734 | && method->lval == lval_xcallable && argc > 0); |
2738 | 2735 | |
2739 | - return invoke_xmethod (method->location.xm_worker, | |
2740 | - argv[0], argv + 1, argc - 1); | |
2736 | + return method->location.xm_worker->invoke (argv[0], argv + 1, argc - 1); | |
2741 | 2737 | } |
2742 | 2738 | |
2743 | 2739 | /* Extract a value as a C number (either long or double). |
@@ -21,6 +21,7 @@ | ||
21 | 21 | #define VALUE_H 1 |
22 | 22 | |
23 | 23 | #include "frame.h" /* For struct frame_id. */ |
24 | +#include "extension.h" | |
24 | 25 | |
25 | 26 | struct block; |
26 | 27 | struct expression; |
@@ -30,7 +31,6 @@ struct type; | ||
30 | 31 | struct ui_file; |
31 | 32 | struct language_defn; |
32 | 33 | struct value_print_options; |
33 | -struct xmethod_worker; | |
34 | 34 | |
35 | 35 | /* Values can be partially 'optimized out' and/or 'unavailable'. |
36 | 36 | These are distinct states and have different string representations |
@@ -1158,7 +1158,10 @@ struct value *call_internal_function (struct gdbarch *gdbarch, | ||
1158 | 1158 | |
1159 | 1159 | char *value_internal_function_name (struct value *); |
1160 | 1160 | |
1161 | -extern struct value *value_of_xmethod (struct xmethod_worker *); | |
1161 | +/* Build a value wrapping and representing WORKER. The value takes ownership | |
1162 | + of the xmethod_worker object. */ | |
1163 | + | |
1164 | +extern struct value *value_from_xmethod (xmethod_worker_up &&worker); | |
1162 | 1165 | |
1163 | 1166 | extern struct type *result_type_of_xmethod (struct value *method, |
1164 | 1167 | int argc, struct value **argv); |