Introduce C++ support in libcc1

Extend libcc1's with an API for C++ support.

Extend libcc1's C API to distinguish between integral types with the
same width, as in C++.  Likewise for float types.

Export small bits of functionality from the C++ front-end for use in
libcc1.  Add support for the C++ front-end to look up names and
addresses using a libcc1-registered binding oracle.  Add support for
global friends.


for  gcc/cp/ChangeLog

	Introduce C++ support in libcc1.
	* cp-tree.h (struct lang_identifier): Add oracle_looked_up.
	(ansi_opname): Rename to...
	(cp_operator_id): ... this.  Adjust all callers.
	(ansi_assopname): Rename to...
	(cp_assignment_operator_id): ... this.  Adjust all callers.
	(cp_literal_operator_id): Declare.
	(set_global_friend): Declare.
	(is_global_friend): Declare.
	(enum cp_oracle_request): New type.
	(cp_binding_oracle_function): New type.
	(cp_binding_oracle): Declare.
	(cp_finish_injected_record_type): Declare.
	* friend.c (global_friend): New var.
	(set_global_friend): New fn.
	(is_global_friend): New fn.
	(is_friend): Call is_global_friend.
	* name-lookup.c (cp_binding_oracle): New var.
	(query_oracle): New fn.
	(qualified_lookup_using_namespace): Call query_oracle.
	(lookup_name_real_1): Likewise.
	* parser.c (cp_literal_operator_id): Drop static.
	* search.c (friend_accessible_p): Call is_global_friend.
	* semantics.c (is_this_parameter): Accept a variable if the
	binding oracle is enabled.

for  include/ChangeLog

	Introduce C++ support in libcc1.
	* gcc-c-fe.def (int_type_v0): Rename from...
	(int_type): ... this.  Introduce new version.
	(float_type_v0): Rename from...
	(float_type): ... this.  Introduce new version.
	(char_type): New.
	* gcc-c-interface.h (gcc_c_api_version): Add GCC_C_FE_VERSION_1.
	(gcc_type_array): Move...
	* gcc-interface.h: ... here.
	* gcc-cp-fe.def: New.
	* gcc-cp-interface.h: New.

