This is an automated email from the git hooks/post-receive script.
unknown user pushed a commit to branch aoliva/libcp1 in repository gcc.
commit 7b24d7dbc6e5863cb3769ff2fbb0c8dc10d464d0 Author: Alexandre Oliva aoliva@redhat.com Date: Mon Jun 29 06:28:09 2015 -0300
Revamp the libcp1plugin API to support classes and namespaces. --- include/gcc-cp-fe.def | 152 +++++++++++------ include/gcc-cp-interface.h | 57 +++++-- libcc1/libcc1.cc | 14 +- libcc1/libcp1.cc | 14 +- libcc1/libcp1plugin.cc | 403 +++++++++++++++++++++++++++++++++------------ libcc1/marshall-cp.hh | 81 +++++++++ libcc1/marshall.cc | 57 ++++++- libcc1/marshall.hh | 6 + libcc1/names.cc | 20 ++- libcc1/names.hh | 18 +- libcc1/rpc.hh | 39 +++++ 11 files changed, 667 insertions(+), 194 deletions(-)
diff --git a/include/gcc-cp-fe.def b/include/gcc-cp-fe.def index 63b5378..56dc079 100644 --- a/include/gcc-cp-fe.def +++ b/include/gcc-cp-fe.def @@ -19,8 +19,29 @@
-/* Create a new "decl" in GCC. A decl is a declaration, basically a - kind of symbol. +/* Push namespace NAME as the current binding level, to which + newly-introduced decls will be bound. An empty string identifies + the global namespace, whereas NULL identifies an anonymous + namespace. A namespace named NAME is created in the current scope, + if needed. */ + +GCC_METHOD1 (int, push_namespace, + const char *) /* Argument NAME. */ + +// FIXME: inline namespaces, anyone? + +/* Pop the namespace last entered with push_namespace, restoring the + binding level in effect before the matching push_namespace. */ + +GCC_METHOD0 (int, pop_namespace) + +/* Return the NAMESPACE_DECL, TYPE_DECL or FUNCTION_DECL of the + current binding level. */ + +GCC_METHOD0 (gcc_decl, get_current_binding_level) + +/* Create a new "decl" in GCC, and bind it in the current binding + level. A decl is a declaration, basically a kind of symbol.
NAME is the name of the new symbol. SYM_KIND is the kind of symbol being requested. SYM_TYPE is the new symbol's C++ type; @@ -31,82 +52,103 @@ an address (e.g., functions), ADDRESS is the address. FILENAME and LINE_NUMBER refer to the symbol's source location. If this is not known, FILENAME can be NULL and LINE_NUMBER can be 0. - This function returns the new decl. */ - -GCC_METHOD7 (gcc_decl, build_decl, + This function returns the new decl. + + Use this function to register typedefs, functions and variables to + namespace and local binding levels, and typedefs, member functions + (static or not), and static data members to class binding levels. + Note that, since access controls are disabled, we have no means to + express private, protected and public. + + FIXME: we would benefit from a gcc_decl argument, to be able to + introduce friend declarations (what for? we disable access + control), using declarations, using directives and namespace + aliases. + + FIXME: How about override and final virtual functions; =delete and + =default ctor, dtor and copy-assignment declarations; explicit + ctors and conversion operators; thread_local variables; other + attributes? Do we need an extra flags parameter, or just + additional gcc_cp_symbol_kinds? */ + +GCC_METHOD7 (gcc_decl, new_decl, const char *, /* Argument NAME. */ - enum gcc_cp_symbol_kind,/* Argument SYM_KIND. */ + enum gcc_cp_symbol_kind, /* Argument SYM_KIND. */ gcc_type, /* Argument SYM_TYPE. */ const char *, /* Argument SUBSTITUTION_NAME. */ gcc_address, /* Argument ADDRESS. */ const char *, /* Argument FILENAME. */ unsigned int) /* Argument LINE_NUMBER. */
-/* Insert a GCC decl into the symbol table. DECL is the decl to - insert. IS_GLOBAL is true if this is an outermost binding, and - false if it is a possibly-shadowing binding. */ +/* Return the type of a pointer to a given base type. */
-GCC_METHOD2 (int /* bool */, bind, - gcc_decl, /* Argument DECL. */ - int /* bool */) /* Argument IS_GLOBAL. */ -/* FIXME: do we want a namespace instead of IS_GLOBAL? */ +GCC_METHOD1 (gcc_type, build_pointer_type, + gcc_type) /* Argument BASE_TYPE. */
-/* Insert a tagged type into the symbol table. NAME is the tag name - of the type and TAGGED_TYPE is the type itself. TAGGED_TYPE must - be either a struct, union, or enum type, as these are the only - types that have tags. FILENAME and LINE_NUMBER refer to the type's - source location. If this is not known, FILENAME can be NULL and - LINE_NUMBER can be 0. */ +// FIXME: we need reference types and pointer-to-member types.
-GCC_METHOD4 (int /* bool */, tagbind, +/* Create a new 'class' (or 'struct') type, record it in the current + binding level, and enter its own binding level. Initially it has + no fields. + + NAME is the class name. BASE_CLASSES indicate the base classes of + class NAME. FILENAME and LINE_NUMBER specify the source location + associated with the class. */ + +GCC_METHOD4 (gcc_type, start_new_class_type, const char *, /* Argument NAME. */ - gcc_type, /* Argument TAGGED_TYPE. */ + const struct gcc_vbase_array *,/* Argument BASE_CLASSES. */ const char *, /* Argument FILENAME. */ unsigned int) /* Argument LINE_NUMBER. */
-/* Return the type of a pointer to a given base type. */ - -GCC_METHOD1 (gcc_type, build_pointer_type, - gcc_type) /* Argument BASE_TYPE. */ +// FIXME: do we need a flag to distinguish structs and classes? This +// would be beneficial at least for error messages.
-/* Create a new 'struct' type. Initially it has no fields. */ +/* Create a new 'union' type, record it in the current binding level, + and enter its own binding level. Initially it has no fields.
-GCC_METHOD0 (gcc_type, build_record_type) + NAME is the union name. FILENAME and LINE_NUMBER specify its + source location. */
-/* Create a new 'union' type. Initially it has no fields. */ +GCC_METHOD3 (gcc_type, start_new_union_type, + const char *, /* Argument NAME. */ + const char *, /* Argument FILENAME. */ + unsigned int) /* Argument LINE_NUMBER. */
-GCC_METHOD0 (gcc_type, build_union_type) +/* Add a non-static data member to a struct or union type. FIELD_NAME + is the field's name. FIELD_TYPE is the type of the field. BITSIZE + and BITPOS indicate where in the struct the field occurs.
-/* Add a field to a struct or union type. FIELD_NAME is the field's - name. FIELD_TYPE is the type of the field. BITSIZE and BITPOS - indicate where in the struct the field occurs. */ + FIXME: how about mutable data members? */
-GCC_METHOD5 (int /* bool */, build_add_field, +GCC_METHOD5 (int /* bool */, new_field, gcc_type, /* Argument RECORD_OR_UNION_TYPE. */ const char *, /* Argument FIELD_NAME. */ gcc_type, /* Argument FIELD_TYPE. */ unsigned long, /* Argument BITSIZE. */ unsigned long) /* Argument BITPOS. */ -/* FIXME: can we use the above for member functions, particularly - virtual ones? */ - -/* FIXME: we need some means to add base classes. */ - -/* FIXME: we need some means to introduce namespaces. */
-/* After all the fields have been added to a struct or union, the - struct or union type must be "finished". This does some final - cleanups in GCC. */ +/* After all the fields have been added to a struct, class or union, + the struct or union type must be "finished". This does some final + cleanups in GCC, and pops to the binding level that was in effect + before the matching build_class_type or build_union_type. */
GCC_METHOD2 (int /* bool */, finish_record_or_union, gcc_type, /* Argument RECORD_OR_UNION_TYPE. */ unsigned long) /* Argument SIZE_IN_BYTES. */
-/* Create a new 'enum' type. The new type initially has no - associated constants. */ +/* Create a new 'enum' type, and record it in the current binding + level. The new type initially has no associated constants.
-GCC_METHOD1 (gcc_type, build_enum_type, - gcc_type) /* Argument UNDERLYING_INT_TYPE. */ + NAME is the enum name. FILENAME and LINE_NUMBER specify its source + location. */ + +GCC_METHOD5 (gcc_type, start_new_enum_type, + const char *, /* Argument NAME. */ + gcc_type, /* Argument UNDERLYING_INT_TYPE. */ + int /* bool */, /* Argument SCOPED_ENUM_P. */ + const char *, /* Argument FILENAME. */ + unsigned int) /* Argument LINE_NUMBER. */
/* Add a new constant to an enum type. NAME is the constant's name and VALUE is its value. */ @@ -129,13 +171,25 @@ GCC_METHOD1 (int /* bool */, finish_enum_type,
GCC_METHOD3 (gcc_type, build_function_type, gcc_type, /* Argument RETURN_TYPE. */ - const struct gcc_type_array *, /* Argument ARGUMENT_TYPES. */ - int /* bool */) /* Argument IS_VARARGS. */ + const struct gcc_type_array *,/* Argument ARGUMENT_TYPES. */ + int /* bool */) /* Argument IS_VARARGS. */ + +/* Create a new non-static member function type. FUNC_TYPE is the + method prototype, without the implicit THIS pointer, added as a + pointer to the QUALS-qualified CLASS_TYPE. */ + +GCC_METHOD4 (gcc_type, build_method_type, + gcc_type, /* Argument CLASS_TYPE. */ + gcc_type, /* Argument FUNC_TYPE. */ + enum gcc_cp_qualifiers, /* Argument QUALS. */ + enum gcc_cp_ref_qualifiers) /* Argument RQUALS. */ + +// FIXME: add a type-variant builder to add exception type specifiers.
/* Return an integer type with the given properties. */
GCC_METHOD2 (gcc_type, int_type, - int /* bool */, /* Argument IS_UNSIGNED. */ + int /* bool */, /* Argument IS_UNSIGNED. */ unsigned long) /* Argument SIZE_IN_BYTES. */
/* Return a floating point type with the given properties. */ diff --git a/include/gcc-cp-interface.h b/include/gcc-cp-interface.h index 264a56c..a4b3be0 100644 --- a/include/gcc-cp-interface.h +++ b/include/gcc-cp-interface.h @@ -34,14 +34,14 @@ extern "C" { struct gcc_cp_context;
/* - * Definitions and declarations for the C front end. + * Definitions and declarations for the C++ front end. */
-/* Defined versions of the C front-end API. */ +/* Defined versions of the C++ front-end API. */
enum gcc_cp_api_version { - GCC_CP_FE_VERSION_0 = 1 + GCC_CP_FE_VERSION_0 = 0xffffffff-1 };
/* Qualifiers. */ @@ -53,6 +53,32 @@ enum gcc_cp_qualifiers GCC_CP_QUALIFIER_RESTRICT = 4 };
+/* Ref qualifiers. */ + +enum gcc_cp_ref_qualifiers { + GCC_CP_REF_QUAL_NONE = 0, + GCC_CP_REF_QUAL_LVALUE = 1, + GCC_CP_REF_QUAL_RVALUE = 2 +}; + +/* An array of types used for creating lists of base classes. */ + +struct gcc_vbase_array +{ + /* Number of elements. */ + + int n_elements; + + /* The base classes. */ + + gcc_type *elements; + + /* Indicate virtual base classes. + Take elements[i] as a virtual base class iff virtualp[i]. */ + + char /* bool */ *virtualp; +}; + /* This enumerates the kinds of decls that GDB can create. */
enum gcc_cp_symbol_kind @@ -71,7 +97,14 @@ enum gcc_cp_symbol_kind
/* A label. */
- GCC_CP_SYMBOL_LABEL + GCC_CP_SYMBOL_LABEL, + + /* A virtual member function. */ + + GCC_CP_SYMBOL_VIRTUAL_FUNCTION + + // FIXME: should we have separate symbol kinds for operator + // functions, ctors, dtors, vtables, rtti, etc? };
/* This enumerates the types of symbols that GCC might request from @@ -80,11 +113,13 @@ enum gcc_cp_symbol_kind enum gcc_cp_oracle_request { /* An ordinary symbol -- a variable, function, typedef, or enum - constant. */ + constant. All namespace-scoped symbols with the requested name + should be defined in response to this request. */
GCC_CP_ORACLE_SYMBOL,
- /* A struct, union, or enum tag. */ + /* A struct, union, or enum tag. All members of the tagged type + should be defined in response to this request. */
GCC_CP_ORACLE_TAG,
@@ -100,16 +135,16 @@ enum gcc_cp_oracle_request being requested, and IDENTIFIER is the name of the symbol. */
typedef void gcc_cp_oracle_function (void *datum, - struct gcc_cp_context *context, - enum gcc_cp_oracle_request request, - const char *identifier); + struct gcc_cp_context *context, + enum gcc_cp_oracle_request request, + const char *identifier);
/* The type of the function called by GCC to ask GDB for a symbol's address. This should return 0 if the address is not known. */
typedef gcc_address gcc_cp_symbol_address_function (void *datum, - struct gcc_cp_context *ctxt, - const char *identifier); + struct gcc_cp_context *ctxt, + const char *identifier);
/* The vtable used by the C front end. */
diff --git a/libcc1/libcc1.cc b/libcc1/libcc1.cc index 9db9624..efbd711 100644 --- a/libcc1/libcc1.cc +++ b/libcc1/libcc1.cc @@ -249,19 +249,19 @@ static const struct gcc_c_fe_vtable c_vtable = set_callbacks,
#define GCC_METHOD0(R, N) \ - rpc<R, cc1_plugin::N>, + rpc<R, cc1_plugin::c::N>, #define GCC_METHOD1(R, N, A) \ - rpc<R, cc1_plugin::N, A>, + rpc<R, cc1_plugin::c::N, A>, #define GCC_METHOD2(R, N, A, B) \ - rpc<R, cc1_plugin::N, A, B>, + rpc<R, cc1_plugin::c::N, A, B>, #define GCC_METHOD3(R, N, A, B, C) \ - rpc<R, cc1_plugin::N, A, B, C>, + rpc<R, cc1_plugin::c::N, A, B, C>, #define GCC_METHOD4(R, N, A, B, C, D) \ - rpc<R, cc1_plugin::N, A, B, C, D>, + rpc<R, cc1_plugin::c::N, A, B, C, D>, #define GCC_METHOD5(R, N, A, B, C, D, E) \ - rpc<R, cc1_plugin::N, A, B, C, D, E>, + rpc<R, cc1_plugin::c::N, A, B, C, D, E>, #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ - rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>, + rpc<R, cc1_plugin::c::N, A, B, C, D, E, F, G>,
#include "gcc-c-fe.def"
diff --git a/libcc1/libcp1.cc b/libcc1/libcp1.cc index 4ee5825..3827be3 100644 --- a/libcc1/libcp1.cc +++ b/libcc1/libcp1.cc @@ -249,19 +249,19 @@ static const struct gcc_cp_fe_vtable cp_vtable = set_callbacks,
#define GCC_METHOD0(R, N) \ - rpc<R, cc1_plugin::N>, + rpc<R, cc1_plugin::cp::N>, #define GCC_METHOD1(R, N, A) \ - rpc<R, cc1_plugin::N, A>, + rpc<R, cc1_plugin::cp::N, A>, #define GCC_METHOD2(R, N, A, B) \ - rpc<R, cc1_plugin::N, A, B>, + rpc<R, cc1_plugin::cp::N, A, B>, #define GCC_METHOD3(R, N, A, B, C) \ - rpc<R, cc1_plugin::N, A, B, C>, + rpc<R, cc1_plugin::cp::N, A, B, C>, #define GCC_METHOD4(R, N, A, B, C, D) \ - rpc<R, cc1_plugin::N, A, B, C, D>, + rpc<R, cc1_plugin::cp::N, A, B, C, D>, #define GCC_METHOD5(R, N, A, B, C, D, E) \ - rpc<R, cc1_plugin::N, A, B, C, D, E>, + rpc<R, cc1_plugin::cp::N, A, B, C, D, E>, #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ - rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>, + rpc<R, cc1_plugin::cp::N, A, B, C, D, E, F, G>,
#include "gcc-cp-fe.def"
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index 9acfe16..173b21d 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -348,15 +348,93 @@ rewrite_decls_to_addresses (void *function_in, void *)
+static inline tree +safe_pushtag (tree name, tree type, tag_scope scope) +{ + void (*save_oracle) (enum cp_oracle_request, tree identifier); + + save_oracle = cp_binding_oracle; + cp_binding_oracle = NULL; + + tree ret = pushtag (name, type, scope); + + cp_binding_oracle = save_oracle; + + return ret; +} + +static inline tree +safe_pushdecl_maybe_friend (tree decl, bool is_friend) +{ + void (*save_oracle) (enum cp_oracle_request, tree identifier); + + save_oracle = cp_binding_oracle; + cp_binding_oracle = NULL; + + tree ret = pushdecl_maybe_friend (decl, is_friend); + + cp_binding_oracle = save_oracle; + + return ret; +} + + + +int +plugin_push_namespace (cc1_plugin::connection *self, + const char *name) +{ + (void)self; + + if (name && !*name) + push_to_top_level (); + else + push_namespace (name ? get_identifier (name) : NULL); + + return 0; +} + +int +plugin_pop_namespace (cc1_plugin::connection *self) +{ + (void)self; + + if (toplevel_bindings_p () && current_namespace == global_namespace) + pop_from_top_level (); + else + pop_namespace (); + + return 0; +} + +gcc_decl +plugin_get_current_binding_level (cc1_plugin::connection *self) +{ + (void)self; + + tree decl; + + if (current_class_type) + decl = TYPE_NAME (current_class_type); + else if (current_function_decl) + decl = current_function_decl; + else if (toplevel_bindings_p ()) + decl = current_namespace; + else + gcc_unreachable (); + + return convert_out (decl); +} + gcc_decl -plugin_build_decl (cc1_plugin::connection *self, - const char *name, - enum gcc_cp_symbol_kind sym_kind, - gcc_type sym_type_in, - const char *substitution_name, - gcc_address address, - const char *filename, - unsigned int line_number) +plugin_new_decl (cc1_plugin::connection *self, + const char *name, + enum gcc_cp_symbol_kind sym_kind, + gcc_type sym_type_in, + const char *substitution_name, + gcc_address address, + const char *filename, + unsigned int line_number) { plugin_context *ctx = static_cast<plugin_context *> (self); { // FIXME in gdb: @@ -438,64 +516,11 @@ plugin_build_decl (cc1_plugin::connection *self, **slot = value; }
- return convert_out (ctx->preserve (decl)); -} - -int -plugin_bind (cc1_plugin::connection *, - gcc_decl decl_in, int is_global) -{ - tree decl = convert_in (decl_in); - - if (is_global) - push_nested_namespace (global_namespace); + decl = safe_pushdecl_maybe_friend (decl, false);
- pushdecl_maybe_friend (decl, false); + rest_of_decl_compilation (decl, toplevel_bindings_p (), 0);
- if (is_global) - pop_nested_namespace (global_namespace); - - rest_of_decl_compilation (decl, is_global, 0); - return 1; -} - -// g++ really wants types to have names, even when they're anonymous. -// FIXME: we can't tell actual anonymous types. We should have type -// names specified earlier, otherwise we'll create wrong bindings -// within class defs. Maybe have a separate call to set scope, name -// and base classes wouldn't be a bad idea. - -static tree -get_placeholder_identifier () -{ - static tree name_placeholder; - if (!name_placeholder) - name_placeholder = get_identifier ("name placeholder"); - return name_placeholder; -} - -void -cp_pushtag (location_t loc, tree name, tree type) -{ - tree decl = TYPE_NAME (type); - DECL_SOURCE_LOCATION (decl) = loc; - gcc_assert (DECL_NAME (decl) == name - || DECL_NAME (decl) == get_placeholder_identifier ()); - DECL_NAME (decl) = name; // FIXME: drop name_placeholder - pushtag (name, type, ts_global); -} - -int -plugin_tagbind (cc1_plugin::connection *self, - const char *name, gcc_type tagged_type, - const char *filename, unsigned int line_number) -{ - plugin_context *ctx = static_cast<plugin_context *> (self); - push_nested_namespace (global_namespace); // FIXME - cp_pushtag (ctx->get_source_location (filename, line_number), - get_identifier (name), convert_in (tagged_type)); - pop_nested_namespace (global_namespace); // FIXME - return 1; + return convert_out (ctx->preserve (decl)); }
gcc_type @@ -509,41 +534,74 @@ plugin_build_pointer_type (cc1_plugin::connection *, // 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) +build_named_class_type (enum tree_code code, + const char *name, + const gcc_vbase_array *base_classes, + source_location loc) { - tree node; - push_nested_namespace (global_namespace); // FIXME - node = make_class_type (code); - tree type_decl = build_decl (input_location, TYPE_DECL, - get_placeholder_identifier (), node); - TYPE_NAME (node) = type_decl; - TYPE_STUB_DECL (node) = type_decl; - xref_basetypes (node, NULL); - begin_class_definition (node); - return node; + 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) + { + for (int i = 0; i < base_classes->n_elements; i++) + { + tree base = finish_base_specifier + (convert_in (base_classes->elements[i]), + access_default_node, base_classes->virtualp[i]); + TREE_CHAIN (base) = bases; + bases = base; + } + bases = nreverse (bases); + } + xref_basetypes (type, bases); + begin_class_definition (type); + return type; }
gcc_type -plugin_build_record_type (cc1_plugin::connection *self) +plugin_start_new_class_type (cc1_plugin::connection *self, + const char *name, + const gcc_vbase_array *base_classes, + const char *filename, + unsigned int line_number) { plugin_context *ctx = static_cast<plugin_context *> (self); - return convert_out (ctx->preserve (build_named_class_type (RECORD_TYPE))); + + tree type = build_named_class_type (RECORD_TYPE, name, base_classes, + ctx->get_source_location (filename, + line_number)); + + return convert_out (ctx->preserve (type)); }
gcc_type -plugin_build_union_type (cc1_plugin::connection *self) +plugin_start_new_union_type (cc1_plugin::connection *self, + const char *name, + const char *filename, + unsigned int line_number) { plugin_context *ctx = static_cast<plugin_context *> (self); - return convert_out (ctx->preserve (build_named_class_type (UNION_TYPE))); + + tree type = build_named_class_type (UNION_TYPE, name, NULL, + ctx->get_source_location (filename, + line_number)); + + return convert_out (ctx->preserve (type)); }
int -plugin_build_add_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) +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 field_type = convert_in (field_type_in); @@ -580,9 +638,6 @@ plugin_build_add_field (cc1_plugin::connection *, DECL_CHAIN (decl) = TYPE_FIELDS (record_or_union_type); TYPE_FIELDS (record_or_union_type) = decl;
- // Now we may have to retrofit the newly-added binding into the - // active bindings. - return 1; }
@@ -597,8 +652,6 @@ plugin_finish_record_or_union (cc1_plugin::connection *,
finish_struct (record_or_union_type, NULL);
- pop_nested_namespace (global_namespace); // FIXME - gcc_assert (compare_tree_int (TYPE_SIZE_UNIT (record_or_union_type), size_in_bytes) == 0);
@@ -606,26 +659,36 @@ plugin_finish_record_or_union (cc1_plugin::connection *, }
gcc_type -plugin_build_enum_type (cc1_plugin::connection *self, - gcc_type underlying_int_type_in) +plugin_start_new_enum_type (cc1_plugin::connection *self, + const char *name, + gcc_type underlying_int_type_in, + int scoped_enum_p, + const char *filename, + unsigned int line_number) { + plugin_context *ctx = static_cast<plugin_context *> (self); tree underlying_int_type = convert_in (underlying_int_type_in);
if (underlying_int_type == error_mark_node) return convert_out (error_mark_node);
bool is_new_type = false; - bool scoped_enum_p = false; // FIXME
- push_nested_namespace (global_namespace); // FIXME + tree id = name ? get_identifier (name) : make_anon_name ();
- tree result = start_enum (get_placeholder_identifier (), NULL_TREE, - underlying_int_type, scoped_enum_p, &is_new_type); + tree type = start_enum (id, NULL_TREE, + underlying_int_type, !!scoped_enum_p, &is_new_type);
gcc_assert (is_new_type);
- plugin_context *ctx = static_cast<plugin_context *> (self); - return convert_out (ctx->preserve (result)); + source_location loc = ctx->get_source_location (filename, line_number); + tree type_decl = build_decl (loc, TYPE_DECL, id, type); + TYPE_NAME (type) = type_decl; + TYPE_STUB_DECL (type) = type_decl; + + safe_pushtag (DECL_NAME (type_decl), type, ts_current); + + return convert_out (ctx->preserve (type)); }
int @@ -653,8 +716,6 @@ plugin_finish_enum_type (cc1_plugin::connection *, finish_enum_value_list (enum_type); finish_enum (enum_type);
- pop_nested_namespace (global_namespace); // FIXME - return 1; }
@@ -688,6 +749,45 @@ plugin_build_function_type (cc1_plugin::connection *self, }
gcc_type +plugin_build_method_type (cc1_plugin::connection *self, + gcc_type class_type_in, + gcc_type func_type_in, + enum gcc_cp_qualifiers quals_in, + enum gcc_cp_ref_qualifiers rquals_in) +{ + tree class_type = convert_in (class_type_in); + tree func_type = convert_in (func_type_in); + cp_cv_quals quals = 0; + cp_ref_qualifier rquals; + + if ((quals_in & GCC_CP_QUALIFIER_CONST) != 0) + quals |= TYPE_QUAL_CONST; + if ((quals_in & GCC_CP_QUALIFIER_VOLATILE) != 0) + quals |= TYPE_QUAL_VOLATILE; + gcc_assert ((quals_in & GCC_CP_QUALIFIER_RESTRICT) == 0); + + switch (rquals_in) + { + case GCC_CP_REF_QUAL_NONE: + rquals = REF_QUAL_NONE; + break; + case GCC_CP_REF_QUAL_LVALUE: + rquals = REF_QUAL_LVALUE; + break; + case GCC_CP_REF_QUAL_RVALUE: + rquals = REF_QUAL_RVALUE; + break; + default: + gcc_unreachable (); + } + + tree method_type = build_memfn_type (class_type, func_type, quals, rquals); + + plugin_context *ctx = static_cast<plugin_context *> (self); + return convert_out (ctx->preserve (method_type)); +} + +gcc_type plugin_int_type (cc1_plugin::connection *self, int is_unsigned, unsigned long size_in_bytes) { @@ -768,7 +868,7 @@ plugin_build_qualified_type (cc1_plugin::connection *, enum gcc_cp_qualifiers qualifiers) { tree unqualified_type = convert_in (unqualified_type_in); - int quals = 0; + cp_cv_quals quals = 0;
if ((qualifiers & GCC_CP_QUALIFIER_CONST) != 0) quals |= TYPE_QUAL_CONST; @@ -814,7 +914,7 @@ plugin_build_constant (cc1_plugin::connection *self, gcc_type type_in, TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; cp_finish_decl (decl, cst, true, NULL, LOOKUP_ONLYCONVERTING); - pushdecl_maybe_friend (decl, false); + safe_pushdecl_maybe_friend (decl, false);
return 1; } @@ -827,6 +927,105 @@ plugin_error (cc1_plugin::connection *, return convert_out (error_mark_node); }
+#if 0 // FIXME: remove me. +gcc_decl +plugin_build_member_decl (cc1_plugin::connection *self, + gcc_decl scope_in, + const char *name, + enum gcc_cp_symbol_kind sym_kind, + gcc_type sym_type_in, + gcc_address address, + const char *filename, + unsigned int line_number) +{ + tree scope = convert_in (scope_in); + tree sym_type = convert_in (sym_type_in); + tree decl; + tree identifier; + + if (!scope) + scope = global_namespace; + + if (name) + identifier = get_identifier (name); + else + identifier = NULL_TREE; + + source_location loc = ctx->get_source_location (filename, line_number); + + switch (sym_kind) { + case GCC_CP_SYMBOL_TYPEDEF: + gcc_assert (identifier); + gcc_assert (!address); + decl = build_decl (loc, TYPE_DECL, identifier, sym_type); + break; + + case GCC_CP_SYMBOL_VARIABLE: + gcc_assert (TREE_CODE (scope) == NAMESPACE_SCOPE + || RECORD_OR_UNION_CODE_P (TREE_CODE (scope))); + gcc_assert (identifier); + gcc_assert (address); + decl = build_decl (loc, VAR_DECL, identifier, sym_type); + DECL_EXTERN (decl) = 1; + break; + + case GCC_CP_SYMBOL_FUNCTION: + { + bool method_p = TREE_CODE (sym_type) == METHOD_TYPE; + bool abstract_p = method_p && !address; + bool virtual_p = abstract_p || method_p && (address & 1) != 0; + + gcc_assert (identifier); + if (method_p) + gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (scope))); + else + { + gcc_assert (address); + gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL + || RECORD_OR_UNION_CODE_P (TREE_CODE (scope))); + } + + if (virtual_p && !abstract_p) + address--; + + decl = build_lang_decl (FUNCTION_DECL, identifier, sym_type); + DECL_EXTERN (decl) = 1; + } + break; + + case GCC_CP_SYMBOL_BASE_CLASS: + gcc_assert (!identifier); + gcc_assert (!address); + gcc_assert (sym_type); + // FIXME: xref_basetypes takes a list + return scope_in; + + case GCC_CP_SYMBOL_NAMESPACE: + gcc_assert (!address); + gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL); + decl = build_lang_decl (NAMESPACE_DECL, identifier, void_type_node); + if (identifier && !decl_anon_ns_mem_p (scope)) + TREE_PUBLIC (decl) = 1; + break; + + case GCC_CP_SYMBOL_TYPENAME: + + + case GCC_CP_SYMBOL_LABEL: + default: + error: + gcc_unreachable (); + } + + TREE_USED (decl) = 1; + TREE_ADDRESSABLE (decl) = 1; + DECL_CONTEXT (decl) = FROB_CONTEXT (scope); + /* add the decl and set its address. */ + + return convert_out (ctx->preserve (decl)); +} +#endif +
// Perform GC marking. diff --git a/libcc1/marshall-cp.hh b/libcc1/marshall-cp.hh index 45a9dc6..d600ff9 100644 --- a/libcc1/marshall-cp.hh +++ b/libcc1/marshall-cp.hh @@ -54,6 +54,87 @@ namespace cc1_plugin *result = (enum gcc_cp_qualifiers) p; return OK; } + + status + unmarshall (connection *conn, enum gcc_cp_ref_qualifiers *result) + { + protocol_int p; + if (!unmarshall_intlike (conn, &p)) + return FAIL; + *result = (enum gcc_cp_ref_qualifiers) p; + return OK; + } + + // Send a gcc_vbase_array marker followed by the array. + status + marshall (connection *conn, const gcc_vbase_array *a) + { + size_t len; + + if (a) + len = a->n_elements; + else + len = (size_t)-1; + + if (!marshall_array_start (conn, 'v', len)) + return FAIL; + + if (!a) + return OK; + + if (!marshall_array_elmts (conn, len * sizeof (a->elements[0]), + a->elements)) + return FAIL; + + return marshall_array_elmts (conn, len * sizeof (a->virtualp[0]), + a->virtualp); + } + + // 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_vbase_array **result) + { + size_t len; + + if (!unmarshall_array_start (conn, 'v', &len)) + return FAIL; + + if (len == (size_t)-1) + { + *result = NULL; + return OK; + } + + *result = new gcc_vbase_array; + + (*result)->n_elements = len; + (*result)->elements = new gcc_type[len]; + + if (!unmarshall_array_elmts (conn, + len * sizeof ((*result)->elements[0]), + (*result)->elements)) + { + delete[] (*result)->elements; + delete *result; + return FAIL; + } + + (*result)->virtualp = new char[len]; + + if (!unmarshall_array_elmts (conn, + len * sizeof ((*result)->virtualp[0]), + (*result)->virtualp)) + { + delete[] (*result)->virtualp; + delete[] (*result)->elements; + delete *result; + return FAIL; + } + + return OK; + } }
#endif // CC1_PLUGIN_MARSHALL_CP_HH diff --git a/libcc1/marshall.cc b/libcc1/marshall.cc index 0e4b77c..9c62c40 100644 --- a/libcc1/marshall.cc +++ b/libcc1/marshall.cc @@ -98,34 +98,77 @@ cc1_plugin::unmarshall (connection *conn, char **result) }
cc1_plugin::status -cc1_plugin::marshall (connection *conn, const gcc_type_array *a) +cc1_plugin::marshall_array_start (connection *conn, char id, + size_t n_elements) { - if (!conn->send ('a')) + if (!conn->send (id)) return FAIL;
- unsigned long long r = a->n_elements; + unsigned long long r = n_elements; if (!conn->send (&r, sizeof (r))) return FAIL;
- return conn->send (a->elements, r * sizeof (a->elements[0])); + return OK; }
cc1_plugin::status -cc1_plugin::unmarshall (connection *conn, gcc_type_array **result) +cc1_plugin::marshall_array_elmts (connection *conn, size_t n_bytes, + void *elements) +{ + return conn->send (elements, n_bytes); +} + +cc1_plugin::status +cc1_plugin::unmarshall_array_start (connection *conn, char id, + size_t *n_elements) { unsigned long long len;
- if (!conn->require ('a')) + if (!conn->require (id)) return FAIL; if (!conn->get (&len, sizeof (len))) return FAIL; + + *n_elements = len; + + return OK; +} + +cc1_plugin::status +cc1_plugin::unmarshall_array_elmts (connection *conn, size_t n_bytes, + void *elements) +{ + return conn->get (elements, n_bytes); +} + +cc1_plugin::status +cc1_plugin::marshall (connection *conn, const gcc_type_array *a) +{ + size_t len = a->n_elements; + + if (!marshall_array_start (conn, 'a', len)) + return FAIL; + + return marshall_array_elmts (conn, len * sizeof (a->elements[0]), + a->elements); +} + +cc1_plugin::status +cc1_plugin::unmarshall (connection *conn, gcc_type_array **result) +{ + size_t len; + + if (!unmarshall_array_start (conn, 'a', &len)) + return FAIL;
*result = new gcc_type_array;
(*result)->n_elements = len; (*result)->elements = new gcc_type[len];
- if (!conn->get ((*result)->elements, len * sizeof ((*result)->elements[0]))) + if (!unmarshall_array_elmts (conn, + len * sizeof ((*result)->elements[0]), + (*result)->elements)) { delete[] (*result)->elements; delete *result; diff --git a/libcc1/marshall.hh b/libcc1/marshall.hh index 021ac96..b4a20c5 100644 --- a/libcc1/marshall.hh +++ b/libcc1/marshall.hh @@ -44,6 +44,12 @@ namespace cc1_plugin // integer store it in the out argument. status unmarshall_intlike (connection *, protocol_int *);
+ status marshall_array_start (connection *, char, size_t); + status marshall_array_elmts (connection *, size_t, void *); + + status unmarshall_array_start (connection *, char, size_t *); + status unmarshall_array_elmts (connection *, size_t, void *); + // A template function that can handle marshalling various integer // objects to the connection. template<typename T> diff --git a/libcc1/names.cc b/libcc1/names.cc index 5ddfa7b..bc635f8 100644 --- a/libcc1/names.cc +++ b/libcc1/names.cc @@ -21,21 +21,27 @@ along with GCC; see the file COPYING3. If not see #include "names.hh"
#define GCC_METHOD0(R, N) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N; #define GCC_METHOD1(R, N, A) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N; #define GCC_METHOD2(R, N, A, B) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N; #define GCC_METHOD3(R, N, A, B, C) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N; #define GCC_METHOD4(R, N, A, B, C, D) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N; #define GCC_METHOD5(R, N, A, B, C, D, E) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N; #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ - const char *cc1_plugin::N = # N; + const char *cc1_plugin::LANG::N = # N;
+#define LANG c #include "gcc-c-fe.def" +#undef LANG + +#define LANG cp +#include "gcc-cp-fe.def" +#undef LANG
#undef GCC_METHOD0 #undef GCC_METHOD1 diff --git a/libcc1/names.hh b/libcc1/names.hh index 9bda8d5..1a8f352 100644 --- a/libcc1/names.hh +++ b/libcc1/names.hh @@ -22,10 +22,6 @@ along with GCC; see the file COPYING3. If not see
namespace cc1_plugin { - // This code defines global string constants, one for each method in - // gcc-c-fe.def. This is needed so that they can be used as - // template arguments elsewhere. - #define GCC_METHOD0(R, N) \ extern const char *N; #define GCC_METHOD1(R, N, A) \ @@ -41,7 +37,21 @@ namespace cc1_plugin #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ extern const char *N;
+ namespace c + { + // This code defines global string constants, one for each method in + // gcc-c-fe.def. This is needed so that they can be used as + // template arguments elsewhere. #include "gcc-c-fe.def" + } + + namespace cp + { + // This code defines global string constants, one for each method in + // gcc-cp-fe.def. This is needed so that they can be used as + // template arguments elsewhere. +#include "gcc-cp-fe.def" + }
#undef GCC_METHOD0 #undef GCC_METHOD1 diff --git a/libcc1/rpc.hh b/libcc1/rpc.hh index 43182a9..be81c49 100644 --- a/libcc1/rpc.hh +++ b/libcc1/rpc.hh @@ -125,6 +125,45 @@ namespace cc1_plugin argument_wrapper &operator= (const argument_wrapper &); };
+#ifdef GCC_CP_INTERFACE_H + // Specialization for gcc_type_array. + template<> + class argument_wrapper<const gcc_vbase_array *> + { + 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->virtualp; + delete[] m_object->elements; + } + delete m_object; + } + + operator const gcc_vbase_array * () const + { + return m_object; + } + + status unmarshall (connection *conn) + { + return ::cc1_plugin::unmarshall (conn, &m_object); + } + + private: + + gcc_vbase_array *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 // "callback". They are each repeated multiple times to handle // different numbers of arguments. (This would be improved with