diff options
Diffstat (limited to 'libcc1')
-rw-r--r-- | libcc1/libcp1plugin.cc | 582 | ||||
-rw-r--r-- | libcc1/marshall-cp.hh | 72 | ||||
-rw-r--r-- | libcc1/rpc.hh | 39 |
3 files changed, 657 insertions, 36 deletions
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index abe42a0d0c6..dd3bb0e964f 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -61,6 +61,7 @@ #include "diagnostic.h" #include "langhooks.h" #include "langhooks-def.h" +#include "decl.h" #include "callbacks.hh" #include "connection.hh" @@ -271,6 +272,30 @@ plugin_init_extra_pragmas (void *, void *) +static decl_addr_value +build_decl_addr_value (tree decl, gcc_address address) +{ + decl_addr_value value = { + decl, + build_int_cst_type (ptr_type_node, address) + }; + return value; +} + +static decl_addr_value * +record_decl_address (plugin_context *ctx, decl_addr_value value) +{ + decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT); + gcc_assert (*slot == NULL); + *slot + = static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value))); + **slot = value; + /* We don't want GCC to warn about e.g. static functions + without a code definition. */ + TREE_NO_WARNING (value.decl) = 1; + return *slot; +} + // Maybe rewrite a decl to its address. static tree address_rewriter (tree *in, int *walk_subtrees, void *arg) @@ -298,14 +323,8 @@ address_rewriter (tree *in, int *walk_subtrees, void *arg) // Insert the decl into the address map in case it is referenced // again. - value.address = build_int_cst_type (ptr_type_node, address); - decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT); - gcc_assert (*slot == NULL); - *slot - = static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value))); - **slot = value; - TREE_NO_WARNING (value.decl) = 1; - found_value = *slot; + value = build_decl_addr_value (value.decl, address); + found_value = record_decl_address (ctx, value); } else return NULL_TREE; @@ -422,6 +441,7 @@ plugin_get_current_binding_level (cc1_plugin::connection *self) return convert_out (decl); } + gcc_decl plugin_new_decl (cc1_plugin::connection *self, const char *name, @@ -477,10 +497,14 @@ plugin_new_decl (cc1_plugin::connection *self, gcc_assert (!sym_flags); return convert_out (error_mark_node); + /* FIXME: add GCC_CP_SYMBOL_CLASS. */ + default: abort (); } + /* FIXME: check for a template parameter list scope. */ + source_location loc = ctx->get_source_location (filename, line_number); bool class_member_p = at_class_scope_p (); bool ctor = false, dtor = false, assop = false; @@ -886,16 +910,7 @@ plugin_new_decl (cc1_plugin::connection *self, else value.address = NULL; if (value.address) - { - decl_addr_value **slot = ctx->address_map.find_slot (&value, INSERT); - gcc_assert (*slot == NULL); - *slot - = static_cast<decl_addr_value *> (xmalloc (sizeof (decl_addr_value))); - **slot = value; - /* We don't want GCC to warn about e.g. static functions - without a code definition. */ - TREE_NO_WARNING (decl) = 1; - } + record_decl_address (ctx, value); } if (class_member_p) @@ -946,21 +961,10 @@ plugin_build_reference_type (cc1_plugin::connection *, return convert_out (rtype); } -// TYPE_NAME needs to be a valid pointer, even if there is no name available. - static tree -build_named_class_type (enum tree_code code, - const char *name, - const gcc_vbase_array *base_classes, - source_location loc) +start_class_def (tree type, + const gcc_vbase_array *base_classes) { - tree type = make_class_type (code); - tree id = name ? get_identifier (name) : make_anon_name (); - tree type_decl = build_decl (loc, TYPE_DECL, id, type); - TYPE_NAME (type) = type_decl; - TYPE_STUB_DECL (type) = type_decl; - safe_pushtag (id, type, ts_current); - tree bases = NULL; if (base_classes) { @@ -979,6 +983,22 @@ build_named_class_type (enum tree_code code, return type; } +static tree +build_named_class_type (enum tree_code code, + const char *name, + const gcc_vbase_array *base_classes, + source_location loc) +{ + tree type = make_class_type (code); + tree id = name ? get_identifier (name) : make_anon_name (); + tree type_decl = build_decl (loc, TYPE_DECL, id, type); + TYPE_NAME (type) = type_decl; + TYPE_STUB_DECL (type) = type_decl; + safe_pushtag (id, type, ts_current); + + return start_class_def (type, base_classes); +} + gcc_type plugin_start_new_class_type (cc1_plugin::connection *self, const char *name, @@ -1012,13 +1032,12 @@ plugin_start_new_union_type (cc1_plugin::connection *self, int plugin_new_field (cc1_plugin::connection *, - gcc_type record_or_union_type_in, const char *field_name, gcc_type field_type_in, unsigned long bitsize, unsigned long bitpos) { - tree record_or_union_type = convert_in (record_or_union_type_in); + tree record_or_union_type = current_class_type; tree field_type = convert_in (field_type_in); gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (record_or_union_type))); @@ -1058,10 +1077,9 @@ plugin_new_field (cc1_plugin::connection *, int plugin_finish_record_or_union (cc1_plugin::connection *, - gcc_type record_or_union_type_in, unsigned long size_in_bytes) { - tree record_or_union_type = convert_in (record_or_union_type_in); + tree record_or_union_type = current_class_type; gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (record_or_union_type))); @@ -1070,6 +1088,9 @@ plugin_finish_record_or_union (cc1_plugin::connection *, gcc_assert (compare_tree_int (TYPE_SIZE_UNIT (record_or_union_type), size_in_bytes) == 0); + // FIXME: end_template_decl if it's a template? I don't think so, + // we're only defining specializations. -lxo + return 1; } @@ -1246,6 +1267,479 @@ plugin_build_pointer_to_member_type (cc1_plugin::connection *self, return convert_out (ctx->preserve (memptr_type)); } +/* Abuse an unused field of the dummy template parms entry to hold the + parm list. */ +#define TP_PARM_LIST TREE_TYPE (current_template_parms) + +int +plugin_start_new_template_decl (cc1_plugin::connection *self ATTRIBUTE_UNUSED) +{ + begin_template_parm_list (); + + TP_PARM_LIST = NULL_TREE; + + return 0; +} + +gcc_typedecl +plugin_type_decl (cc1_plugin::connection *, + gcc_type type_in) +{ + tree type = convert_in (type_in); + + tree name = TYPE_NAME (type); + gcc_assert (name); + + return convert_out (name); +} + +gcc_typedecl +plugin_new_template_typename_parm (cc1_plugin::connection *self, + const char *id, + int /* bool */ pack_p, + gcc_typedecl default_type, + const char *filename, + unsigned int line_number) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + source_location loc = ctx->get_source_location (filename, line_number); + + tree parm = finish_template_type_parm (class_type_node, get_identifier (id)); + parm = build_tree_list (convert_in (default_type), parm); + + gcc_assert (!(pack_p && default_type)); + + /* Create a type and a decl for the type parm, and add the decl to + TP_PARM_LIST. */ + TP_PARM_LIST = process_template_parm (TP_PARM_LIST, loc, parm, + /* is_non_type = */ false, pack_p); + + /* Return the type of the newly-added parm decl. */ + return convert_out (ctx->preserve (TREE_TYPE (tree_last (TP_PARM_LIST)))); +} + +gcc_utempl +plugin_new_template_template_parm (cc1_plugin::connection *self, + const char *id, + int /* bool */ pack_p, + gcc_utempl default_templ, + const char *filename, + unsigned int line_number) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + source_location loc = ctx->get_source_location (filename, line_number); + + /* Finish the template parm list that started this template parm. */ + end_template_parm_list (TP_PARM_LIST); + + tree parm = finish_template_template_parm (class_type_node, + get_identifier (id)); + parm = build_tree_list (convert_in (default_templ), parm); + + gcc_assert (!(pack_p && default_templ)); + + /* Create a type and a decl for the template parm, and add the decl + to TP_PARM_LIST. */ + TP_PARM_LIST = process_template_parm (TP_PARM_LIST, loc, parm, + /* is_non_type = */ false, pack_p); + + /* Return the decl of the newly-added template template parm. */ + return convert_out (ctx->preserve (tree_last (TP_PARM_LIST))); +} + +gcc_decl +plugin_new_template_value_parm (cc1_plugin::connection *self, + gcc_type type, + const char *id, + gcc_expr default_value, + const char *filename, + unsigned int line_number) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + source_location loc = ctx->get_source_location (filename, line_number); + + cp_declarator declarator; + memset (&declarator, 0, sizeof (declarator)); + // &declarator = make_id_declarator (NULL, get_identifier (id), sfk_none): + declarator.kind = cdk_id; + declarator.u.id.qualifying_scope = NULL; + declarator.u.id.unqualified_name = get_identifier (id); + declarator.u.id.sfk = sfk_none; + + cp_decl_specifier_seq declspec; + memset (&declspec, 0, sizeof (declspec)); + // cp_parser_set_decl_spec_type (&declspec, convert_in (type), -token-, false): + declspec.any_specifiers_p = declspec.any_type_specifiers_p = true; + declspec.type = convert_in (type); + declspec.locations[ds_type_spec] = loc; + + tree parm = grokdeclarator (&declarator, &declspec, TPARM, 0, 0); + parm = build_tree_list (convert_in (default_value), parm); + + /* Create a type and a decl for the template parm, and add the decl + to TP_PARM_LIST. */ + TP_PARM_LIST = process_template_parm (TP_PARM_LIST, loc, parm, + /* is_non_type = */ true, false); + + /* Return the newly-added parm decl. */ + return convert_out (ctx->preserve (tree_last (TP_PARM_LIST))); +} + +static tree +targlist (const gcc_cp_template_args *targs) +{ + int n = targs->n_elements; + tree vec = make_tree_vec (n); + while (n--) + { + switch (targs->kinds[n]) + { + case GCC_CP_TPARG_VALUE: + TREE_VEC_ELT (vec, n) = convert_in (targs->elements[n].value); + break; + case GCC_CP_TPARG_CLASS: + TREE_VEC_ELT (vec, n) = convert_in (targs->elements[n].type); + break; + case GCC_CP_TPARG_TEMPL: + TREE_VEC_ELT (vec, n) = convert_in (targs->elements[n].templ); + break; + case GCC_CP_TPARG_PACK: + TREE_VEC_ELT (vec, n) = convert_in (targs->elements[n].pack); + break; + default: + gcc_unreachable (); + } + } + return vec; +} + +gcc_typedecl +plugin_new_dependent_typename (cc1_plugin::connection *self, + gcc_typedecl enclosing_type, + const char *id, + const gcc_cp_template_args *targs) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree type = convert_in (enclosing_type); + tree name = get_identifier (id); + if (targs) + name = build_min_nt_loc (/*loc=*/0, TEMPLATE_ID_EXPR, + name, targlist (targs)); + tree res = make_typename_type (type, name, typename_type, + /*complain=*/tf_error); + return convert_out (ctx->preserve (res)); +} + +gcc_utempl +plugin_new_dependent_class_template (cc1_plugin::connection *self, + gcc_typedecl enclosing_type, + const char *id) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree type = convert_in (enclosing_type); + tree name = get_identifier (id); + tree res = make_unbound_class_template (type, name, NULL_TREE, + /*complain=*/tf_error); + return convert_out (ctx->preserve (res)); +} + +gcc_typedecl +plugin_new_dependent_typespec (cc1_plugin::connection *self, + gcc_utempl template_decl, + const gcc_cp_template_args *targs) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree type = convert_in (template_decl); + tree decl = finish_template_type (type, targlist (targs), + /*entering_scope=*/false); + return convert_out (ctx->preserve (decl)); +} + +gcc_decl +plugin_new_dependent_value_expr (cc1_plugin::connection *self, + gcc_typedecl enclosing_type, + const char *id, + const gcc_cp_template_args *targs) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree type = convert_in (enclosing_type); + tree name = get_identifier (id); + if (targs) + name = lookup_template_function (name, targlist (targs)); + tree res = build_qualified_name (NULL_TREE, type, name, !!targs); + return convert_out (ctx->preserve (res)); +} + +gcc_expr +plugin_literal_expr (cc1_plugin::connection *self, + gcc_type type, unsigned long value) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree t = convert_in (type); + tree val = build_int_cst_type (t, (unsigned HOST_WIDE_INT) value); + return convert_out (ctx->preserve (val)); +} + +gcc_expr +plugin_decl_expr (cc1_plugin::connection *, gcc_decl decl_in) +{ + tree decl = convert_in (decl_in); + gcc_assert (DECL_P (decl)); + return convert_out (decl); +} + +gcc_expr +plugin_unary_value_expr (cc1_plugin::connection *self, + const char *unary_op, + gcc_expr operand) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree op0 = convert_in (operand); + tree_code opcode = ERROR_MARK; + switch (CHARS2 (unary_op[0], unary_op[1])) + { + case CHARS2 ('p', 's'): // operator + (unary) + opcode = UNARY_PLUS_EXPR; + break; + case CHARS2 ('n', 'g'): // operator - (unary) + opcode = NEGATE_EXPR; + break; + case CHARS2 ('a', 'd'): // operator & (unary) + /* FIXME: how do we distinguish taking the address of a data + member from creating a pointer-to-member value? Both would + take the same decl as the operand, unless we require + different expr codes for e.g. this->member and + class::member. */ + opcode = ADDR_EXPR; + break; + case CHARS2 ('d', 'e'): // operator * (unary) + opcode = INDIRECT_REF; + break; + case CHARS2 ('c', 'o'): // operator ~ + opcode = BIT_NOT_EXPR; + break; + case CHARS2 ('n', 't'): // operator ! + opcode = TRUTH_NOT_EXPR; + break; + /* FIXME: __real__, __imag__. */ + case CHARS2 ('p', 'p'): // operator ++ + case CHARS2 ('m', 'm'): // operator -- + default: + gcc_unreachable (); + } + processing_template_decl++; + tree val = build_x_unary_op (/*loc=*/0, opcode, op0, tf_error); + processing_template_decl--; + return convert_out (ctx->preserve (val)); +} + +gcc_expr +plugin_binary_value_expr (cc1_plugin::connection *self, + const char *binary_op, + gcc_expr operand1, + gcc_expr operand2) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree op0 = convert_in (operand1); + tree op1 = convert_in (operand2); + tree_code opcode = ERROR_MARK; + switch (CHARS2 (binary_op[0], binary_op[1])) + { + case CHARS2 ('p', 'l'): // operator + + opcode = PLUS_EXPR; + break; + case CHARS2 ('m', 'i'): // operator - + opcode = MINUS_EXPR; + break; + case CHARS2 ('m', 'l'): // operator * + opcode = MULT_EXPR; + break; + case CHARS2 ('d', 'v'): // operator / + opcode = TRUNC_DIV_EXPR; + break; + case CHARS2 ('r', 'm'): // operator % + opcode = TRUNC_MOD_EXPR; + break; + case CHARS2 ('a', 'n'): // operator & + opcode = BIT_AND_EXPR; + break; + case CHARS2 ('o', 'r'): // operator | + opcode = BIT_IOR_EXPR; + break; + case CHARS2 ('e', 'o'): // operator ^ + opcode = BIT_XOR_EXPR; + break; + case CHARS2 ('l', 's'): // operator << + opcode = LSHIFT_EXPR; + break; + case CHARS2 ('r', 's'): // operator >> + opcode = RSHIFT_EXPR; + break; + case CHARS2 ('e', 'q'): // operator == + opcode = EQ_EXPR; + break; + case CHARS2 ('n', 'e'): // operator != + opcode = NE_EXPR; + break; + case CHARS2 ('l', 't'): // operator < + opcode = LT_EXPR; + break; + case CHARS2 ('g', 't'): // operator > + opcode = GT_EXPR; + break; + case CHARS2 ('l', 'e'): // operator <= + opcode = LE_EXPR; + break; + case CHARS2 ('g', 'e'): // operator >= + opcode = GE_EXPR; + break; + case CHARS2 ('a', 'a'): // operator && + opcode = TRUTH_ANDIF_EXPR; + break; + case CHARS2 ('o', 'o'): // operator || + opcode = TRUTH_ORIF_EXPR; + break; + case CHARS2 ('c', 'm'): // operator , + opcode = COMPOUND_EXPR; + break; + case CHARS2 ('p', 'm'): // operator ->* + opcode = MEMBER_REF; + break; + case CHARS2 ('p', 't'): // operator -> + opcode = COMPONENT_REF; + break; + case CHARS2 ('i', 'x'): // operator [] + opcode = ARRAY_REF; + break; + default: + gcc_unreachable (); + } + processing_template_decl++; + tree val = build_x_binary_op (/*loc=*/0, opcode, op0, ERROR_MARK, + op1, ERROR_MARK, NULL, tf_error); + processing_template_decl--; + return convert_out (ctx->preserve (val)); +} + +gcc_expr +plugin_ternary_value_expr (cc1_plugin::connection *self, + const char *ternary_op, + gcc_expr operand1, + gcc_expr operand2, + gcc_expr operand3) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree op0 = convert_in (operand1); + tree op1 = convert_in (operand2); + tree op2 = convert_in (operand3); + gcc_assert (CHARS2 (ternary_op[0], ternary_op[1]) + == CHARS2 ('q', 'u')); // ternary operator + processing_template_decl++; + tree val = build_x_conditional_expr (/*loc=*/0, op0, op1, op2, tf_error); + processing_template_decl--; + return convert_out (ctx->preserve (val)); +} + +gcc_expr +plugin_unary_type_expr (cc1_plugin::connection *self, + const char *unary_op, + gcc_typedecl operand) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree type = convert_in (operand); + tree_code opcode = ERROR_MARK; + switch (CHARS2 (unary_op[0], unary_op[1])) + { + /* FIXME: implement sizeof, alignof, ... */ + default: + gcc_unreachable (); + } + processing_template_decl++; + tree val = cxx_sizeof_or_alignof_type (type, opcode, true); + processing_template_decl--; + return convert_out (ctx->preserve (val)); +} + +gcc_expr +plugin_type_value_expr (cc1_plugin::connection *self, + const char *binary_op, + gcc_typedecl operand1, + gcc_expr operand2) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree type = convert_in (operand1); + tree expr = convert_in (operand2); + tree_code opcode = ERROR_MARK; + switch (CHARS2 (binary_op[0], binary_op[1])) + { + /* FIXME: implement type casts, ... */ + default: + gcc_unreachable (); + } + processing_template_decl++; + tree val = NULL_TREE; + processing_template_decl--; + return convert_out (ctx->preserve (val)); +} + +gcc_typedecl +plugin_expr_type (cc1_plugin::connection *, + gcc_expr operand) +{ + tree op0 = convert_in (operand); + tree type = TREE_TYPE (op0); + if (type) + type = TYPE_NAME (type); + return convert_out (type); +} + +gcc_decl +plugin_specialize_function_template (cc1_plugin::connection *self, + gcc_decl template_decl, + const gcc_cp_template_args *targs, + gcc_address address, + const char *filename, + unsigned int line_number) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + source_location loc = ctx->get_source_location (filename, line_number); + tree name = convert_in (template_decl); + tree targsl = targlist (targs); + + tree fnid = lookup_template_function (name, targsl); + if (TREE_CODE (fnid) == TEMPLATE_ID_EXPR) + SET_EXPR_LOCATION (fnid, loc); + + tree decl = tsubst (name, targsl, tf_error, NULL_TREE); + DECL_SOURCE_LOCATION (decl) = loc; + + record_decl_address (ctx, build_decl_addr_value (decl, address)); + + return convert_out (ctx->preserve (decl)); +} + +gcc_type +plugin_start_specialize_class_template (cc1_plugin::connection *self, + gcc_decl template_decl, + const gcc_cp_template_args *args, + const gcc_vbase_array *base_classes, + const char *filename, + unsigned int line_number) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + source_location loc = ctx->get_source_location (filename, line_number); + tree name = convert_in (template_decl); + + // begin_specialization (); // hopefully we don't really need this + + tree tdecl = finish_template_type (name, targlist (args), false);; + DECL_SOURCE_LOCATION (tdecl) = loc; + + tree type = start_class_def (TREE_TYPE (tdecl), base_classes); + + return convert_out (ctx->preserve (type)); +} + gcc_type plugin_int_type (cc1_plugin::connection *self, int is_unsigned, unsigned long size_in_bytes) @@ -1310,6 +1804,24 @@ plugin_build_array_type (cc1_plugin::connection *self, } gcc_type +plugin_build_dependent_array_type (cc1_plugin::connection *self, + gcc_type element_type_in, + gcc_expr num_elements_in) +{ + plugin_context *ctx = static_cast<plugin_context *> (self); + tree element_type = convert_in (element_type_in); + tree size = convert_in (num_elements_in); + tree name = get_identifier ("dependent array type"); + + processing_template_decl++; + tree itype = compute_array_index_type (name, size, tf_error); + tree type = build_cplus_array_type (element_type, itype); + processing_template_decl--; + + return convert_out (ctx->preserve (type)); +} + +gcc_type plugin_build_vla_array_type (cc1_plugin::connection *self, gcc_type element_type_in, const char *upper_bound_name) diff --git a/libcc1/marshall-cp.hh b/libcc1/marshall-cp.hh index 5f6fc65f525..8ce13eed5a7 100644 --- a/libcc1/marshall-cp.hh +++ b/libcc1/marshall-cp.hh @@ -136,6 +136,78 @@ namespace cc1_plugin *result = gva; return OK; } + + // Send a gcc_cp_template_args marker followed by the array. + status + marshall (connection *conn, const gcc_cp_template_args *a) + { + size_t len; + + if (a) + len = a->n_elements; + else + len = (size_t)-1; + + if (!marshall_array_start (conn, 't', len)) + return FAIL; + + if (!a) + return OK; + + if (!marshall_array_elmts (conn, len * sizeof (a->kinds[0]), + a->kinds)) + return FAIL; + + return marshall_array_elmts (conn, len * sizeof (a->elements[0]), + a->elements); + } + + // Read a gcc_vbase_array marker, followed by a gcc_vbase_array. The + // resulting array must be freed by the caller, using 'delete[]' on + // elements and virtualp, and 'delete' on the array object itself. + status + unmarshall (connection *conn, struct gcc_cp_template_args **result) + { + size_t len; + + if (!unmarshall_array_start (conn, 't', &len)) + return FAIL; + + if (len == (size_t)-1) + { + *result = NULL; + return OK; + } + + struct gcc_cp_template_args *gva = new gcc_cp_template_args; + + gva->n_elements = len; + gva->kinds = new char[len]; + + if (!unmarshall_array_elmts (conn, + len * sizeof (gva->kinds[0]), + gva->kinds)) + { + delete[] gva->kinds; + delete gva; + return FAIL; + } + + gva->elements = new gcc_cp_template_arg[len]; + + if (!unmarshall_array_elmts (conn, + len * sizeof (gva->elements[0]), + gva->elements)) + { + delete[] gva->elements; + delete[] gva->kinds; + delete gva; + return FAIL; + } + + *result = gva; + return OK; + } } #endif // CC1_PLUGIN_MARSHALL_CP_HH diff --git a/libcc1/rpc.hh b/libcc1/rpc.hh index be81c49df8b..f9efe04c02e 100644 --- a/libcc1/rpc.hh +++ b/libcc1/rpc.hh @@ -126,7 +126,7 @@ namespace cc1_plugin }; #ifdef GCC_CP_INTERFACE_H - // Specialization for gcc_type_array. + // Specialization for gcc_vbase_array. template<> class argument_wrapper<const gcc_vbase_array *> { @@ -162,6 +162,43 @@ namespace cc1_plugin argument_wrapper (const argument_wrapper &); argument_wrapper &operator= (const argument_wrapper &); }; + + // Specialization for gcc_cp_template_args. + template<> + class argument_wrapper<const gcc_cp_template_args *> + { + public: + argument_wrapper () : m_object (NULL) { } + ~argument_wrapper () + { + // It would be nicer if gcc_type_array could have a destructor. + // But, it is in code shared with gdb and cannot. + if (m_object != NULL) + { + delete[] m_object->elements; + delete[] m_object->kinds; + } + delete m_object; + } + + operator const gcc_cp_template_args * () const + { + return m_object; + } + + status unmarshall (connection *conn) + { + return ::cc1_plugin::unmarshall (conn, &m_object); + } + + private: + + gcc_cp_template_args *m_object; + + // No copying or assignment allowed. + argument_wrapper (const argument_wrapper &); + argument_wrapper &operator= (const argument_wrapper &); + }; #endif /* GCC_CP_INTERFACE_H */ // There are two kinds of template functions here: "call" and |