diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2015-07-23 08:09:19 -0300 |
---|---|---|
committer | Alexandre Oliva <aoliva@redhat.com> | 2016-02-19 19:55:08 -0200 |
commit | f11953f20ada5ca2585737e508bd38ae288acc58 (patch) | |
tree | 1d90713d8696bd42e64ae5877ffefd949dc8eea0 | |
parent | c353c065f655acc13ead0197e1a3222f901958da (diff) | |
download | gcc-f11953f20ada5ca2585737e508bd38ae288acc58.tar.gz |
libcc1 interface: add C++ refs, memptrs, throw specs
Add support for reference types, pointers to members, and exception
specifications for function and method types.
Bumped GCC_CP_FE_VERSION_0.
-rw-r--r-- | include/gcc-cp-fe.def | 49 | ||||
-rw-r--r-- | include/gcc-cp-interface.h | 2 | ||||
-rw-r--r-- | libcc1/libcp1plugin.cc | 69 | ||||
-rw-r--r-- | libcc1/marshall.cc | 16 |
4 files changed, 122 insertions, 14 deletions
diff --git a/include/gcc-cp-fe.def b/include/gcc-cp-fe.def index 0dc386754ee..74715810f9c 100644 --- a/include/gcc-cp-fe.def +++ b/include/gcc-cp-fe.def @@ -60,9 +60,11 @@ GCC_METHOD0 (gcc_decl, get_current_binding_level) Note that, since access controls are disabled, we have no means to express private, protected and public. + We have no means to introduce friend declarations, but since we + disable access control, they make no difference whatsoever. + 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 + introduce using declarations, using directives and namespace aliases. FIXME: How about override and final virtual functions; =delete and @@ -85,7 +87,21 @@ GCC_METHOD7 (gcc_decl, new_decl, GCC_METHOD1 (gcc_type, build_pointer_type, gcc_type) /* Argument BASE_TYPE. */ -// FIXME: we need reference types and pointer-to-member types. +/* Return the type of a reference to a given base type. */ + +GCC_METHOD2 (gcc_type, build_reference_type, + gcc_type, /* Argument BASE_TYPE. */ + enum gcc_cp_ref_qualifiers) /* Argument RQUALS. */ + +/* Create a new pointer-to-member type. MEMBER_TYPE is the data + member type, while CLASS_TYPE is the class type containing the data + member. For pointers to member functions, MEMBER_TYPE must be a + method type, and CLASS_TYPE must be specified even though it might + be possible to extract it from the method type. */ + +GCC_METHOD2 (gcc_type, build_pointer_to_member_type, + gcc_type, /* Argument CLASS_TYPE. */ + gcc_type) /* Argument MEMBER_TYPE. */ /* Create a new 'class' (or 'struct') type, record it in the current binding level, and enter its own binding level. Initially it has @@ -167,21 +183,32 @@ GCC_METHOD1 (int /* bool */, finish_enum_type, /* Create a new function type. RETURN_TYPE is the type returned by the function, and ARGUMENT_TYPES is a vector, of length NARGS, of the argument types. IS_VARARGS is true if the function is - varargs. - - FIXME: C++ allows such stuff as "typedef int f() const;" to create - a cv-qualified (member) function type not associated with any - specific class, which can then be used to declare member functions - and pointers to member functions. Our API doesn't support this. */ + varargs. */ 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. */ +/* Create a variant of a function type with an exception + specification. FUNCTION_TYPE is a function or method type. + EXCEPT_TYPES is an array with the list of exception types. Zero as + the array length implies throw() AKA noexcept(true); NULL as the + pointer to gcc_type_array implies noexcept(false), which is almost + equivalent (but distinguishable by the compiler) to an unspecified + exception list. */ + +GCC_METHOD2 (gcc_type, build_exception_spec_variant, + gcc_type, /* Argument FUNCTION_TYPE. */ + const struct gcc_type_array *)/* Argument EXCEPT_TYPES. */ + /* 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. */ + pointer to the QUALS-qualified CLASS_TYPE. If CLASS_TYPE is NULL, + this creates a cv-qualified (member) function type not associated + with any specific class, as needed to support "typedef void f(int) + const;", which can later be used to declare member functions and + pointers to member functions. */ GCC_METHOD4 (gcc_type, build_method_type, gcc_type, /* Argument CLASS_TYPE. */ @@ -189,7 +216,7 @@ GCC_METHOD4 (gcc_type, build_method_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. +// FIXME: add default expressions for function arguments? /* Return an integer type with the given properties. */ diff --git a/include/gcc-cp-interface.h b/include/gcc-cp-interface.h index a4b3be0d30c..cb297b644a5 100644 --- a/include/gcc-cp-interface.h +++ b/include/gcc-cp-interface.h @@ -41,7 +41,7 @@ struct gcc_cp_context; enum gcc_cp_api_version { - GCC_CP_FE_VERSION_0 = 0xffffffff-1 + GCC_CP_FE_VERSION_0 = 0xffffffff-2 }; /* Qualifiers. */ diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index c8681420613..b4d9ee28c3d 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -563,6 +563,31 @@ plugin_build_pointer_type (cc1_plugin::connection *, return convert_out (build_pointer_type (convert_in (base_type))); } +gcc_type +plugin_build_reference_type (cc1_plugin::connection *, + gcc_type base_type_in, + enum gcc_cp_ref_qualifiers rquals) +{ + bool rval; + + switch (rquals) + { + case GCC_CP_REF_QUAL_LVALUE: + rval = false; + break; + case GCC_CP_REF_QUAL_RVALUE: + rval = true; + break; + case GCC_CP_REF_QUAL_NONE: + default: + gcc_unreachable (); + } + + tree rtype = cp_build_reference_type (convert_in (base_type_in), rval); + + return convert_out (rtype); +} + // TYPE_NAME needs to be a valid pointer, even if there is no name available. static tree @@ -781,6 +806,32 @@ plugin_build_function_type (cc1_plugin::connection *self, } gcc_type +plugin_build_exception_spec_variant (cc1_plugin::connection *self, + gcc_type function_type_in, + const struct gcc_type_array *except_types_in) +{ + tree function_type = convert_in (function_type_in); + tree except_types = NULL_TREE; + + if (!except_types_in) + except_types = noexcept_false_spec; + else if (!except_types_in->n_elements) + except_types = empty_except_spec; + else + for (int i = 0; i < except_types_in->n_elements; i++) + except_types = add_exception_specifier (except_types, + convert_in + (except_types_in->elements[i]), + 0); + + function_type = build_exception_variant (function_type, + except_types); + + plugin_context *ctx = static_cast<plugin_context *> (self); + return convert_out (ctx->preserve (function_type)); +} + +gcc_type plugin_build_method_type (cc1_plugin::connection *self, gcc_type class_type_in, gcc_type func_type_in, @@ -813,13 +864,29 @@ plugin_build_method_type (cc1_plugin::connection *self, gcc_unreachable (); } - tree method_type = build_memfn_type (func_type, class_type, quals, rquals); + tree method_type = class_type + ? build_memfn_type (func_type, class_type, quals, rquals) + : apply_memfn_quals (func_type, quals, rquals); plugin_context *ctx = static_cast<plugin_context *> (self); return convert_out (ctx->preserve (method_type)); } gcc_type +plugin_build_pointer_to_member_type (cc1_plugin::connection *self, + gcc_type class_type_in, + gcc_type member_type_in) +{ + tree class_type = convert_in (class_type_in); + tree member_type = convert_in (member_type_in); + + tree memptr_type = build_ptrmem_type (class_type, member_type); + + plugin_context *ctx = static_cast<plugin_context *> (self); + return convert_out (ctx->preserve (memptr_type)); +} + +gcc_type plugin_int_type (cc1_plugin::connection *self, int is_unsigned, unsigned long size_in_bytes) { diff --git a/libcc1/marshall.cc b/libcc1/marshall.cc index 9c62c407886..4d81f147ab5 100644 --- a/libcc1/marshall.cc +++ b/libcc1/marshall.cc @@ -144,11 +144,19 @@ cc1_plugin::unmarshall_array_elmts (connection *conn, size_t n_bytes, cc1_plugin::status cc1_plugin::marshall (connection *conn, const gcc_type_array *a) { - size_t len = a->n_elements; + size_t len; + + if (a) + len = a->n_elements; + else + len = (size_t)-1; if (!marshall_array_start (conn, 'a', len)) return FAIL; + if (!a) + return OK; + return marshall_array_elmts (conn, len * sizeof (a->elements[0]), a->elements); } @@ -161,6 +169,12 @@ cc1_plugin::unmarshall (connection *conn, gcc_type_array **result) if (!unmarshall_array_start (conn, 'a', &len)) return FAIL; + if (len == (size_t)-1) + { + *result = NULL; + return OK; + } + *result = new gcc_type_array; (*result)->n_elements = len; |