for  libcc1/ChangeLog

	Introduce C++ support.
	* Makefile.am (AM_CPPFLAGS): Move some -I flags to...
	(CPPFLAGS_FOR_C_FAMILY, CPPFLAGS_FOR_C, CPPFLAGS_FOR_CXX): ...
	new macros.
	(plugin_LTLIBRARIES): Add libcp1plugin.la.
	(BUILT_SOURCES, MOSTLYCLEANFILES): Add...
	(cp-compiler-name.h): ... this.  New.
	(c-compiler-name.h): Rename all over from...
	(compiler-name.h): ... this.  Create it atomically.
	(marshall_c_source, marshall_cxx_source): New macros.
	(libcc1plugin_la_SOURCES): Rename plugin.cc to libcc1plugin.cc.
	Add marshall_c_source expansion.
	(libcc1plugin.lo_CPPFLAGS): New macro.
	(libcp1plugin_la_LDFLAGS): Likewise.
	(libcp1plugin_la_SOURCES): Likewise.
	(libcp1plugin.lo_CPPFLAGS): Likewise.
	(libcp1plugin_la_LIBADD): Likewise.
	(libcp1plugin_la_DEPENDENCIES): Likewise.
	(libcp1plugin_la_LINK): Likewise.
	(libcc1_la_SOURCES): Added marshall_c_source and
	marshall_cxx_source expansions.
	* Makefile.in: Rebuild.
	* compiler-name.h: Rename all over to...
	* c-compiler-name.h: ... this.  Define C_COMPILER_NAME instead
	of COMPILER_NAME.
	* plugin.cc: Rename all over to...
	* libcc1plugin.cc: ... this.  Include marshall-c.hh.
	(address_rewriter): Drop cleaning up of VLA sizes.
	(plugin_build_decl): Mark decls as external.
	(plugin_tagbind): Propagate name to all variants.
	(build_anonymous_node): New.
	(plugin_build_record_type): Use it instead of make_node.
	(plugin_build_union_type): Likewise.
	(plugin_build_enum_type): Likewise.
	(plugin_finish_record_or_union): Update all type variants.
	(safe_lookup_builtin_type): New.
	(plugin_int_check): Factor out of, and add checks to, ...
	(plugin_int_type): ... this.  Rename to...
	(plugin_int_type_v0): ... this.
	(plugin_int_type): New interface, new implementation.
	(plugin_char_type): New.
	(plugin_float_type_v0): Rename from...
	(plugin_float_type): ... this.  New interface, new implementation.
	(plugin_init): Bump handshake version.
	* libcc1.cc: Include marshall-c.hh.  Drop gcc-interface.h.
	(call_binding_oracle): Rename to...
	(c_call_binding_oracle): ... this, into anonymous namespace.
	(call_symbol_address): Rename to...
	(c_call_symbol_address): ... this, likewise.
	(GCC_METHOD#): Move methods into cc1plugin::c:: namespace.
	(libcc1::compiler::find): Refer to C_COMPILER_NAME.
	(fork_exec): Bump to GCC_C_FE_VERSION_1.
	(libcc1_compile): Prefix callbacks with c_.
	(gcc_c_fe_context): Accept GCC_C_FE_VERSION_1.
	* libcc1.sym: Export gcc_cp_fe_context.
	* libcp1.cc: New, mostly copied and adjusted from libcc1.cc.
	* libcp1plugin.cc: New, initially copied from libcc1plugin.cc.
	* libcp1plugin.sym: New.
	* marshall-c.hh: New.  Move C-specific types from...
	* marshall.cc: ... this.
	(cc1_plugin::marshall_array_start): New.
	(cc1_plugin::marshall_array_elmts): New.
	(cc1_plugin::marshall for gcc_type_array): Use the above.
	(cc1_plugin::unmarshall_array_start): New.
	(cc1_plugin::unmarshall_array_elmts): New.
	(cc1_plugin::unmarshall for gcc_type_array): Use the above.
	* marshall.hh: Declare the new array building blocks.
	Drop C-specific unmarshall declarations.
	* marshall-cp.hh: New.
	* names.cc (GCC_METHOD#): Add LANG:: to method names.
	(LANG): Define while including gcc-c-fe.def and gcc-cp-fe.def.
	* names.hh: Include gcc-c-fe.def and gcc-cp-fe.def in the
	corresponding namespaces.
	* rpc.hh: Don't include marshall.hh.
	[GCC_CP_INTERFACE_H] (argument_wrapper): Specialize for
	gcc_vbase_array, gcc_cp_template_args, gcc_cp_function_args.

From-SVN: r245051
This commit is contained in:
Alexandre Oliva 2017-01-31 01:02:03 +00:00 committed by Alexandre Oliva
parent 9f92b93b7b
commit 8db29d88f3
38 changed files with 7205 additions and 257 deletions

View File

@ -1,3 +1,31 @@
2017-01-30 Alexandre Oliva <aoliva@redhat.com>
Introduce C++ support in libcc1.
* cp-tree.h (struct lang_identifier): Add oracle_looked_up.
(ansi_opname): Rename to...
(cp_operator_id): ... this. Adjust all callers.
(ansi_assopname): Rename to...
(cp_assignment_operator_id): ... this. Adjust all callers.
(cp_literal_operator_id): Declare.
(set_global_friend): Declare.
(is_global_friend): Declare.
(enum cp_oracle_request): New type.
(cp_binding_oracle_function): New type.
(cp_binding_oracle): Declare.
(cp_finish_injected_record_type): Declare.
* friend.c (global_friend): New var.
(set_global_friend): New fn.
(is_global_friend): New fn.
(is_friend): Call is_global_friend.
* name-lookup.c (cp_binding_oracle): New var.
(query_oracle): New fn.
(qualified_lookup_using_namespace): Call query_oracle.
(lookup_name_real_1): Likewise.
* parser.c (cp_literal_operator_id): Drop static.
* search.c (friend_accessible_p): Call is_global_friend.
* semantics.c (is_this_parameter): Accept a variable if the
binding oracle is enabled.
2017-01-27 Jason Merrill <jason@redhat.com>
PR c++/78771 - ICE with inherited constructor.

View File

@ -4426,7 +4426,7 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
if (TYPE_BINFO (type))
{
fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname (CALL_EXPR), 1);
fns = lookup_fnfields (TYPE_BINFO (type), cp_operator_id (CALL_EXPR), 1);
if (fns == error_mark_node)
return error_mark_node;
}
@ -5136,7 +5136,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
add_builtin_candidates (&candidates,
COND_EXPR,
NOP_EXPR,
ansi_opname (COND_EXPR),
cp_operator_id (COND_EXPR),
args,
LOOKUP_NORMAL, complain);
@ -5559,10 +5559,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
{
code2 = TREE_CODE (arg3);
arg3 = NULL_TREE;
fnname = ansi_assopname (code2);
fnname = cp_assignment_operator_id (code2);
}
else
fnname = ansi_opname (code);
fnname = cp_operator_id (code);
arg1 = prep_operand (arg1);
@ -6167,7 +6167,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
type = strip_array_types (TREE_TYPE (TREE_TYPE (addr)));
fnname = ansi_opname (code);
fnname = cp_operator_id (code);
if (CLASS_TYPE_P (type)
&& COMPLETE_TYPE_P (complete_type (type))
@ -8283,7 +8283,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
|| name == complete_dtor_identifier
|| name == base_dtor_identifier
|| name == deleting_dtor_identifier
|| name == ansi_assopname (NOP_EXPR));
|| name == cp_assignment_operator_id (NOP_EXPR));
if (TYPE_P (binfo))
{
/* Resolve the name. */
@ -8311,7 +8311,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
if (!same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (instance), BINFO_TYPE (binfo)))
{
if (name != ansi_assopname (NOP_EXPR))
if (name != cp_assignment_operator_id (NOP_EXPR))
/* For constructors and destructors, either the base is
non-virtual, or it is virtual but we are doing the
conversion from a constructor or destructor for the

View File

@ -3254,7 +3254,7 @@ static tree
dfs_declare_virt_assop_and_dtor (tree binfo, void *data)
{
tree bv, fn, t = (tree)data;
tree opname = ansi_assopname (NOP_EXPR);
tree opname = cp_assignment_operator_id (NOP_EXPR);
gcc_assert (t && CLASS_TYPE_P (t));
gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO);
@ -5349,7 +5349,7 @@ vbase_has_user_provided_move_assign (tree type)
{
/* Does the type itself have a user-provided move assignment operator? */
for (tree fns
= lookup_fnfields_slot_nolazy (type, ansi_assopname (NOP_EXPR));
= lookup_fnfields_slot_nolazy (type, cp_assignment_operator_id (NOP_EXPR));
fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
@ -5513,7 +5513,7 @@ type_has_move_assign (tree t)
lazily_declare_fn (sfk_move_assignment, t);
}
for (fns = lookup_fnfields_slot_nolazy (t, ansi_assopname (NOP_EXPR));
for (fns = lookup_fnfields_slot_nolazy (t, cp_assignment_operator_id (NOP_EXPR));
fns; fns = OVL_NEXT (fns))
if (move_fn_p (OVL_CURRENT (fns)))
return true;
@ -5558,7 +5558,7 @@ type_has_user_declared_move_assign (tree t)
if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
return false;
for (fns = lookup_fnfields_slot_nolazy (t, ansi_assopname (NOP_EXPR));
for (fns = lookup_fnfields_slot_nolazy (t, cp_assignment_operator_id (NOP_EXPR));
fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
@ -5679,7 +5679,7 @@ type_requires_array_cookie (tree type)
the array to the deallocation function, so we will need to store
a cookie. */
fns = lookup_fnfields (TYPE_BINFO (type),
ansi_opname (VEC_DELETE_EXPR),
cp_operator_id (VEC_DELETE_EXPR),
/*protect=*/0);
/* If there are no `operator []' members, or the lookup is
ambiguous, then we don't need a cookie. */

View File

@ -332,6 +332,7 @@ struct GTY(()) lang_identifier {
cxx_binding *bindings;
tree class_template_info;
tree label_value;
bool oracle_looked_up;
};
/* Return a typed pointer version of T if it designates a
@ -1530,15 +1531,17 @@ struct GTY(()) language_function {
/* True if NAME is the IDENTIFIER_NODE for an overloaded "operator
new" or "operator delete". */
#define NEW_DELETE_OPNAME_P(NAME) \
((NAME) == ansi_opname (NEW_EXPR) \
|| (NAME) == ansi_opname (VEC_NEW_EXPR) \
|| (NAME) == ansi_opname (DELETE_EXPR) \
|| (NAME) == ansi_opname (VEC_DELETE_EXPR))
((NAME) == cp_operator_id (NEW_EXPR) \
|| (NAME) == cp_operator_id (VEC_NEW_EXPR) \
|| (NAME) == cp_operator_id (DELETE_EXPR) \
|| (NAME) == cp_operator_id (VEC_DELETE_EXPR))
#define ansi_opname(CODE) \
#define cp_operator_id(CODE) \
(operator_name_info[(int) (CODE)].identifier)
#define ansi_assopname(CODE) \
#define cp_assignment_operator_id(CODE) \
(assignment_operator_name_info[(int) (CODE)].identifier)
/* In parser.c. */
extern tree cp_literal_operator_id (const char *);
/* TRUE if a tree code represents a statement. */
extern bool statement_code_p[MAX_TREE_CODES];
@ -6027,6 +6030,9 @@ extern void make_friend_class (tree, tree, bool);
extern void add_friend (tree, tree, bool);
extern tree do_friend (tree, tree, tree, tree, enum overload_flags, bool);
extern void set_global_friend (tree);
extern bool is_global_friend (tree);
/* in init.c */
extern tree expand_member_init (tree);
extern void emit_mem_initializers (tree);
@ -6944,6 +6950,25 @@ extern void suggest_alternatives_for (location_t, tree, bool);
extern bool suggest_alternative_in_explicit_scope (location_t, tree, tree);
extern tree strip_using_decl (tree);
/* Tell the binding oracle what kind of binding we are looking for. */
enum cp_oracle_request
{
CP_ORACLE_IDENTIFIER
};
/* If this is non-NULL, then it is a "binding oracle" which can lazily
create bindings when needed by the C compiler. The oracle is told
the name and type of the binding to create. It can call pushdecl
or the like to ensure the binding is visible; or do nothing,
leaving the binding untouched. c-decl.c takes note of when the
oracle has been called and will not call it again if it fails to
create a given binding. */
typedef void cp_binding_oracle_function (enum cp_oracle_request, tree identifier);
extern cp_binding_oracle_function *cp_binding_oracle;
/* in constraint.cc */
extern void init_constraint_processing ();
extern bool constraint_p (tree);
@ -7009,6 +7034,9 @@ extern void diagnose_constraints (location_t, tree, tree);
extern tree decompose_conclusions (tree);
extern bool subsumes (tree, tree);
/* In class.c */
extern void cp_finish_injected_record_type (tree);
/* in vtable-class-hierarchy.c */
extern void vtv_compute_class_hierarchy_transitive_closure (void);
extern void vtv_generate_init_routine (void);

View File

@ -4564,7 +4564,7 @@ static tree
push_cp_library_fn (enum tree_code operator_code, tree type,
int ecf_flags)
{
tree fn = build_cp_library_fn (ansi_opname (operator_code),
tree fn = build_cp_library_fn (cp_operator_id (operator_code),
operator_code,
type, ecf_flags);
pushdecl (fn);
@ -12937,12 +12937,12 @@ grok_op_properties (tree decl, bool complain)
do
{
#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \
if (ansi_opname (CODE) == name) \
if (cp_operator_id (CODE) == name) \
{ \
operator_code = (CODE); \
break; \
} \
else if (ansi_assopname (CODE) == name) \
else if (cp_assignment_operator_id (CODE) == name) \
{ \
operator_code = (CODE); \
DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \

View File

@ -4386,7 +4386,7 @@ maybe_warn_sized_delete (enum tree_code code)
tree sized = NULL_TREE;
tree unsized = NULL_TREE;
for (tree ovl = IDENTIFIER_GLOBAL_VALUE (ansi_opname (code));
for (tree ovl = IDENTIFIER_GLOBAL_VALUE (cp_operator_id (code));
ovl; ovl = OVL_NEXT (ovl))
{
tree fn = OVL_CURRENT (ovl);

View File

@ -24,6 +24,46 @@ along with GCC; see the file COPYING3. If not see
/* Friend data structures are described in cp-tree.h. */
/* The GLOBAL_FRIEND scope (functions, classes, or templates) is
regarded as a friend of every class. This is only used by libcc1,
to enable GDB's code snippets to access private members without
disabling access control in general, which could cause different
template overload resolution results when accessibility matters
(e.g. tests for an accessible member). */
static tree global_friend;
/* Set the GLOBAL_FRIEND for this compilation session. It might be
set multiple times, but always to the same scope. */
void
set_global_friend (tree scope)
{
gcc_checking_assert (scope != NULL_TREE);
gcc_assert (!global_friend || global_friend == scope);
global_friend = scope;
}
/* Return TRUE if SCOPE is the global friend. */
bool
is_global_friend (tree scope)
{
gcc_checking_assert (scope != NULL_TREE);
if (global_friend == scope)
return true;
if (!global_friend)
return false;
if (is_specialization_of_friend (global_friend, scope))
return true;
return false;
}
/* Returns nonzero if SUPPLICANT is a friend of TYPE. */
int
@ -36,6 +76,9 @@ is_friend (tree type, tree supplicant)
if (supplicant == NULL_TREE || type == NULL_TREE)
return 0;
if (is_global_friend (supplicant))
return 1;
declp = DECL_P (supplicant);
if (declp)

View File

@ -2924,7 +2924,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
tree fnname;
tree fns;
fnname = ansi_opname (array_p ? VEC_NEW_EXPR : NEW_EXPR);
fnname = cp_operator_id (array_p ? VEC_NEW_EXPR : NEW_EXPR);
member_new_p = !globally_qualified_p
&& CLASS_TYPE_P (elt_type)

View File

@ -202,7 +202,7 @@ lambda_function (tree lambda)
if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
&& !COMPLETE_OR_OPEN_TYPE_P (type))
return NULL_TREE;
lambda = lookup_member (type, ansi_opname (CALL_EXPR),
lambda = lookup_member (type, cp_operator_id (CALL_EXPR),
/*protect=*/0, /*want_type=*/false,
tf_warning_or_error);
if (lambda)

View File

@ -433,7 +433,7 @@ unqualified_name_lookup_error (tree name, location_t loc)
if (IDENTIFIER_OPNAME_P (name))
{
if (name != ansi_opname (ERROR_MARK))
if (name != cp_operator_id (ERROR_MARK))
error_at (loc, "%qD not defined", name);
}
else

View File

@ -812,7 +812,7 @@ do_build_copy_assign (tree fndecl)
parmvec = make_tree_vector_single (converted_parm);
finish_expr_stmt
(build_special_member_call (current_class_ref,
ansi_assopname (NOP_EXPR),
cp_assignment_operator_id (NOP_EXPR),
&parmvec,
base_binfo,
flags,
@ -1105,7 +1105,7 @@ get_copy_assign (tree type)
int quals = (TYPE_HAS_CONST_COPY_ASSIGN (type)
? TYPE_QUAL_CONST : TYPE_UNQUALIFIED);
tree argtype = build_stub_type (type, quals, false);
tree fn = locate_fn_flags (type, ansi_assopname (NOP_EXPR), argtype,
tree fn = locate_fn_flags (type, cp_assignment_operator_id (NOP_EXPR), argtype,
LOOKUP_NORMAL, tf_warning_or_error);
if (fn == error_mark_node)
return NULL_TREE;
@ -1463,7 +1463,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
case sfk_move_assignment:
case sfk_copy_assignment:
assign_p = true;
fnname = ansi_assopname (NOP_EXPR);
fnname = cp_assignment_operator_id (NOP_EXPR);
break;
case sfk_destructor:
@ -1622,7 +1622,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
if (check_vdtor && type_has_virtual_destructor (basetype))
{
rval = locate_fn_flags (ctype, ansi_opname (DELETE_EXPR),
rval = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
ptr_type_node, flags, complain);
/* Unlike for base ctor/op=/dtor, for operator delete it's fine
to have a null rval (no class-specific op delete). */
@ -1949,7 +1949,7 @@ implicitly_declare_fn (special_function_kind kind, tree type,
|| kind == sfk_move_assignment)
{
return_type = build_reference_type (type);
name = ansi_assopname (NOP_EXPR);
name = cp_assignment_operator_id (NOP_EXPR);
}
else
name = constructor_name (type);

View File

@ -92,6 +92,28 @@ get_anonymous_namespace_name (void)
static GTY((deletable)) binding_entry free_binding_entry = NULL;
/* The binding oracle; see cp-tree.h. */
cp_binding_oracle_function *cp_binding_oracle;
/* If we have a binding oracle, ask it for all namespace-scoped
definitions of NAME. */
static inline void
query_oracle (tree name)
{
if (!cp_binding_oracle)
return;
/* LOOKED_UP holds the set of identifiers that we have already
looked up with the oracle. */
static hash_set<tree> looked_up;
if (looked_up.add (name))
return;
cp_binding_oracle (CP_ORACLE_IDENTIFIER, name);
}
/* Create a binding_entry object for (NAME, TYPE). */
static inline binding_entry
@ -4706,6 +4728,8 @@ qualified_lookup_using_namespace (tree name, tree scope,
/* Look through namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
query_oracle (name);
/* Algorithm: Starting with SCOPE, walk through the set of used
namespaces. For each used namespace, look through its inline
namespace set for any bindings and usings. If no bindings are
@ -5030,6 +5054,8 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
cxx_binding *iter;
tree val = NULL_TREE;
query_oracle (name);
/* Conversion operators are handled specially because ordinary
unqualified name lookup will not find template conversion
operators. */
@ -6238,6 +6264,7 @@ pushtag (tree name, tree type, tag_scope scope)
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and

View File

@ -249,9 +249,6 @@ static cp_token_cache *cp_token_cache_new
static void cp_parser_initial_pragma
(cp_token *);
static tree cp_literal_operator_id
(const char *);
static void cp_parser_cilk_simd
(cp_parser *, cp_token *, bool *);
static tree cp_parser_cilk_for
@ -10279,7 +10276,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
p = obstack_alloc (&declarator_obstack, 0);
declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR),
declarator = make_id_declarator (NULL_TREE, cp_operator_id (CALL_EXPR),
sfk_none);
quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
@ -14297,7 +14294,7 @@ cp_parser_operator_function_id (cp_parser* parser)
/* Return an identifier node for a user-defined literal operator.
The suffix identifier is chained to the operator name identifier. */
static tree
tree
cp_literal_operator_id (const char* name)
{
tree identifier;
@ -14366,12 +14363,12 @@ cp_parser_operator (cp_parser* parser)
if (cp_token *close_token
= cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
end_loc = close_token->location;
id = ansi_opname (op == NEW_EXPR
id = cp_operator_id (op == NEW_EXPR
? VEC_NEW_EXPR : VEC_DELETE_EXPR);
}
/* Otherwise, we have the non-array variant. */
else
id = ansi_opname (op);
id = cp_operator_id (op);
location_t loc = make_location (start_loc, start_loc, end_loc);
@ -14379,147 +14376,147 @@ cp_parser_operator (cp_parser* parser)
}
case CPP_PLUS:
id = ansi_opname (PLUS_EXPR);
id = cp_operator_id (PLUS_EXPR);
break;
case CPP_MINUS:
id = ansi_opname (MINUS_EXPR);
id = cp_operator_id (MINUS_EXPR);
break;
case CPP_MULT:
id = ansi_opname (MULT_EXPR);
id = cp_operator_id (MULT_EXPR);
break;
case CPP_DIV:
id = ansi_opname (TRUNC_DIV_EXPR);
id = cp_operator_id (TRUNC_DIV_EXPR);
break;
case CPP_MOD:
id = ansi_opname (TRUNC_MOD_EXPR);
id = cp_operator_id (TRUNC_MOD_EXPR);
break;
case CPP_XOR:
id = ansi_opname (BIT_XOR_EXPR);
id = cp_operator_id (BIT_XOR_EXPR);
break;
case CPP_AND:
id = ansi_opname (BIT_AND_EXPR);
id = cp_operator_id (BIT_AND_EXPR);
break;
case CPP_OR:
id = ansi_opname (BIT_IOR_EXPR);
id = cp_operator_id (BIT_IOR_EXPR);
break;
case CPP_COMPL:
id = ansi_opname (BIT_NOT_EXPR);
id = cp_operator_id (BIT_NOT_EXPR);
break;
case CPP_NOT:
id = ansi_opname (TRUTH_NOT_EXPR);
id = cp_operator_id (TRUTH_NOT_EXPR);
break;
case CPP_EQ:
id = ansi_assopname (NOP_EXPR);
id = cp_assignment_operator_id (NOP_EXPR);
break;
case CPP_LESS:
id = ansi_opname (LT_EXPR);
id = cp_operator_id (LT_EXPR);
break;
case CPP_GREATER:
id = ansi_opname (GT_EXPR);
id = cp_operator_id (GT_EXPR);
break;
case CPP_PLUS_EQ:
id = ansi_assopname (PLUS_EXPR);
id = cp_assignment_operator_id (PLUS_EXPR);
break;
case CPP_MINUS_EQ:
id = ansi_assopname (MINUS_EXPR);
id = cp_assignment_operator_id (MINUS_EXPR);
break;
case CPP_MULT_EQ:
id = ansi_assopname (MULT_EXPR);
id = cp_assignment_operator_id (MULT_EXPR);
break;
case CPP_DIV_EQ:
id = ansi_assopname (TRUNC_DIV_EXPR);
id = cp_assignment_operator_id (TRUNC_DIV_EXPR);
break;
case CPP_MOD_EQ:
id = ansi_assopname (TRUNC_MOD_EXPR);
id = cp_assignment_operator_id (TRUNC_MOD_EXPR);
break;
case CPP_XOR_EQ:
id = ansi_assopname (BIT_XOR_EXPR);
id = cp_assignment_operator_id (BIT_XOR_EXPR);
break;
case CPP_AND_EQ:
id = ansi_assopname (BIT_AND_EXPR);
id = cp_assignment_operator_id (BIT_AND_EXPR);
break;
case CPP_OR_EQ:
id = ansi_assopname (BIT_IOR_EXPR);
id = cp_assignment_operator_id (BIT_IOR_EXPR);
break;
case CPP_LSHIFT:
id = ansi_opname (LSHIFT_EXPR);
id = cp_operator_id (LSHIFT_EXPR);
break;
case CPP_RSHIFT:
id = ansi_opname (RSHIFT_EXPR);
id = cp_operator_id (RSHIFT_EXPR);
break;
case CPP_LSHIFT_EQ:
id = ansi_assopname (LSHIFT_EXPR);
id = cp_assignment_operator_id (LSHIFT_EXPR);
break;
case CPP_RSHIFT_EQ:
id = ansi_assopname (RSHIFT_EXPR);
id = cp_assignment_operator_id (RSHIFT_EXPR);
break;
case CPP_EQ_EQ:
id = ansi_opname (EQ_EXPR);
id = cp_operator_id (EQ_EXPR);
break;
case CPP_NOT_EQ:
id = ansi_opname (NE_EXPR);
id = cp_operator_id (NE_EXPR);
break;
case CPP_LESS_EQ:
id = ansi_opname (LE_EXPR);
id = cp_operator_id (LE_EXPR);
break;
case CPP_GREATER_EQ:
id = ansi_opname (GE_EXPR);
id = cp_operator_id (GE_EXPR);
break;
case CPP_AND_AND:
id = ansi_opname (TRUTH_ANDIF_EXPR);
id = cp_operator_id (TRUTH_ANDIF_EXPR);
break;
case CPP_OR_OR:
id = ansi_opname (TRUTH_ORIF_EXPR);
id = cp_operator_id (TRUTH_ORIF_EXPR);
break;
case CPP_PLUS_PLUS:
id = ansi_opname (POSTINCREMENT_EXPR);
id = cp_operator_id (POSTINCREMENT_EXPR);
break;
case CPP_MINUS_MINUS:
id = ansi_opname (PREDECREMENT_EXPR);
id = cp_operator_id (PREDECREMENT_EXPR);
break;
case CPP_COMMA:
id = ansi_opname (COMPOUND_EXPR);
id = cp_operator_id (COMPOUND_EXPR);
break;
case CPP_DEREF_STAR:
id = ansi_opname (MEMBER_REF);
id = cp_operator_id (MEMBER_REF);
break;
case CPP_DEREF:
id = ansi_opname (COMPONENT_REF);
id = cp_operator_id (COMPONENT_REF);
break;
case CPP_OPEN_PAREN:
@ -14527,14 +14524,14 @@ cp_parser_operator (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
/* Look for the matching `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
return ansi_opname (CALL_EXPR);
return cp_operator_id (CALL_EXPR);
case CPP_OPEN_SQUARE:
/* Consume the `['. */
cp_lexer_consume_token (parser->lexer);
/* Look for the matching `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
return ansi_opname (ARRAY_REF);
return cp_operator_id (ARRAY_REF);
case CPP_UTF8STRING:
case CPP_UTF8STRING_USERDEF:
@ -31991,21 +31988,21 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
code = MIN_EXPR;
else if (strcmp (p, "max") == 0)
code = MAX_EXPR;
else if (id == ansi_opname (PLUS_EXPR))
else if (id == cp_operator_id (PLUS_EXPR))
code = PLUS_EXPR;
else if (id == ansi_opname (MULT_EXPR))
else if (id == cp_operator_id (MULT_EXPR))
code = MULT_EXPR;
else if (id == ansi_opname (MINUS_EXPR))
else if (id == cp_operator_id (MINUS_EXPR))
code = MINUS_EXPR;
else if (id == ansi_opname (BIT_AND_EXPR))
else if (id == cp_operator_id (BIT_AND_EXPR))
code = BIT_AND_EXPR;
else if (id == ansi_opname (BIT_IOR_EXPR))
else if (id == cp_operator_id (BIT_IOR_EXPR))
code = BIT_IOR_EXPR;
else if (id == ansi_opname (BIT_XOR_EXPR))
else if (id == cp_operator_id (BIT_XOR_EXPR))
code = BIT_XOR_EXPR;
else if (id == ansi_opname (TRUTH_ANDIF_EXPR))
else if (id == cp_operator_id (TRUTH_ANDIF_EXPR))
code = TRUTH_ANDIF_EXPR;
else if (id == ansi_opname (TRUTH_ORIF_EXPR))
else if (id == cp_operator_id (TRUTH_ORIF_EXPR))
code = TRUTH_ORIF_EXPR;
id = omp_reduction_id (code, id, NULL_TREE);
tree scope = parser->scope;

View File

@ -782,6 +782,9 @@ friend_accessible_p (tree scope, tree decl, tree type, tree otype)
if (!scope)
return 0;
if (is_global_friend (scope))
return 1;
/* Is SCOPE itself a suitable P? */
if (TYPE_P (scope) && protected_accessible_p (decl, scope, type, otype))
return 1;
@ -1664,7 +1667,7 @@ lookup_fnfields_1 (tree type, tree name)
if (CLASSTYPE_LAZY_MOVE_CTOR (type))
lazily_declare_fn (sfk_move_constructor, type);
}
else if (name == ansi_assopname (NOP_EXPR))
else if (name == cp_assignment_operator_id (NOP_EXPR))
{
if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
lazily_declare_fn (sfk_copy_assignment, type);

View File

@ -5107,7 +5107,7 @@ omp_reduction_id (enum tree_code reduction_code, tree reduction_id, tree type)
case BIT_IOR_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
reduction_id = ansi_opname (reduction_code);
reduction_id = cp_operator_id (reduction_code);
break;
case MIN_EXPR:
p = "min";
@ -9012,7 +9012,7 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
if (assign_p)
{
int ix;
ix = lookup_fnfields_1 (type, ansi_assopname (NOP_EXPR));
ix = lookup_fnfields_1 (type, cp_assignment_operator_id (NOP_EXPR));
if (ix < 0)
return false;
fns = (*CLASSTYPE_METHOD_VEC (type))[ix];
@ -9295,7 +9295,8 @@ is_this_parameter (tree t)
{
if (!DECL_P (t) || DECL_NAME (t) != this_identifier)
return false;
gcc_assert (TREE_CODE (t) == PARM_DECL || is_capture_proxy (t));
gcc_assert (TREE_CODE (t) == PARM_DECL || is_capture_proxy (t)
|| (cp_binding_oracle && TREE_CODE (t) == VAR_DECL));
return true;
}

View File

@ -8881,7 +8881,7 @@ check_return_expr (tree retval, bool *no_warning)
/* Effective C++ rule 15. See also start_function. */
if (warn_ecpp
&& DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR))
&& DECL_NAME (current_function_decl) == cp_assignment_operator_id (NOP_EXPR))
{
bool warn = true;

View File

@ -1,3 +1,17 @@
2017-01-30 Alexandre Oliva <aoliva@redhat.com>
Introduce C++ support in libcc1.
* gcc-c-fe.def (int_type_v0): Rename from...
(int_type): ... this. Introduce new version.
(float_type_v0): Rename from...
(float_type): ... this. Introduce new version.
(char_type): New.
* gcc-c-interface.h (gcc_c_api_version): Add GCC_C_FE_VERSION_1.
(gcc_type_array): Move...
* gcc-interface.h: ... here.
* gcc-cp-fe.def: New.
* gcc-cp-interface.h: New.
2017-01-30 Jan Kratochvil <jan.kratochvil@redhat.com>
* gcc-interface.h (enum gcc_base_api_version): Update comment

View File

@ -125,16 +125,18 @@ GCC_METHOD3 (gcc_type, build_function_type,
const struct gcc_type_array *, /* Argument ARGUMENT_TYPES. */
int /* bool */) /* Argument IS_VARARGS. */
/* Return an integer type with the given properties. */
/* Return an integer type with the given properties.
Deprecated in v1, use int_type instead. */
GCC_METHOD2 (gcc_type, int_type,
GCC_METHOD2 (gcc_type, int_type_v0,
int /* bool */, /* Argument IS_UNSIGNED. */
unsigned long) /* Argument SIZE_IN_BYTES. */
/* Return a floating point type with the given properties. */
/* Return a floating point type with the given properties.
Deprecated in v1, use float_type instead. */
GCC_METHOD1 (gcc_type, float_type,
unsigned long) /* Argument SIZE_IN_BYTES. */
GCC_METHOD1 (gcc_type, float_type_v0,
unsigned long) /* Argument SIZE_IN_BYTES. */
/* Return the 'void' type. */
@ -195,3 +197,26 @@ GCC_METHOD5 (int /* bool */, build_constant,
GCC_METHOD1 (gcc_type, error,
const char *) /* Argument MESSAGE. */
/* Return an integer type with the given properties. If BUILTIN_NAME
is non-NULL, it must name a builtin integral type with the given
signedness and size, and that is the type that will be returned. */
GCC_METHOD3 (gcc_type, int_type,
int /* bool */, /* Argument IS_UNSIGNED. */
unsigned long, /* Argument SIZE_IN_BYTES. */
const char *) /* Argument BUILTIN_NAME. */
/* Return the 'char' type, a distinct type from both 'signed char' and
'unsigned char' returned by int_type. */
GCC_METHOD0 (gcc_type, char_type)
/* Return a floating point type with the given properties. If BUILTIN_NAME
is non-NULL, it must name a builtin integral type with the given
signedness and size, and that is the type that will be returned. */
GCC_METHOD2 (gcc_type, float_type,
unsigned long, /* Argument SIZE_IN_BYTES. */
const char *) /* Argument BUILTIN_NAME. */

View File

@ -41,7 +41,11 @@ struct gcc_c_context;
enum gcc_c_api_version
{
GCC_C_FE_VERSION_0 = 0
GCC_C_FE_VERSION_0 = 0,
/* Added char_type. Added new version of int_type and float_type,
deprecated int_type_v0 and float_type_v0. */
GCC_C_FE_VERSION_1 = 1
};
/* Qualifiers. */
@ -111,19 +115,6 @@ typedef gcc_address gcc_c_symbol_address_function (void *datum,
struct gcc_c_context *ctxt,
const char *identifier);
/* An array of types used for creating a function type. */
struct gcc_type_array
{
/* Number of elements. */
int n_elements;
/* The elements. */
gcc_type *elements;
};
/* The vtable used by the C front end. */
struct gcc_c_fe_vtable
@ -146,7 +137,7 @@ struct gcc_c_fe_vtable
provides the declaration.
DATUM is an arbitrary piece of data that is passed back verbatim
to the callbakcs in requests. */
to the callbacks in requests. */
void (*set_callbacks) (struct gcc_c_context *self,
gcc_c_oracle_function *binding_oracle,

1050
include/gcc-cp-fe.def Normal file

File diff suppressed because it is too large Load Diff

496
include/gcc-cp-interface.h Normal file
View File

@ -0,0 +1,496 @@
/* Interface between GCC C++ FE and GDB
Copyright (C) 2014-2017 Free Software Foundation, Inc.
This file is part of GCC.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef GCC_CP_INTERFACE_H
#define GCC_CP_INTERFACE_H
#include "gcc-interface.h"
/* This header defines the interface to the GCC API. It must be both
valid C and valid C++, because it is included by both programs. */
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declaration. */
struct gcc_cp_context;
/*
* Definitions and declarations for the C++ front end.
*/
/* Defined versions of the C++ front-end API. */
enum gcc_cp_api_version
{
GCC_CP_FE_VERSION_0 = 0
};
/* Qualifiers. */
enum gcc_cp_qualifiers
{
GCC_CP_QUALIFIER_CONST = 1,
GCC_CP_QUALIFIER_VOLATILE = 2,
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
};
/* Opaque typedef for unbound class templates. They are used for
template arguments, and defaults for template template
parameters. */
typedef unsigned long long gcc_utempl;
/* Opaque typedef for expressions. They are used for template
arguments, defaults for non-type template parameters, and defaults
for function arguments. */
typedef unsigned long long gcc_expr;
typedef enum
{ GCC_CP_TPARG_VALUE, GCC_CP_TPARG_CLASS,
GCC_CP_TPARG_TEMPL, GCC_CP_TPARG_PACK }
gcc_cp_template_arg_kind;
typedef union
{ gcc_expr value; gcc_type type; gcc_utempl templ; gcc_type pack; }
gcc_cp_template_arg;
/* An array of template arguments. */
struct gcc_cp_template_args
{
/* Number of elements. */
int n_elements;
/* kind[i] indicates what kind of template argument type[i] is. */
char /* gcc_cp_template_arg_kind */ *kinds;
/* The template arguments. */
gcc_cp_template_arg *elements;
};
/* An array of (default) function arguments. */
struct gcc_cp_function_args
{
/* Number of elements. */
int n_elements;
/* The (default) values for each argument. */
gcc_expr *elements;
};
/* This enumerates the kinds of decls that GDB can create. */
enum gcc_cp_symbol_kind
{
/* A function. */
GCC_CP_SYMBOL_FUNCTION,
/* A variable. */
GCC_CP_SYMBOL_VARIABLE,
/* A typedef, or an alias declaration (including template ones). */
GCC_CP_SYMBOL_TYPEDEF,
/* A label. */
GCC_CP_SYMBOL_LABEL,
/* A class, forward declared in build_decl (to be later defined in
start_class_definition), or, in a template parameter list scope,
a declaration of a template class, closing the parameter
list. */
GCC_CP_SYMBOL_CLASS,
/* A union, forward declared in build_decl (to be later defined in
start_class_definition). */
GCC_CP_SYMBOL_UNION,
/* An enumeration type being introduced with start_new_enum_type. */
GCC_CP_SYMBOL_ENUM,
/* A nonstatic data member being introduced with new_field. */
GCC_CP_SYMBOL_FIELD,
/* A base class in a gcc_vbase_array. */
GCC_CP_SYMBOL_BASECLASS,
/* A using declaration in new_using_decl. */
GCC_CP_SYMBOL_USING,
/* A (lambda) closure class type. In many regards this is just like
a regular class, but it's not supposed to have base classes, some
of the member functions that are usually implicitly-defined are
deleted, and it should have an operator() member function that
holds the lambda body. We can't instantiate objects of lambda
types from the snippet, but we can interact with them in such
ways as passing them to functions that take their types, and
calling their body. */
GCC_CP_SYMBOL_LAMBDA_CLOSURE,
/* Marker to check that we haven't exceeded GCC_CP_SYMBOL_MASK. */
GCC_CP_SYMBOL_END,
GCC_CP_SYMBOL_MASK = 15,
/* When defining a class member, at least one of the
GCC_CP_ACCESS_MASK bits must be set; when defining a namespace-
or union-scoped symbol, none of them must be set. */
GCC_CP_ACCESS_PRIVATE,
GCC_CP_ACCESS_PUBLIC = GCC_CP_ACCESS_PRIVATE << 1,
GCC_CP_ACCESS_MASK = (GCC_CP_ACCESS_PUBLIC
| GCC_CP_ACCESS_PRIVATE),
GCC_CP_ACCESS_PROTECTED = GCC_CP_ACCESS_MASK,
GCC_CP_ACCESS_NONE = 0,
GCC_CP_FLAG_BASE = GCC_CP_ACCESS_PRIVATE << 2,
/* Flags to be used along with GCC_CP_SYMBOL_FUNCTION: */
/* This flag should be set for constructors, destructors and
operators. */
GCC_CP_FLAG_SPECIAL_FUNCTION = GCC_CP_FLAG_BASE,
/* We intentionally cannot express inline, constexpr, or virtual
override for functions. We can't inline or constexpr-replace
without a source-level body. The override keyword is only
meaningful within the definition of the containing class. */
/* This indicates a "virtual" member function, explicitly or
implicitly (due to a virtual function with the same name and
prototype in a base class) declared as such. */
GCC_CP_FLAG_VIRTUAL_FUNCTION = GCC_CP_FLAG_BASE << 1,
/* The following two flags should only be set when the flag above is
set. */
/* This indicates a pure virtual member function, i.e., one that is
declared with "= 0", even if a body is provided in the
definition. */
GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION = GCC_CP_FLAG_BASE << 2,
/* This indicates a "final" virtual member function. */
GCC_CP_FLAG_FINAL_VIRTUAL_FUNCTION = GCC_CP_FLAG_BASE << 3,
/* This indicates a special member function should have its default
implementation. This either means the function declaration
contains the "= default" tokens, or that the member function was
implicitly generated by the compiler, although the latter use is
discouraged: just let the compiler implicitly introduce it.
A member function defaulted after its first declaration has
slightly different ABI implications from one implicitly generated
or explicitly defaulted at the declaration (and definition)
point. To avoid silent (possibly harmless) violation of the one
definition rule, it is recommended that this flag not be used for
such functions, and that the address of the definition be
supplied instead. */
GCC_CP_FLAG_DEFAULTED_FUNCTION = GCC_CP_FLAG_BASE << 4,
/* This indicates a deleted member function, i.e., one that has been
defined as "= delete" at its declaration point, or one that has
been implicitly defined as deleted (with or without an explicit
"= default" definition).
This should not be used for implicitly-declared member functions
that resolve to deleted definitions, as it may affect the
implicit declaration of other member functions. */
GCC_CP_FLAG_DELETED_FUNCTION = GCC_CP_FLAG_BASE << 5,
/* This indicates a constructor or type-conversion operator declared
as "explicit". */
GCC_CP_FLAG_EXPLICIT_FUNCTION = GCC_CP_FLAG_BASE << 6,
GCC_CP_FLAG_END_FUNCTION,
GCC_CP_FLAG_MASK_FUNCTION = (((GCC_CP_FLAG_END_FUNCTION - 1) << 1)
- GCC_CP_FLAG_BASE),
/* Flags to be used along with GCC_CP_SYMBOL_VARIABLE: */
/* This indicates a variable declared as "constexpr". */
GCC_CP_FLAG_CONSTEXPR_VARIABLE = GCC_CP_FLAG_BASE,
/* This indicates a variable declared as "thread_local". ??? What
should the ADDRESS be? */
GCC_CP_FLAG_THREAD_LOCAL_VARIABLE = GCC_CP_FLAG_BASE << 1,
GCC_CP_FLAG_END_VARIABLE,
GCC_CP_FLAG_MASK_VARIABLE = (((GCC_CP_FLAG_END_VARIABLE - 1) << 1)
- GCC_CP_FLAG_BASE),
/* Flags to be used when defining nonstatic data members of classes
with new_field. */
/* Use this when no flags are present. */
GCC_CP_FLAG_FIELD_NOFLAG = 0,
/* This indicates the field is declared as mutable. */
GCC_CP_FLAG_FIELD_MUTABLE = GCC_CP_FLAG_BASE,
GCC_CP_FLAG_END_FIELD,
GCC_CP_FLAG_MASK_FIELD = (((GCC_CP_FLAG_END_FIELD - 1) << 1)
- GCC_CP_FLAG_BASE),
/* Flags to be used when defining an enum with
start_new_enum_type. */
/* This indicates an enum type without any flags. */
GCC_CP_FLAG_ENUM_NOFLAG = 0,
/* This indicates a scoped enum type. */
GCC_CP_FLAG_ENUM_SCOPED = GCC_CP_FLAG_BASE,
GCC_CP_FLAG_END_ENUM,
GCC_CP_FLAG_MASK_ENUM = (((GCC_CP_FLAG_END_ENUM - 1) << 1)
- GCC_CP_FLAG_BASE),
/* Flags to be used when introducing a class or a class template
with build_decl. */
/* This indicates an enum type without any flags. */
GCC_CP_FLAG_CLASS_NOFLAG = 0,
/* This indicates the class is actually a struct. This has no
effect whatsoever on access control in this interface, since all
class members must have explicit access control bits set, but it
may affect error messages. */
GCC_CP_FLAG_CLASS_IS_STRUCT = GCC_CP_FLAG_BASE,
GCC_CP_FLAG_END_CLASS,
GCC_CP_FLAG_MASK_CLASS = (((GCC_CP_FLAG_END_CLASS - 1) << 1)
- GCC_CP_FLAG_BASE),
/* Flags to be used when introducing a virtual base class in a
gcc_vbase_array. */
/* This indicates an enum type without any flags. */
GCC_CP_FLAG_BASECLASS_NOFLAG = 0,
/* This indicates the class is actually a struct. This has no
effect whatsoever on access control in this interface, since all
class members must have explicit access control bits set, but it
may affect error messages. */
GCC_CP_FLAG_BASECLASS_VIRTUAL = GCC_CP_FLAG_BASE,
GCC_CP_FLAG_END_BASECLASS,
GCC_CP_FLAG_MASK_BASECLASS = (((GCC_CP_FLAG_END_BASECLASS - 1) << 1)
- GCC_CP_FLAG_BASE),
GCC_CP_FLAG_MASK = (GCC_CP_FLAG_MASK_FUNCTION
| GCC_CP_FLAG_MASK_VARIABLE
| GCC_CP_FLAG_MASK_FIELD
| GCC_CP_FLAG_MASK_ENUM
| GCC_CP_FLAG_MASK_CLASS
| GCC_CP_FLAG_MASK_BASECLASS
)
};
/* 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;
/* Flags for each base class. Used to indicate access control and
virtualness. */
enum gcc_cp_symbol_kind *flags;
};
/* This enumerates the types of symbols that GCC might request from
GDB. */
enum gcc_cp_oracle_request
{
/* An identifier in namespace scope -- type, variable, function,
namespace, template. All namespace-scoped symbols with the
requested name, in any namespace (including the global
namespace), should be defined in response to this request. */
GCC_CP_ORACLE_IDENTIFIER
};
/* The type of the function called by GCC to ask GDB for a symbol's
definition. DATUM is an arbitrary value supplied when the oracle
function is registered. CONTEXT is the GCC context in which the
request is being made. REQUEST specifies what sort of symbol is
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);
/* 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);
/* The type of the function called by GCC to ask GDB to enter or leave
the user expression scope. */
typedef void gcc_cp_enter_leave_user_expr_scope_function (void *datum,
struct gcc_cp_context
*context);
/* The vtable used by the C front end. */
struct gcc_cp_fe_vtable
{
/* The version of the C interface. The value is one of the
gcc_cp_api_version constants. */
unsigned int cp_version;
/* Set the callbacks for this context.
The binding oracle is called whenever the C++ parser needs to
look up a symbol. This gives the caller a chance to lazily
instantiate symbols using other parts of the gcc_cp_fe_interface
API. The symbol is looked up without a scope, and the oracle
must supply a definition for ALL namespace-scoped definitions
bound to the symbol.
The address oracle is called whenever the C++ parser needs to
look up a symbol. This may be called for symbols not provided by
the symbol oracle, such as built-in functions where GCC provides
the declaration; other internal symbols, such as those related
with thunks, rtti, and virtual tables are likely to be queried
through this interface too. The identifier is a mangled symbol
name.
DATUM is an arbitrary piece of data that is passed back verbatim
to the callbacks in requests. */
void (*set_callbacks) (struct gcc_cp_context *self,
gcc_cp_oracle_function *binding_oracle,
gcc_cp_symbol_address_function *address_oracle,
gcc_cp_enter_leave_user_expr_scope_function *enter_scope,
gcc_cp_enter_leave_user_expr_scope_function *leave_scope,
void *datum);
#define GCC_METHOD0(R, N) \
R (*N) (struct gcc_cp_context *);
#define GCC_METHOD1(R, N, A) \
R (*N) (struct gcc_cp_context *, A);
#define GCC_METHOD2(R, N, A, B) \
R (*N) (struct gcc_cp_context *, A, B);
#define GCC_METHOD3(R, N, A, B, C) \
R (*N) (struct gcc_cp_context *, A, B, C);
#define GCC_METHOD4(R, N, A, B, C, D) \
R (*N) (struct gcc_cp_context *, A, B, C, D);
#define GCC_METHOD5(R, N, A, B, C, D, E) \
R (*N) (struct gcc_cp_context *, A, B, C, D, E);
#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
R (*N) (struct gcc_cp_context *, A, B, C, D, E, F, G);
#include "gcc-cp-fe.def"
#undef GCC_METHOD0
#undef GCC_METHOD1
#undef GCC_METHOD2
#undef GCC_METHOD3
#undef GCC_METHOD4
#undef GCC_METHOD5
#undef GCC_METHOD7
};
/* The C front end object. */
struct gcc_cp_context
{
/* Base class. */
struct gcc_base_context base;
/* Our vtable. This is a separate field because this is simpler
than implementing a vtable inheritance scheme in C. */
const struct gcc_cp_fe_vtable *cp_ops;
};
/* The name of the .so that the compiler builds. We dlopen this
later. */
#define GCC_CP_FE_LIBCC libcc1.so
/* The compiler exports a single initialization function. This macro
holds its name as a symbol. */
#define GCC_CP_FE_CONTEXT gcc_cp_fe_context
/* The type of the initialization function. The caller passes in the
desired base version and desired C-specific version. If the
request can be satisfied, a compatible gcc_context object will be
returned. Otherwise, the function returns NULL. */
typedef struct gcc_cp_context *gcc_cp_fe_context_function
(enum gcc_base_api_version,
enum gcc_cp_api_version);
#ifdef __cplusplus
}
#endif
#endif /* GCC_CP_INTERFACE_H */

View File

@ -169,6 +169,20 @@ struct gcc_base_context
const struct gcc_base_vtable *ops;
};
/* An array of types used for creating function types in multiple
languages. */
struct gcc_type_array
{
/* Number of elements. */
int n_elements;
/* The elements. */
gcc_type *elements;
};
/* The name of the dummy wrapper function generated by gdb. */
#define GCC_FE_WRAPPER_FUNCTION "_gdb_expr"

View File

@ -1,3 +1,82 @@
2017-01-30 Alexandre Oliva <aoliva@redhat.com>
Introduce C++ support.
* Makefile.am (AM_CPPFLAGS): Move some -I flags to...
(CPPFLAGS_FOR_C_FAMILY, CPPFLAGS_FOR_C, CPPFLAGS_FOR_CXX): ...
new macros.
(plugin_LTLIBRARIES): Add libcp1plugin.la.
(BUILT_SOURCES, MOSTLYCLEANFILES): Add...
(cp-compiler-name.h): ... this. New.
(c-compiler-name.h): Rename all over from...
(compiler-name.h): ... this. Create it atomically.
(marshall_c_source, marshall_cxx_source): New macros.
(libcc1plugin_la_SOURCES): Rename plugin.cc to libcc1plugin.cc.
Add marshall_c_source expansion.
(libcc1plugin.lo_CPPFLAGS): New macro.
(libcp1plugin_la_LDFLAGS): Likewise.
(libcp1plugin_la_SOURCES): Likewise.
(libcp1plugin.lo_CPPFLAGS): Likewise.
(libcp1plugin_la_LIBADD): Likewise.
(libcp1plugin_la_DEPENDENCIES): Likewise.
(libcp1plugin_la_LINK): Likewise.
(libcc1_la_SOURCES): Added marshall_c_source and
marshall_cxx_source expansions.
* Makefile.in: Rebuild.
* compiler-name.h: Rename all over to...
* c-compiler-name.h: ... this. Define C_COMPILER_NAME instead
of COMPILER_NAME.
* plugin.cc: Rename all over to...
* libcc1plugin.cc: ... this. Include marshall-c.hh.
(address_rewriter): Drop cleaning up of VLA sizes.
(plugin_build_decl): Mark decls as external.
(plugin_tagbind): Propagate name to all variants.
(build_anonymous_node): New.
(plugin_build_record_type): Use it instead of make_node.
(plugin_build_union_type): Likewise.
(plugin_build_enum_type): Likewise.
(plugin_finish_record_or_union): Update all type variants.
(safe_lookup_builtin_type): New.
(plugin_int_check): Factor out of, and add checks to, ...
(plugin_int_type): ... this. Rename to...
(plugin_int_type_v0): ... this.
(plugin_int_type): New interface, new implementation.
(plugin_char_type): New.
(plugin_float_type_v0): Rename from...
(plugin_float_type): ... this. New interface, new implementation.
(plugin_init): Bump handshake version.
* libcc1.cc: Include marshall-c.hh. Drop gcc-interface.h.
(call_binding_oracle): Rename to...
(c_call_binding_oracle): ... this, into anonymous namespace.
(call_symbol_address): Rename to...
(c_call_symbol_address): ... this, likewise.
(GCC_METHOD#): Move methods into cc1plugin::c:: namespace.
(libcc1::compiler::find): Refer to C_COMPILER_NAME.
(fork_exec): Bump to GCC_C_FE_VERSION_1.
(libcc1_compile): Prefix callbacks with c_.
(gcc_c_fe_context): Accept GCC_C_FE_VERSION_1.
* libcc1.sym: Export gcc_cp_fe_context.
* libcp1.cc: New, mostly copied and adjusted from libcc1.cc.
* libcp1plugin.cc: New, initially copied from libcc1plugin.cc.
* libcp1plugin.sym: New.
* marshall-c.hh: New. Move C-specific types from...
* marshall.cc: ... this.
(cc1_plugin::marshall_array_start): New.
(cc1_plugin::marshall_array_elmts): New.
(cc1_plugin::marshall for gcc_type_array): Use the above.
(cc1_plugin::unmarshall_array_start): New.
(cc1_plugin::unmarshall_array_elmts): New.
(cc1_plugin::unmarshall for gcc_type_array): Use the above.
* marshall.hh: Declare the new array building blocks.
Drop C-specific unmarshall declarations.
* marshall-cp.hh: New.
* names.cc (GCC_METHOD#): Add LANG:: to method names.
(LANG): Define while including gcc-c-fe.def and gcc-cp-fe.def.
* names.hh: Include gcc-c-fe.def and gcc-cp-fe.def in the
corresponding namespaces.
* rpc.hh: Don't include marshall.hh.
[GCC_CP_INTERFACE_H] (argument_wrapper): Specialize for
gcc_vbase_array, gcc_cp_template_args, gcc_cp_function_args.
2017-01-30 Jan Kratochvil <jan.kratochvil@redhat.com>
* findcomp.cc: Include system.h.

View File

@ -19,9 +19,11 @@
ACLOCAL_AMFLAGS = -I .. -I ../config
gcc_build_dir = ../gcc
AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
-I $(gcc_build_dir) -I$(srcdir)/../gcc \
-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
-I $(srcdir)/../libcpp/include $(GMPINC)
-I $(gcc_build_dir) -I$(srcdir)/../gcc $($@_CPPFLAGS) $(GMPINC)
CPPFLAGS_FOR_C_FAMILY = -I $(srcdir)/../gcc/c-family \
-I $(srcdir)/../libcpp/include
CPPFLAGS_FOR_C = $(CPPFLAGS_FOR_C_FAMILY) -I $(srcdir)/../gcc/c
CPPFLAGS_FOR_CXX = $(CPPFLAGS_FOR_C_FAMILY) -I $(srcdir)/../gcc/cp
AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR) $(visibility)
override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
@ -39,33 +41,57 @@ plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
cc1libdir = $(libdir)/$(libsuffix)
if ENABLE_PLUGIN
plugin_LTLIBRARIES = libcc1plugin.la
plugin_LTLIBRARIES = libcc1plugin.la libcp1plugin.la
cc1lib_LTLIBRARIES = libcc1.la
endif
BUILT_SOURCES = compiler-name.h
MOSTLYCLEANFILES = compiler-name.h
BUILT_SOURCES = c-compiler-name.h cp-compiler-name.h
MOSTLYCLEANFILES = c-compiler-name.h cp-compiler-name.h
# Put this in a header so we don't run sed for each compilation. This
# is also simpler to debug as one can easily see the constant.
compiler-name.h: Makefile
echo "#define COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > $@
# FIXME: compute it in configure.ac and output it in config.status, or
# introduce timestamp files for some indirection to avoid rebuilding it
# every time.
c-compiler-name.h: Makefile
-rm -f $@T
echo "#define C_COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > $@T
mv $@T $@ # $(SHELL) $(srcdir)/../move-if-change $@T $@
cp-compiler-name.h: Makefile
-rm -f $@T
echo "#define CP_COMPILER_NAME \"`echo g++ | sed '$(transform)'`\"" > $@T
mv $@T $@ # $(SHELL) $(srcdir)/../move-if-change $@T $@
shared_source = callbacks.cc callbacks.hh connection.cc connection.hh \
marshall.cc marshall.hh rpc.hh status.hh
marshall_c_source = marshall-c.hh
marshall_cxx_source = marshall-cp.hh
libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
libcc1plugin_la_SOURCES = libcc1plugin.cc $(shared_source) $(marshall_c_source)
libcc1plugin.lo_CPPFLAGS = $(CPPFLAGS_FOR_C)
libcc1plugin_la_LIBADD = $(libiberty)
libcc1plugin_la_DEPENDENCIES = $(libiberty_dep)
libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
libcp1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcp1plugin.sym
libcp1plugin_la_SOURCES = libcp1plugin.cc $(shared_source) $(marshall_cxx_source)
libcp1plugin.lo_CPPFLAGS = $(CPPFLAGS_FOR_CXX)
libcp1plugin_la_LIBADD = $(libiberty)
libcp1plugin_la_DEPENDENCIES = $(libiberty_dep)
libcp1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libcp1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
libcc1_la_SOURCES = findcomp.cc libcc1.cc libcp1.cc \
names.cc names.hh $(shared_source) \
$(marshall_c_source) $(marshall_cxx_source)
libcc1_la_LIBADD = $(libiberty)
libcc1_la_DEPENDENCIES = $(libiberty_dep)
libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \

View File

@ -105,12 +105,19 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(cc1libdir)" "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(cc1lib_LTLIBRARIES) $(plugin_LTLIBRARIES)
am__objects_1 = callbacks.lo connection.lo marshall.lo
am_libcc1_la_OBJECTS = findcomp.lo libcc1.lo names.lo $(am__objects_1)
am__objects_2 =
am_libcc1_la_OBJECTS = findcomp.lo libcc1.lo libcp1.lo names.lo \
$(am__objects_1) $(am__objects_2) $(am__objects_2)
libcc1_la_OBJECTS = $(am_libcc1_la_OBJECTS)
@ENABLE_PLUGIN_TRUE@am_libcc1_la_rpath = -rpath $(cc1libdir)
am_libcc1plugin_la_OBJECTS = plugin.lo $(am__objects_1)
am_libcc1plugin_la_OBJECTS = libcc1plugin.lo $(am__objects_1) \
$(am__objects_2)
libcc1plugin_la_OBJECTS = $(am_libcc1plugin_la_OBJECTS)
@ENABLE_PLUGIN_TRUE@am_libcc1plugin_la_rpath = -rpath $(plugindir)
am_libcp1plugin_la_OBJECTS = libcp1plugin.lo $(am__objects_1) \
$(am__objects_2)
libcp1plugin_la_OBJECTS = $(am_libcp1plugin_la_OBJECTS)
@ENABLE_PLUGIN_TRUE@am_libcp1plugin_la_rpath = -rpath $(plugindir)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/../depcomp
am__depfiles_maybe = depfiles
@ -133,7 +140,8 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libcc1_la_SOURCES) $(libcc1plugin_la_SOURCES)
SOURCES = $(libcc1_la_SOURCES) $(libcc1plugin_la_SOURCES) \
$(libcp1plugin_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@ -277,10 +285,13 @@ visibility = @visibility@
ACLOCAL_AMFLAGS = -I .. -I ../config
gcc_build_dir = ../gcc
AM_CPPFLAGS = -I $(srcdir)/../include -I $(srcdir)/../libgcc \
-I $(gcc_build_dir) -I$(srcdir)/../gcc \
-I $(srcdir)/../gcc/c -I $(srcdir)/../gcc/c-family \
-I $(srcdir)/../libcpp/include $(GMPINC)
-I $(gcc_build_dir) -I$(srcdir)/../gcc $($@_CPPFLAGS) $(GMPINC)
CPPFLAGS_FOR_C_FAMILY = -I $(srcdir)/../gcc/c-family \
-I $(srcdir)/../libcpp/include
CPPFLAGS_FOR_C = $(CPPFLAGS_FOR_C_FAMILY) -I $(srcdir)/../gcc/c
CPPFLAGS_FOR_CXX = $(CPPFLAGS_FOR_C_FAMILY) -I $(srcdir)/../gcc/cp
AM_CXXFLAGS = $(WARN_FLAGS) $(WERROR) $(visibility)
# Can be simplified when libiberty becomes a normal convenience library.
libiberty_normal = ../libiberty/libiberty.a
@ -294,24 +305,39 @@ libiberty = $(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
libiberty_dep = $(patsubst $(Wc)%,%,$(libiberty))
plugindir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/plugin
cc1libdir = $(libdir)/$(libsuffix)
@ENABLE_PLUGIN_TRUE@plugin_LTLIBRARIES = libcc1plugin.la
@ENABLE_PLUGIN_TRUE@plugin_LTLIBRARIES = libcc1plugin.la libcp1plugin.la
@ENABLE_PLUGIN_TRUE@cc1lib_LTLIBRARIES = libcc1.la
BUILT_SOURCES = compiler-name.h
MOSTLYCLEANFILES = compiler-name.h
BUILT_SOURCES = c-compiler-name.h cp-compiler-name.h
MOSTLYCLEANFILES = c-compiler-name.h cp-compiler-name.h
shared_source = callbacks.cc callbacks.hh connection.cc connection.hh \
marshall.cc marshall.hh rpc.hh status.hh
marshall_c_source = marshall-c.hh
marshall_cxx_source = marshall-cp.hh
libcc1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1plugin.sym
libcc1plugin_la_SOURCES = plugin.cc $(shared_source)
libcc1plugin_la_SOURCES = libcc1plugin.cc $(shared_source) $(marshall_c_source)
libcc1plugin.lo_CPPFLAGS = $(CPPFLAGS_FOR_C)
libcc1plugin_la_LIBADD = $(libiberty)
libcc1plugin_la_DEPENDENCIES = $(libiberty_dep)
libcc1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libcc1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
libcp1plugin_la_LDFLAGS = -module -export-symbols $(srcdir)/libcp1plugin.sym
libcp1plugin_la_SOURCES = libcp1plugin.cc $(shared_source) $(marshall_cxx_source)
libcp1plugin.lo_CPPFLAGS = $(CPPFLAGS_FOR_CXX)
libcp1plugin_la_LIBADD = $(libiberty)
libcp1plugin_la_DEPENDENCIES = $(libiberty_dep)
libcp1plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(libcp1plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
libcc1_la_LDFLAGS = -module -export-symbols $(srcdir)/libcc1.sym
libcc1_la_SOURCES = findcomp.cc libcc1.cc names.cc names.hh $(shared_source)
libcc1_la_SOURCES = findcomp.cc libcc1.cc libcp1.cc \
names.cc names.hh $(shared_source) \
$(marshall_c_source) $(marshall_cxx_source)
libcc1_la_LIBADD = $(libiberty)
libcc1_la_DEPENDENCIES = $(libiberty_dep)
libcc1_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@ -440,6 +466,8 @@ libcc1.la: $(libcc1_la_OBJECTS) $(libcc1_la_DEPENDENCIES) $(EXTRA_libcc1_la_DEPE
$(libcc1_la_LINK) $(am_libcc1_la_rpath) $(libcc1_la_OBJECTS) $(libcc1_la_LIBADD) $(LIBS)
libcc1plugin.la: $(libcc1plugin_la_OBJECTS) $(libcc1plugin_la_DEPENDENCIES) $(EXTRA_libcc1plugin_la_DEPENDENCIES)
$(libcc1plugin_la_LINK) $(am_libcc1plugin_la_rpath) $(libcc1plugin_la_OBJECTS) $(libcc1plugin_la_LIBADD) $(LIBS)
libcp1plugin.la: $(libcp1plugin_la_OBJECTS) $(libcp1plugin_la_DEPENDENCIES) $(EXTRA_libcp1plugin_la_DEPENDENCIES)
$(libcp1plugin_la_LINK) $(am_libcp1plugin_la_rpath) $(libcp1plugin_la_OBJECTS) $(libcp1plugin_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@ -451,9 +479,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findcomp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcc1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcc1plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcp1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcp1plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/marshall.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@
.cc.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@ -674,8 +704,18 @@ override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
# Put this in a header so we don't run sed for each compilation. This
# is also simpler to debug as one can easily see the constant.
compiler-name.h: Makefile
echo "#define COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > $@
# FIXME: compute it in configure.ac and output it in config.status, or
# introduce timestamp files for some indirection to avoid rebuilding it
# every time.
c-compiler-name.h: Makefile
-rm -f $@T
echo "#define C_COMPILER_NAME \"`echo gcc | sed '$(transform)'`\"" > $@T
mv $@T $@ # $(SHELL) $(srcdir)/../move-if-change $@T $@
cp-compiler-name.h: Makefile
-rm -f $@T
echo "#define CP_COMPILER_NAME \"`echo g++ | sed '$(transform)'`\"" > $@T
mv $@T $@ # $(SHELL) $(srcdir)/../move-if-change $@T $@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View File

@ -29,15 +29,15 @@ along with GCC; see the file COPYING3. If not see
#include <sys/stat.h>
#include <stdlib.h>
#include <sstream>
#include "marshall-c.hh"
#include "rpc.hh"
#include "connection.hh"
#include "names.hh"
#include "callbacks.hh"
#include "gcc-interface.h"
#include "libiberty.h"
#include "xregex.h"
#include "findcomp.hh"
#include "compiler-name.h"
#include "c-compiler-name.h"
#include "intl.h"
struct libcc1;
@ -164,30 +164,35 @@ libcc1::~libcc1 ()
// This is a wrapper function that is called by the RPC system and
// that then forwards the call to the library user. Note that the
// return value is not used; the type cannot be 'void' due to
// limitations in our simple RPC.
int
call_binding_oracle (cc1_plugin::connection *conn,
enum gcc_c_oracle_request request,
const char *identifier)
{
libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
// Enclose these functions in an anonymous namespace because they
// shouldn't be exported, but they can't be static because they're
// used as template arguments.
namespace {
// This is a wrapper function that is called by the RPC system and
// that then forwards the call to the library user. Note that the
// return value is not used; the type cannot be 'void' due to
// limitations in our simple RPC.
int
c_call_binding_oracle (cc1_plugin::connection *conn,
enum gcc_c_oracle_request request,
const char *identifier)
{
libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
self->binding_oracle (self->oracle_datum, self, request, identifier);
return 1;
}
self->binding_oracle (self->oracle_datum, self, request, identifier);
return 1;
}
// This is a wrapper function that is called by the RPC system and
// that then forwards the call to the library user.
gcc_address
call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
{
libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
// This is a wrapper function that is called by the RPC system and
// that then forwards the call to the library user.
gcc_address
c_call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
{
libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
return self->address_oracle (self->oracle_datum, self, identifier);
}
return self->address_oracle (self->oracle_datum, self, identifier);
}
} /* anonymous namespace */
@ -298,19 +303,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"
@ -377,13 +382,12 @@ libcc1::compiler::find (std::string &compiler ATTRIBUTE_UNUSED) const
char *
libcc1::compiler_triplet_regexp::find (std::string &compiler) const
{
std::string rx = make_regexp (triplet_regexp_.c_str (), COMPILER_NAME);
std::string rx = make_regexp (triplet_regexp_.c_str (), C_COMPILER_NAME);
if (self_->verbose)
fprintf (stderr, _("searching for compiler matching regex %s\n"),
rx.c_str());
regex_t triplet;
int code;
code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
int code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
if (code != 0)
{
size_t len = regerror (code, &triplet, NULL, 0);
@ -532,7 +536,7 @@ fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
cc1_plugin::status result = cc1_plugin::FAIL;
if (self->connection->send ('H')
&& ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_0))
&& ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_1))
result = self->connection->wait_for_query ();
close (spair_fds[0]);
@ -601,12 +605,12 @@ libcc1_compile (struct gcc_base_context *s,
= cc1_plugin::callback<int,
enum gcc_c_oracle_request,
const char *,
call_binding_oracle>;
c_call_binding_oracle>;
self->connection->add_callback ("binding_oracle", fun);
fun = cc1_plugin::callback<gcc_address,
const char *,
call_symbol_address>;
c_call_symbol_address>;
self->connection->add_callback ("address_oracle", fun);
char **argv = new (std::nothrow) char *[self->args.size () + 1];
@ -663,7 +667,7 @@ gcc_c_fe_context (enum gcc_base_api_version base_version,
enum gcc_c_api_version c_version)
{
if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1)
|| c_version != GCC_C_FE_VERSION_0)
|| (c_version != GCC_C_FE_VERSION_0 && c_version != GCC_C_FE_VERSION_1))
return NULL;
return new libcc1 (&vtable, &c_vtable);

View File

@ -1 +1,2 @@
gcc_c_fe_context
gcc_cp_fe_context

View File

@ -63,6 +63,7 @@
#include "callbacks.hh"
#include "connection.hh"
#include "marshall-c.hh"
#include "rpc.hh"
#ifdef __GNUC__
@ -298,18 +299,7 @@ address_rewriter (tree *in, int *walk_subtrees, void *arg)
value.decl = *in;
decl_addr_value *found_value = ctx->address_map.find (&value);
if (found_value != NULL)
{
// At this point we don't need VLA sizes for gdb-supplied
// variables, and having them here confuses later passes, so we
// drop them.
if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (*in)))
{
TREE_TYPE (*in)
= build_array_type_nelts (TREE_TYPE (TREE_TYPE (*in)), 1);
DECL_SIZE (*in) = TYPE_SIZE (TREE_TYPE (*in));
DECL_SIZE_UNIT (*in) = TYPE_SIZE_UNIT (TREE_TYPE (*in));
}
}
;
else if (DECL_IS_BUILTIN (*in))
{
gcc_address address;
@ -417,6 +407,7 @@ plugin_build_decl (cc1_plugin::connection *self,
{
decl_addr_value value;
DECL_EXTERNAL (decl) = 1;
value.decl = decl;
if (substitution_name != NULL)
{
@ -456,8 +447,15 @@ plugin_tagbind (cc1_plugin::connection *self,
const char *filename, unsigned int line_number)
{
plugin_context *ctx = static_cast<plugin_context *> (self);
tree t = convert_in (tagged_type), x;
c_pushtag (ctx->get_source_location (filename, line_number),
get_identifier (name), convert_in (tagged_type));
get_identifier (name), t);
/* Propagate the newly-added type name so that previously-created
variant types are not disconnected from their main variants. */
for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
TYPE_NAME (x) = TYPE_NAME (t);
return 1;
}
@ -469,18 +467,30 @@ plugin_build_pointer_type (cc1_plugin::connection *,
return convert_out (build_pointer_type (convert_in (base_type)));
}
// TYPE_NAME needs to be a valid pointer, even if there is no name available.
static tree
build_anonymous_node (enum tree_code code)
{
tree node = make_node (code);
tree type_decl = build_decl (input_location, TYPE_DECL, NULL_TREE, node);
TYPE_NAME (node) = type_decl;
TYPE_STUB_DECL (node) = type_decl;
return node;
}
gcc_type
plugin_build_record_type (cc1_plugin::connection *self)
{
plugin_context *ctx = static_cast<plugin_context *> (self);
return convert_out (ctx->preserve (make_node (RECORD_TYPE)));
return convert_out (ctx->preserve (build_anonymous_node (RECORD_TYPE)));
}
gcc_type
plugin_build_union_type (cc1_plugin::connection *self)
{
plugin_context *ctx = static_cast<plugin_context *> (self);
return convert_out (ctx->preserve (make_node (UNION_TYPE)));
return convert_out (ctx->preserve (build_anonymous_node (UNION_TYPE)));
}
int
@ -565,6 +575,23 @@ plugin_finish_record_or_union (cc1_plugin::connection *,
// FIXME we have no idea about TYPE_PACKED
}
tree t = record_or_union_type, x;
for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
{
/* Like finish_struct, update the qualified variant types. */
TYPE_FIELDS (x) = TYPE_FIELDS (t);
TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
/* We copy these fields too. */
SET_TYPE_ALIGN (x, TYPE_ALIGN (t));
TYPE_SIZE (x) = TYPE_SIZE (t);
TYPE_SIZE_UNIT (x) = TYPE_SIZE_UNIT (t);
if (x != record_or_union_type)
compute_record_mode (x);
}
return 1;
}
@ -577,7 +604,7 @@ plugin_build_enum_type (cc1_plugin::connection *self,
if (underlying_int_type == error_mark_node)
return convert_out (error_mark_node);
tree result = make_node (ENUMERAL_TYPE);
tree result = build_anonymous_node (ENUMERAL_TYPE);
TYPE_PRECISION (result) = TYPE_PRECISION (underlying_int_type);
TYPE_UNSIGNED (result) = TYPE_UNSIGNED (underlying_int_type);
@ -667,16 +694,39 @@ plugin_build_function_type (cc1_plugin::connection *self,
return convert_out (ctx->preserve (result));
}
gcc_type
plugin_int_type (cc1_plugin::connection *self,
int is_unsigned, unsigned long size_in_bytes)
/* Return a builtin type associated with BUILTIN_NAME. */
static tree
safe_lookup_builtin_type (const char *builtin_name)
{
tree result = NULL_TREE;
if (!builtin_name)
return result;
result = identifier_global_value (get_identifier (builtin_name));
if (!result)
return result;
gcc_assert (TREE_CODE (result) == TYPE_DECL);
result = TREE_TYPE (result);
return result;
}
static gcc_type
plugin_int_check (cc1_plugin::connection *self,
int is_unsigned, unsigned long size_in_bytes,
tree result)
{
tree result = c_common_type_for_size (BITS_PER_UNIT * size_in_bytes,
is_unsigned);
if (result == NULL_TREE)
result = error_mark_node;
else
{
gcc_assert (!TYPE_UNSIGNED (result) == !is_unsigned);
gcc_assert (TREE_CODE (TYPE_SIZE (result)) == INTEGER_CST);
gcc_assert (TYPE_PRECISION (result) == BITS_PER_UNIT * size_in_bytes);
plugin_context *ctx = static_cast<plugin_context *> (self);
ctx->preserve (result);
}
@ -684,7 +734,37 @@ plugin_int_type (cc1_plugin::connection *self,
}
gcc_type
plugin_float_type (cc1_plugin::connection *,
plugin_int_type_v0 (cc1_plugin::connection *self,
int is_unsigned, unsigned long size_in_bytes)
{
tree result = c_common_type_for_size (BITS_PER_UNIT * size_in_bytes,
is_unsigned);
return plugin_int_check (self, is_unsigned, size_in_bytes, result);
}
gcc_type
plugin_int_type (cc1_plugin::connection *self,
int is_unsigned, unsigned long size_in_bytes,
const char *builtin_name)
{
if (!builtin_name)
return plugin_int_type_v0 (self, is_unsigned, size_in_bytes);
tree result = safe_lookup_builtin_type (builtin_name);
gcc_assert (!result || TREE_CODE (result) == INTEGER_TYPE);
return plugin_int_check (self, is_unsigned, size_in_bytes, result);
}
gcc_type
plugin_char_type (cc1_plugin::connection *)
{
return convert_out (char_type_node);
}
gcc_type
plugin_float_type_v0 (cc1_plugin::connection *,
unsigned long size_in_bytes)
{
if (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (float_type_node))
@ -696,6 +776,25 @@ plugin_float_type (cc1_plugin::connection *,
return convert_out (error_mark_node);
}
gcc_type
plugin_float_type (cc1_plugin::connection *self,
unsigned long size_in_bytes,
const char *builtin_name)
{
if (!builtin_name)
return plugin_float_type_v0 (self, size_in_bytes);
tree result = safe_lookup_builtin_type (builtin_name);
if (!result)
return convert_out (error_mark_node);
gcc_assert (TREE_CODE (result) == REAL_TYPE);
gcc_assert (BITS_PER_UNIT * size_in_bytes == TYPE_PRECISION (result));
return convert_out (result);
}
gcc_type
plugin_void_type (cc1_plugin::connection *)
{
@ -848,7 +947,7 @@ plugin_init (struct plugin_name_args *plugin_info,
|| ! ::cc1_plugin::unmarshall (current_context, &version))
fatal_error (input_location,
"%s: handshake failed", plugin_info->base_name);
if (version != GCC_C_FE_VERSION_0)
if (version != GCC_C_FE_VERSION_1)
fatal_error (input_location,
"%s: unknown version in handshake", plugin_info->base_name);

706
libcc1/libcp1.cc Normal file
View File

@ -0,0 +1,706 @@
/* The library used by gdb.
Copyright (C) 2014-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <cc1plugin-config.h>
#include <vector>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sstream>
#include "marshall-cp.hh"
#include "rpc.hh"
#include "connection.hh"
#include "names.hh"
#include "callbacks.hh"
#include "libiberty.h"
#include "xregex.h"
#include "findcomp.hh"
#include "cp-compiler-name.h"
#include "intl.h"
struct libcp1;
class libcp1_connection;
// The C compiler context that we hand back to our caller.
struct libcp1 : public gcc_cp_context
{
libcp1 (const gcc_base_vtable *, const gcc_cp_fe_vtable *);
~libcp1 ();
// A convenience function to print something.
void print (const char *str)
{
this->print_function (this->print_datum, str);
}
libcp1_connection *connection;
gcc_cp_oracle_function *binding_oracle;
gcc_cp_symbol_address_function *address_oracle;
gcc_cp_enter_leave_user_expr_scope_function *enter_scope;
gcc_cp_enter_leave_user_expr_scope_function *leave_scope;
void *oracle_datum;
void (*print_function) (void *datum, const char *message);
void *print_datum;
std::vector<std::string> args;
std::string source_file;
/* Non-zero as an equivalent to gcc driver option "-v". */
bool verbose;
/* Compiler to set by set_triplet_regexp or set_driver_filename. */
class compiler
{
protected:
libcp1 *self_;
public:
compiler (libcp1 *self) : self_ (self)
{
}
virtual char *find (std::string &compiler) const;
virtual ~compiler ()
{
}
} *compilerp;
/* Compiler to set by set_triplet_regexp. */
class compiler_triplet_regexp : public compiler
{
private:
std::string triplet_regexp_;
public:
virtual char *find (std::string &compiler) const;
compiler_triplet_regexp (libcp1 *self, std::string triplet_regexp)
: compiler (self), triplet_regexp_ (triplet_regexp)
{
}
virtual ~compiler_triplet_regexp ()
{
}
};
/* Compiler to set by set_driver_filename. */
class compiler_driver_filename : public compiler
{
private:
std::string driver_filename_;
public:
virtual char *find (std::string &compiler) const;
compiler_driver_filename (libcp1 *self, std::string driver_filename)
: compiler (self), driver_filename_ (driver_filename)
{
}
virtual ~compiler_driver_filename ()
{
}
};
};
// A local subclass of connection that holds a back-pointer to the
// gcc_c_context object that we provide to our caller.
class libcp1_connection : public cc1_plugin::connection
{
public:
libcp1_connection (int fd, int aux_fd, libcp1 *b)
: connection (fd, aux_fd),
back_ptr (b)
{
}
virtual void print (const char *buf)
{
back_ptr->print (buf);
}
libcp1 *back_ptr;
};
libcp1::libcp1 (const gcc_base_vtable *v,
const gcc_cp_fe_vtable *cv)
: connection (NULL),
binding_oracle (NULL),
address_oracle (NULL),
oracle_datum (NULL),
print_function (NULL),
print_datum (NULL),
args (),
source_file (),
verbose (false),
compilerp (new libcp1::compiler (this))
{
base.ops = v;
cp_ops = cv;
}
libcp1::~libcp1 ()
{
delete connection;
delete compilerp;
}
// Enclose these functions in an anonymous namespace because they
// shouldn't be exported, but they can't be static because they're
// used as template arguments.
namespace {
// This is a wrapper function that is called by the RPC system and
// that then forwards the call to the library user. Note that the
// return value is not used; the type cannot be 'void' due to
// limitations in our simple RPC.
int
cp_call_binding_oracle (cc1_plugin::connection *conn,
enum gcc_cp_oracle_request request,
const char *identifier)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
self->binding_oracle (self->oracle_datum, self, request, identifier);
return 1;
}
// This is a wrapper function that is called by the RPC system and
// that then forwards the call to the library user.
gcc_address
cp_call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
return self->address_oracle (self->oracle_datum, self, identifier);
}
int
cp_call_enter_scope (cc1_plugin::connection *conn)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
self->enter_scope (self->oracle_datum, self);
return 1;
}
int
cp_call_leave_scope (cc1_plugin::connection *conn)
{
libcp1 *self = ((libcp1_connection *) conn)->back_ptr;
self->leave_scope (self->oracle_datum, self);
return 1;
}
} /* anonymous namespace */
static void
set_callbacks (struct gcc_cp_context *s,
gcc_cp_oracle_function *binding_oracle,
gcc_cp_symbol_address_function *address_oracle,
gcc_cp_enter_leave_user_expr_scope_function *enter_scope,
gcc_cp_enter_leave_user_expr_scope_function *leave_scope,
void *datum)
{
libcp1 *self = (libcp1 *) s;
self->binding_oracle = binding_oracle;
self->address_oracle = address_oracle;
self->enter_scope = enter_scope;
self->leave_scope = leave_scope;
self->oracle_datum = datum;
}
// Instances of these rpc<> template functions are installed into the
// "cp_vtable". These functions are parameterized by type and method
// name and forward the call via the connection.
template<typename R, const char *&NAME>
R rpc (struct gcc_cp_context *s)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result))
return 0;
return result;
}
template<typename R, const char *&NAME, typename A>
R rpc (struct gcc_cp_context *s, A arg)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result, arg))
return 0;
return result;
}
template<typename R, const char *&NAME, typename A1, typename A2>
R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
return 0;
return result;
}
template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
return 0;
return result;
}
template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
typename A4>
R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
arg4))
return 0;
return result;
}
template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
typename A4, typename A5>
R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
arg4, arg5))
return 0;
return result;
}
template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
typename A4, typename A5, typename A6, typename A7>
R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
A6 arg6, A7 arg7)
{
libcp1 *self = (libcp1 *) s;
R result;
if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
arg4, arg5, arg6, arg7))
return 0;
return result;
}
static const struct gcc_cp_fe_vtable cp_vtable =
{
GCC_CP_FE_VERSION_0,
set_callbacks,
#define GCC_METHOD0(R, N) \
rpc<R, cc1_plugin::cp::N>,
#define GCC_METHOD1(R, N, A) \
rpc<R, cc1_plugin::cp::N, A>,
#define GCC_METHOD2(R, N, A, B) \
rpc<R, cc1_plugin::cp::N, A, B>,
#define GCC_METHOD3(R, 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::cp::N, A, B, C, D>,
#define GCC_METHOD5(R, 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::cp::N, A, B, C, D, E, F, G>,
#include "gcc-cp-fe.def"
#undef GCC_METHOD0
#undef GCC_METHOD1
#undef GCC_METHOD2
#undef GCC_METHOD3
#undef GCC_METHOD4
#undef GCC_METHOD5
#undef GCC_METHOD7
};
// Construct an appropriate regexp to match the compiler name.
static std::string
make_regexp (const char *triplet_regexp, const char *compiler)
{
std::stringstream buf;
buf << "^" << triplet_regexp << "-";
// Quote the compiler name in case it has something funny in it.
for (const char *p = compiler; *p; ++p)
{
switch (*p)
{
case '.':
case '^':
case '$':
case '*':
case '+':
case '?':
case '(':
case ')':
case '[':
case '{':
case '\\':
case '|':
buf << '\\';
break;
}
buf << *p;
}
buf << "$";
return buf.str ();
}
static void
libcp1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose)
{
libcp1 *self = (libcp1 *) s;
self->verbose = verbose != 0;
}
char *
libcp1::compiler::find (std::string &compiler ATTRIBUTE_UNUSED) const
{
return xstrdup (_("Compiler has not been specified"));
}
char *
libcp1::compiler_triplet_regexp::find (std::string &compiler) const
{
std::string rx = make_regexp (triplet_regexp_.c_str (), CP_COMPILER_NAME);
if (self_->verbose)
fprintf (stderr, _("searching for compiler matching regex %s\n"),
rx.c_str());
regex_t triplet;
int code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
if (code != 0)
{
size_t len = regerror (code, &triplet, NULL, 0);
char err[len];
regerror (code, &triplet, err, len);
return concat ("Could not compile regexp \"",
rx.c_str (),
"\": ",
err,
(char *) NULL);
}
if (!find_compiler (triplet, &compiler))
{
regfree (&triplet);
return concat ("Could not find a compiler matching \"",
rx.c_str (),
"\"",
(char *) NULL);
}
regfree (&triplet);
if (self_->verbose)
fprintf (stderr, _("found compiler %s\n"), compiler.c_str());
return NULL;
}
char *
libcp1::compiler_driver_filename::find (std::string &compiler) const
{
// Simulate fnotice by fprintf.
if (self_->verbose)
fprintf (stderr, _("using explicit compiler filename %s\n"),
driver_filename_.c_str());
compiler = driver_filename_;
return NULL;
}
static char *
libcp1_set_arguments (struct gcc_base_context *s,
int argc, char **argv)
{
libcp1 *self = (libcp1 *) s;
std::string compiler;
char *errmsg = self->compilerp->find (compiler);
if (errmsg != NULL)
return errmsg;
self->args.push_back (compiler);
for (int i = 0; i < argc; ++i)
self->args.push_back (argv[i]);
return NULL;
}
static char *
libcp1_set_triplet_regexp (struct gcc_base_context *s,
const char *triplet_regexp)
{
libcp1 *self = (libcp1 *) s;
delete self->compilerp;
self->compilerp = new libcp1::compiler_triplet_regexp (self, triplet_regexp);
return NULL;
}
static char *
libcp1_set_driver_filename (struct gcc_base_context *s,
const char *driver_filename)
{
libcp1 *self = (libcp1 *) s;
delete self->compilerp;
self->compilerp = new libcp1::compiler_driver_filename (self,
driver_filename);
return NULL;
}
static char *
libcp1_set_arguments_v0 (struct gcc_base_context *s,
const char *triplet_regexp,
int argc, char **argv)
{
char *errmsg = libcp1_set_triplet_regexp (s, triplet_regexp);
if (errmsg != NULL)
return errmsg;
return libcp1_set_arguments (s, argc, argv);
}
static void
libcp1_set_source_file (struct gcc_base_context *s,
const char *file)
{
libcp1 *self = (libcp1 *) s;
self->source_file = file;
}
static void
libcp1_set_print_callback (struct gcc_base_context *s,
void (*print_function) (void *datum,
const char *message),
void *datum)
{
libcp1 *self = (libcp1 *) s;
self->print_function = print_function;
self->print_datum = datum;
}
static int
fork_exec (libcp1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
{
pid_t child_pid = fork ();
if (child_pid == -1)
{
close (spair_fds[0]);
close (spair_fds[1]);
close (stderr_fds[0]);
close (stderr_fds[1]);
return 0;
}
if (child_pid == 0)
{
// Child.
dup2 (stderr_fds[1], 1);
dup2 (stderr_fds[1], 2);
close (stderr_fds[0]);
close (stderr_fds[1]);
close (spair_fds[0]);
execvp (argv[0], argv);
_exit (127);
}
else
{
// Parent.
close (spair_fds[1]);
close (stderr_fds[1]);
cc1_plugin::status result = cc1_plugin::FAIL;
if (self->connection->send ('H')
&& ::cc1_plugin::marshall (self->connection, GCC_CP_FE_VERSION_0))
result = self->connection->wait_for_query ();
close (spair_fds[0]);
close (stderr_fds[0]);
while (true)
{
int status;
if (waitpid (child_pid, &status, 0) == -1)
{
if (errno != EINTR)
return 0;
}
if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
return 0;
break;
}
if (!result)
return 0;
return 1;
}
}
static int
libcp1_compile (struct gcc_base_context *s,
const char *filename)
{
libcp1 *self = (libcp1 *) s;
int fds[2];
if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
{
self->print ("could not create socketpair\n");
return 0;
}
int stderr_fds[2];
if (pipe (stderr_fds) != 0)
{
self->print ("could not create pipe\n");
close (fds[0]);
close (fds[1]);
return 0;
}
self->args.push_back ("-fplugin=libcp1plugin");
char buf[100];
if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcp1plugin-fd=%d", fds[1])
>= (long) sizeof (buf))
abort ();
self->args.push_back (buf);
self->args.push_back (self->source_file);
self->args.push_back ("-c");
self->args.push_back ("-o");
self->args.push_back (filename);
if (self->verbose)
self->args.push_back ("-v");
self->connection = new libcp1_connection (fds[0], stderr_fds[0], self);
cc1_plugin::callback_ftype *fun
= cc1_plugin::callback<int,
enum gcc_cp_oracle_request,
const char *,
cp_call_binding_oracle>;
self->connection->add_callback ("binding_oracle", fun);
fun = cc1_plugin::callback<gcc_address,
const char *,
cp_call_symbol_address>;
self->connection->add_callback ("address_oracle", fun);
fun = cc1_plugin::callback<int,
cp_call_enter_scope>;
self->connection->add_callback ("enter_scope", fun);
fun = cc1_plugin::callback<int,
cp_call_leave_scope>;
self->connection->add_callback ("leave_scope", fun);
char **argv = new (std::nothrow) char *[self->args.size () + 1];
if (argv == NULL)
return 0;
for (unsigned int i = 0; i < self->args.size (); ++i)
argv[i] = const_cast<char *> (self->args[i].c_str ());
argv[self->args.size ()] = NULL;
return fork_exec (self, argv, fds, stderr_fds);
}
static int
libcp1_compile_v0 (struct gcc_base_context *s, const char *filename,
int verbose)
{
libcp1_set_verbose (s, verbose);
return libcp1_compile (s, filename);
}
static void
libcp1_destroy (struct gcc_base_context *s)
{
libcp1 *self = (libcp1 *) s;
delete self;
}
static const struct gcc_base_vtable vtable =
{
GCC_FE_VERSION_0,
libcp1_set_arguments_v0,
libcp1_set_source_file,
libcp1_set_print_callback,
libcp1_compile_v0,
libcp1_destroy,
libcp1_set_verbose,
libcp1_compile,
libcp1_set_arguments,
libcp1_set_triplet_regexp,
libcp1_set_driver_filename,
};
extern "C" gcc_cp_fe_context_function gcc_cp_fe_context;
#ifdef __GNUC__
#pragma GCC visibility push(default)
#endif
extern "C"
struct gcc_cp_context *
gcc_cp_fe_context (enum gcc_base_api_version base_version,
enum gcc_cp_api_version cp_version)
{
if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1)
|| cp_version != GCC_CP_FE_VERSION_0)
return NULL;
return new libcp1 (&vtable, &cp_vtable);
}

