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:
parent
9f92b93b7b
commit
8db29d88f3
38 changed files with 7205 additions and 257 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
103
gcc/cp/parser.c
103
gcc/cp/parser.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
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
496
include/gcc-cp-interface.h
Normal 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 */
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
gcc_c_fe_context
|
||||
gcc_cp_fe_context
|
||||
|
|
|
@ -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
706
libcc1/libcp1.cc
Normal 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
3789
libcc1/libcp1plugin.cc
Normal file
File diff suppressed because it is too large
Load diff
2
libcc1/libcp1plugin.sym
Normal file
2
libcc1/libcp1plugin.sym
Normal file
|
@ -0,0 +1,2 @@
|
|||
plugin_init
|
||||
plugin_is_GPL_compatible
|
59
libcc1/marshall-c.hh
Normal file
59
libcc1/marshall-c.hh
Normal 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
271
libcc1/marshall-cp.hh
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
113
libcc1/rpc.hh
113
libcc1/rpc.hh
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue