summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-31 01:02:03 +0000
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-31 01:02:03 +0000
commit37af486a23dbed5ff5003392c42495f4b68afb71 (patch)
tree3901a07d4c4dde00dbe21a5d032c741cfc2aaaa2 /gcc/cp
parent470672abaafa1c83bba7d6b1972c17096eaa9c65 (diff)
downloadgcc-37af486a23dbed5ff5003392c42495f4b68afb71.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@245051 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog28
-rw-r--r--gcc/cp/call.c14
-rw-r--r--gcc/cp/class.c10
-rw-r--r--gcc/cp/cp-tree.h40
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/friend.c43
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/lambda.c2
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/method.c10
-rw-r--r--gcc/cp/name-lookup.c27
-rw-r--r--gcc/cp/parser.c103
-rw-r--r--gcc/cp/search.c5
-rw-r--r--gcc/cp/semantics.c7
-rw-r--r--gcc/cp/typeck.c2
16 files changed, 215 insertions, 88 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1f31731bc69..18732c927e3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8030d7ebb0b..6533214799d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 03a973084e5..d99ebcdc7df 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f412ddd6e4a..a744d8372bf 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 44aefd82b73..9bdfd4ff64b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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; \
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a9a1d2286a8..86d98202f0d 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 9eec9e48869..3815daef4d5 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -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)
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index de43d81ce30..42f1c6192ec 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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)
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 4d22c3d37d9..538c8063957 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -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)
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 60a70e9b325..ad6318656ad 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -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
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index e80b80606b5..941f9a657e4 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 10fb540e1f1..a3cb7eea907 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7f685506bc1..592f903a6f9 100644
--- a/gcc/cp/parser.c
+++ b/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;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index ec8f4ab4ba6..09c1b4e6456 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 42b555c5883..bd91e1832f7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index f677b48ee58..8f66d3c7933 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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;