summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2015-07-23 08:09:19 -0300
committerAlexandre Oliva <aoliva@redhat.com>2016-02-19 19:55:08 -0200
commitf11953f20ada5ca2585737e508bd38ae288acc58 (patch)
tree1d90713d8696bd42e64ae5877ffefd949dc8eea0
parentc353c065f655acc13ead0197e1a3222f901958da (diff)
downloadgcc-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.def49
-rw-r--r--include/gcc-cp-interface.h2
-rw-r--r--libcc1/libcp1plugin.cc69
-rw-r--r--libcc1/marshall.cc16
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;