3789
libcc1/libcp1plugin.cc Normal file

File diff suppressed because it is too large Load Diff

2
libcc1/libcp1plugin.sym Normal file
View File

@ -0,0 +1,2 @@
plugin_init
plugin_is_GPL_compatible

59
libcc1/marshall-c.hh Normal file
View File

@ -0,0 +1,59 @@
/* Marshalling and unmarshalling of C-specific types.
Copyright (C) 2014-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef CC1_PLUGIN_MARSHALL_C_HH
#define CC1_PLUGIN_MARSHALL_C_HH
#include "marshall.hh"
#include "gcc-c-interface.h"
namespace cc1_plugin
{
status
unmarshall (connection *conn, enum gcc_c_symbol_kind *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_c_symbol_kind) p;
return OK;
}
status
unmarshall (connection *conn, enum gcc_c_oracle_request *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_c_oracle_request) p;
return OK;
}
status
unmarshall (connection *conn, enum gcc_qualifiers *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_qualifiers) p;
return OK;
}
}
#endif // CC1_PLUGIN_MARSHALL_C_HH

271
libcc1/marshall-cp.hh Normal file
View File

@ -0,0 +1,271 @@
/* Marshalling and unmarshalling of C++-specific types.
Copyright (C) 2014-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef CC1_PLUGIN_MARSHALL_CXX_HH
#define CC1_PLUGIN_MARSHALL_CXX_HH
#include "marshall.hh"
#include "gcc-cp-interface.h"
namespace cc1_plugin
{
status
unmarshall (connection *conn, enum gcc_cp_symbol_kind *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_cp_symbol_kind) p;
return OK;
}
status
unmarshall (connection *conn, enum gcc_cp_oracle_request *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_cp_oracle_request) p;
return OK;
}
status
unmarshall (connection *conn, enum gcc_cp_qualifiers *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*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->flags[0]),
a->flags);
}
// 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;
}
struct gcc_vbase_array *gva = new gcc_vbase_array;
gva->n_elements = len;
gva->elements = new gcc_type[len];
if (!unmarshall_array_elmts (conn,
len * sizeof (gva->elements[0]),
gva->elements))
{
delete[] gva->elements;
delete gva;
return FAIL;
}
gva->flags = new enum gcc_cp_symbol_kind[len];
if (!unmarshall_array_elmts (conn,
len * sizeof (gva->flags[0]),
gva->flags))
{
delete[] gva->flags;
delete[] gva->elements;
delete gva;
return FAIL;
}
*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;
}
// Send a gcc_cp_function_args marker followed by the array.
status
marshall (connection *conn, const gcc_cp_function_args *a)
{
size_t len;
if (a)
len = a->n_elements;
else
len = (size_t)-1;
if (!marshall_array_start (conn, 'd', len))
return FAIL;
if (!a)
return OK;
return marshall_array_elmts (conn, len * sizeof (a->elements[0]),
a->elements);
}
// Read a gcc_cp_function_args marker, followed by a
// gcc_cp_function_args. 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_function_args **result)
{
size_t len;
if (!unmarshall_array_start (conn, 'd', &len))
return FAIL;
if (len == (size_t)-1)
{
*result = NULL;
return OK;
}
struct gcc_cp_function_args *gva = new gcc_cp_function_args;
gva->n_elements = len;
gva->elements = new gcc_expr[len];
if (!unmarshall_array_elmts (conn,
len * sizeof (gva->elements[0]),
gva->elements))
{
delete[] gva->elements;
delete gva;
return FAIL;
}
*result = gva;
return OK;
}
}
#endif // CC1_PLUGIN_MARSHALL_CP_HH

View File

@ -49,36 +49,6 @@ cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result)
return conn->get (result, sizeof (*result));
}
cc1_plugin::status
cc1_plugin::unmarshall (connection *conn, enum gcc_c_symbol_kind *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_c_symbol_kind) p;
return OK;
}
cc1_plugin::status
cc1_plugin::unmarshall (connection *conn, enum gcc_c_oracle_request *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_c_oracle_request) p;
return OK;
}
cc1_plugin::status
cc1_plugin::unmarshall (connection *conn, enum gcc_qualifiers *result)
{
protocol_int p;
if (!unmarshall_intlike (conn, &p))
return FAIL;
*result = (enum gcc_qualifiers) p;
return OK;
}
cc1_plugin::status
cc1_plugin::marshall (connection *conn, const char *str)
{
@ -128,39 +98,98 @@ 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::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 (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;
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);
}
cc1_plugin::status
cc1_plugin::unmarshall (connection *conn, gcc_type_array **result)
{
unsigned long long len;
size_t len;
if (!conn->require ('a'))
return FAIL;
if (!conn->get (&len, sizeof (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 (len == (size_t)-1)
{
delete[] (*result)->elements;
*result = NULL;
return OK;
}
gcc_type_array *gta = new gcc_type_array;
gta->n_elements = len;
gta->elements = new gcc_type[len];
if (!unmarshall_array_elmts (conn,
len * sizeof (gta->elements[0]),
gta->elements))
{
delete[] gta->elements;
delete *result;
return FAIL;
}
*result = gta;
return OK;
}

View File

@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see
#define CC1_PLUGIN_MARSHALL_HH
#include "status.hh"
#include "gcc-c-interface.h"
#include "gcc-interface.h"
namespace cc1_plugin
{
@ -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>
@ -67,13 +73,6 @@ namespace cc1_plugin
return OK;
}
// Unmarshallers for some specific enum types. With C++11 we
// wouldn't need these, as we could add type traits to the scalar
// unmarshaller.
status unmarshall (connection *, enum gcc_c_symbol_kind *);
status unmarshall (connection *, enum gcc_qualifiers *);
status unmarshall (connection *, enum gcc_c_oracle_request *);
// Send a string type marker followed by a string.
status marshall (connection *, const char *);

View File

@ -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

View File

@ -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

View File

@ -21,7 +21,6 @@ along with GCC; see the file COPYING3. If not see
#define CC1_PLUGIN_RPC_HH
#include "status.hh"
#include "marshall.hh"
#include "connection.hh"
namespace cc1_plugin
@ -126,6 +125,118 @@ namespace cc1_plugin
argument_wrapper &operator= (const argument_wrapper &);
};
#ifdef GCC_CP_INTERFACE_H
// Specialization for gcc_vbase_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->flags;
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 &);
};
// 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 &);
};
// Specialization for gcc_cp_function_args.
template<>
class argument_wrapper<const gcc_cp_function_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;
}
operator const gcc_cp_function_args * () const
{
return m_object;
}
status unmarshall (connection *conn)
{
return ::cc1_plugin::unmarshall (conn, &m_object);
}
private:
gcc_cp_function_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
// "callback". They are each repeated multiple times to handle
// different numbers of arguments. (This would be improved with