+2017-10-31 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (assign_op_identifier, call_op_identifier): Define.
+ (LAMBDA_FUNCTION_P): Use DECL_OVERLOADED_OPERATOR_IS.
+ (DECL_OVERLOADED_OPERATOR_P): Just retuurn true/false.
+ (DECL_OVERLOADED_OPERATOR_CODE, DECL_OVERLOADED_OPERATOR_IS): Define.
+ * call.c (add_function_candidate): Use
+ DECL_OVERLOADED_OPERATOR_IS.
+ (build_op_call_1): Use call_op_identifier &
+ DECL_OVERLOADED_OPERATOR_IS.
+ (build_over_call): Likewise.
+ (has_trivial_copy_assign_p): Use assign_op_identifier.
+ (build_special_member_call): Likewise.
+ * class.c (dfs_declare_virt_assop_and_dtor): Likewise.
+ (vbase_has_user_provided_move_assign,
+ classtype_has_move_assign_or_move_ctor_p): Likewise.
+ * decl.c (duplicate_decls): Use DECL_OVERLOADED_OPERATOR_CODE.
+ (grok_special_member_properties): Use assign_op_identifier.
+ (start_preparsed_function): Use DECL_OVERLOADED_OPERATOR_IS.
+ * decl2.c (mark_used): Use DECL_CONV_FN_P.
+ * dump.c (dump_access): Delete prototype.
+ (dump_op): Delete.
+ (cp_dump_tree): Don't call it.
+ * lambda.c (lambda_function): Use call_op_identifier.
+ (maybe_add_lambda_conv_op): Not an overloaded operator. Remove
+ unneeded braces.
+ * mangle.c (write_unqualified_name): Use DECL_OVERLOADED_OPERTOR_CODE.
+ * method.c (do_build_copy_assign): Use assign_op_identifier.
+ (synthesize_method): Use DECL_OVERLOADED_OPERATOR_IS.
+ (get_copy_assign): Use assign_op_identifier.
+ (synthesized_method_walk): Likewise.
+ (defaultable_fn_check): Use DECL_OVERLOADED_OPERATOR_IS.
+ * parser.c (cp_parser_lambda_declarator_opt): Use
+ call_op_identifier.
+ * semanitics.c (classtype_has_nothrow_assign_or_copy_p): Use
+ assign_op_identifier.
+ * tree.c (special_function_p): Use DECL_OVERLOADED_OPERATOR_IS.
+ * typeck.c (check_return_expr): Use DECL_OVERLOADED_OPERATOR_CODE.
+ (check_return_expr): Use assign_op_identifier.
+
2017-10-30 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/82085
if (DECL_CONSTRUCTOR_P (fn))
i = 1;
else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
- && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+ && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR))
i = 2;
else
i = 0;
if (TYPE_BINFO (type))
{
- fns = lookup_fnfields (TYPE_BINFO (type), cp_operator_id (CALL_EXPR), 1);
+ fns = lookup_fnfields (TYPE_BINFO (type), call_op_identifier, 1);
if (fns == error_mark_node)
return error_mark_node;
}
}
result = error_mark_node;
}
- /* Since cand->fn will be a type, not a function, for a conversion
- function, we must be careful not to unconditionally look at
- DECL_NAME here. */
else if (TREE_CODE (cand->fn) == FUNCTION_DECL
- && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
+ && DECL_OVERLOADED_OPERATOR_P (cand->fn)
+ && DECL_OVERLOADED_OPERATOR_IS (cand->fn, CALL_EXPR))
result = build_over_call (cand, LOOKUP_NORMAL, complain);
else
{
return val;
}
}
- else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
+ else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
+ && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR)
&& trivial_fn_p (fn)
&& !DECL_DELETED_FN (fn))
{
static bool
has_trivial_copy_assign_p (tree type, bool access, bool *hasassign)
{
- tree fns = get_class_binding (type, cp_assignment_operator_id (NOP_EXPR));
+ tree fns = get_class_binding (type, assign_op_identifier);
bool all_trivial = true;
/* Iterate over overloads of the assignment operator, checking
vec<tree, va_gc> *allocated = NULL;
tree ret;
- gcc_assert (IDENTIFIER_CDTOR_P (name)
- || name == cp_assignment_operator_id (NOP_EXPR));
+ gcc_assert (IDENTIFIER_CDTOR_P (name) || name == assign_op_identifier);
if (TYPE_P (binfo))
{
/* Resolve the name. */
if (!same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (instance), BINFO_TYPE (binfo)))
{
- if (name != cp_assignment_operator_id (NOP_EXPR))
+ if (IDENTIFIER_CDTOR_P (name))
/* 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
statically. */
instance = convert_to_base_statically (instance, binfo);
else
- /* However, for assignment operators, we must convert
- dynamically if the base is virtual. */
- instance = build_base_path (PLUS_EXPR, instance,
- binfo, /*nonnull=*/1, complain);
+ {
+ /* However, for assignment operators, we must convert
+ dynamically if the base is virtual. */
+ gcc_checking_assert (name == assign_op_identifier);
+ instance = build_base_path (PLUS_EXPR, instance,
+ binfo, /*nonnull=*/1, complain);
+ }
}
}
dfs_declare_virt_assop_and_dtor (tree binfo, void *data)
{
tree bv, fn, t = (tree)data;
- tree opname = cp_assignment_operator_id (NOP_EXPR);
+ tree opname = assign_op_identifier;
gcc_assert (t && CLASS_TYPE_P (t));
gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO);
/* Does the type itself have a user-provided move assignment operator? */
if (!CLASSTYPE_LAZY_MOVE_ASSIGN (type))
for (ovl_iterator iter (get_class_binding_direct
- (type, cp_assignment_operator_id (NOP_EXPR)));
+ (type, assign_op_identifier));
iter; ++iter)
if (!DECL_ARTIFICIAL (*iter) && move_fn_p (*iter))
return true;
if (!CLASSTYPE_LAZY_MOVE_ASSIGN (t))
for (ovl_iterator iter (get_class_binding_direct
- (t, cp_assignment_operator_id (NOP_EXPR)));
+ (t, assign_op_identifier));
iter; ++iter)
if ((!user_p || !DECL_ARTIFICIAL (*iter)) && move_fn_p (*iter))
return true;
things) to iterate over their overloads defined by/for a type. For
example:
- tree ovlid = cp_assignment_operator_id (NOP_EXPR);
+ tree ovlid = assign_op_identifier;
tree overloads = get_class_binding (type, ovlid);
for (ovl_iterator it (overloads); it; ++it) { ... }
/* The name of a destructor that destroys virtual base classes, and
then deletes the entire object. */
#define deleting_dtor_identifier cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER]
+
+#define assign_op_identifier (cp_assignment_operator_id (NOP_EXPR))
+#define call_op_identifier (cp_operator_id (CALL_EXPR))
/* The name used for conversion operators -- but note that actual
conversion functions use special identifiers outside the identifier
table. */
(CLASS_TYPE_P (NODE) && CLASSTYPE_LAMBDA_EXPR (NODE))
/* Test if FUNCTION_DECL is a lambda function. */
-#define LAMBDA_FUNCTION_P(FNDECL) \
- (DECL_DECLARES_FUNCTION_P (FNDECL) \
- && DECL_OVERLOADED_OPERATOR_P (FNDECL) == CALL_EXPR \
+#define LAMBDA_FUNCTION_P(FNDECL) \
+ (DECL_DECLARES_FUNCTION_P (FNDECL) \
+ && DECL_OVERLOADED_OPERATOR_P (FNDECL) \
+ && DECL_OVERLOADED_OPERATOR_IS (FNDECL, CALL_EXPR) \
&& LAMBDA_TYPE_P (CP_DECL_CONTEXT (FNDECL)))
enum cp_lambda_default_capture_mode_type {
#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
(LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
-/* If NODE is an overloaded operator, then this returns the TREE_CODE
- associated with the overloaded operator. If NODE is not an
- overloaded operator, ERROR_MARK is returned. Since the numerical
- value of ERROR_MARK is zero, this macro can be used as a predicate
- to test whether or not NODE is an overloaded operator. */
+/* True iff decl NODE is for an overloaded operator. */
#define DECL_OVERLOADED_OPERATOR_P(NODE) \
- (IDENTIFIER_ANY_OP_P (DECL_NAME (NODE)) \
- ? LANG_DECL_FN_CHECK (NODE)->operator_code : ERROR_MARK)
+ IDENTIFIER_ANY_OP_P (DECL_NAME (NODE))
/* Nonzero if NODE is an assignment operator (including += and such). */
-#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
+#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
IDENTIFIER_ASSIGN_OP_P (DECL_NAME (NODE))
+/* NODE is a function_decl for an overloaded operator. Return its
+ operator code. */
+#define DECL_OVERLOADED_OPERATOR_CODE(NODE) \
+ (LANG_DECL_FN_CHECK (NODE)->operator_code)
+
+/* DECL is an overloaded operator. Test whether it is for TREE_CODE
+ (a literal constant). */
+#define DECL_OVERLOADED_OPERATOR_IS(DECL, CODE) \
+ (DECL_OVERLOADED_OPERATOR_CODE (DECL) == CODE)
+
/* For FUNCTION_DECLs: nonzero means that this function is a
constructor or a destructor with an extra in-charge parameter to
control whether or not virtual bases are constructed. */
DECL_FINAL_P (newdecl) |= DECL_FINAL_P (olddecl);
DECL_OVERRIDE_P (newdecl) |= DECL_OVERRIDE_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
- if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
+ if (DECL_OVERLOADED_OPERATOR_P (olddecl))
SET_OVERLOADED_OPERATOR_CODE
- (newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
+ (newdecl, DECL_OVERLOADED_OPERATOR_CODE (olddecl));
new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
/* Optionally warn about more than one declaration for the same
&& !ctor && !move_fn_p (decl))
TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1;
}
- else if (DECL_NAME (decl) == cp_assignment_operator_id (NOP_EXPR))
+ else if (DECL_NAME (decl) == assign_op_identifier)
{
/* [class.copy]
/* Effective C++ rule 15. */
if (warn_ecpp
- && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
+ && DECL_ASSIGNMENT_OPERATOR_P (decl1)
+ && DECL_OVERLOADED_OPERATOR_IS (decl1, NOP_EXPR)
&& VOID_TYPE_P (TREE_TYPE (fntype)))
- warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>");
+ warning (OPT_Weffc__,
+ "%<operator=%> should return a reference to %<*this%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
&& DECL_DELETED_FN (decl))
{
if (DECL_ARTIFICIAL (decl)
- && DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR
+ && DECL_CONV_FN_P (decl)
&& LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
/* We mark a lambda conversion op as deleted if we can't
generate it properly; see maybe_add_lambda_conv_op. */
- sorry ("converting lambda which uses %<...%> to function pointer");
+ sorry ("converting lambda that uses %<...%> to function pointer");
else if (complain & tf_error)
{
error ("use of deleted function %qD", decl);
#include "cp-tree.h"
#include "tree-dump.h"
-static void dump_access (dump_info_p, tree);
-
-static void dump_op (dump_info_p, tree);
-
/* Dump a representation of the accessibility information associated
with T. */
dump_string_field (di, "accs", "pub");
}
-/* Dump a representation of the specific operator for an overloaded
- operator associated with node t. */
-
-static void
-dump_op (dump_info_p di, tree t)
-{
- switch (DECL_OVERLOADED_OPERATOR_P (t)) {
- case NEW_EXPR:
- dump_string (di, "new");
- break;
- case VEC_NEW_EXPR:
- dump_string (di, "vecnew");
- break;
- case DELETE_EXPR:
- dump_string (di, "delete");
- break;
- case VEC_DELETE_EXPR:
- dump_string (di, "vecdelete");
- break;
- case UNARY_PLUS_EXPR:
- dump_string (di, "pos");
- break;
- case NEGATE_EXPR:
- dump_string (di, "neg");
- break;
- case ADDR_EXPR:
- dump_string (di, "addr");
- break;
- case INDIRECT_REF:
- dump_string(di, "deref");
- break;
- case BIT_NOT_EXPR:
- dump_string(di, "not");
- break;
- case TRUTH_NOT_EXPR:
- dump_string(di, "lnot");
- break;
- case PREINCREMENT_EXPR:
- dump_string(di, "preinc");
- break;
- case PREDECREMENT_EXPR:
- dump_string(di, "predec");
- break;
- case PLUS_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "plusassign");
- else
- dump_string(di, "plus");
- break;
- case MINUS_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "minusassign");
- else
- dump_string(di, "minus");
- break;
- case MULT_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "multassign");
- else
- dump_string (di, "mult");
- break;
- case TRUNC_DIV_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "divassign");
- else
- dump_string (di, "div");
- break;
- case TRUNC_MOD_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "modassign");
- else
- dump_string (di, "mod");
- break;
- case BIT_AND_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "andassign");
- else
- dump_string (di, "and");
- break;
- case BIT_IOR_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "orassign");
- else
- dump_string (di, "or");
- break;
- case BIT_XOR_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "xorassign");
- else
- dump_string (di, "xor");
- break;
- case LSHIFT_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "lshiftassign");
- else
- dump_string (di, "lshift");
- break;
- case RSHIFT_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "rshiftassign");
- else
- dump_string (di, "rshift");
- break;
- case EQ_EXPR:
- dump_string (di, "eq");
- break;
- case NE_EXPR:
- dump_string (di, "ne");
- break;
- case LT_EXPR:
- dump_string (di, "lt");
- break;
- case GT_EXPR:
- dump_string (di, "gt");
- break;
- case LE_EXPR:
- dump_string (di, "le");
- break;
- case GE_EXPR:
- dump_string (di, "ge");
- break;
- case TRUTH_ANDIF_EXPR:
- dump_string (di, "land");
- break;
- case TRUTH_ORIF_EXPR:
- dump_string (di, "lor");
- break;
- case COMPOUND_EXPR:
- dump_string (di, "compound");
- break;
- case MEMBER_REF:
- dump_string (di, "memref");
- break;
- case COMPONENT_REF:
- dump_string (di, "ref");
- break;
- case ARRAY_REF:
- dump_string (di, "subs");
- break;
- case POSTINCREMENT_EXPR:
- dump_string (di, "postinc");
- break;
- case POSTDECREMENT_EXPR:
- dump_string (di, "postdec");
- break;
- case CALL_EXPR:
- dump_string (di, "call");
- break;
- case NOP_EXPR:
- if (DECL_ASSIGNMENT_OPERATOR_P (t))
- dump_string (di, "assign");
- break;
- default:
- break;
- }
-}
-
/* Dump information common to statements from STMT. */
static void
case FUNCTION_DECL:
if (!DECL_THUNK_P (t))
{
- if (DECL_OVERLOADED_OPERATOR_P (t)) {
+ if (DECL_OVERLOADED_OPERATOR_P (t))
dump_string_field (di, "note", "operator");
- dump_op (di, t);
- }
if (DECL_FUNCTION_MEMBER_P (t))
{
dump_string_field (di, "note", "member");
if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
&& !COMPLETE_OR_OPEN_TYPE_P (type))
return NULL_TREE;
- lambda = lookup_member (type, cp_operator_id (CALL_EXPR),
+ lambda = lookup_member (type, call_op_identifier,
/*protect=*/0, /*want_type=*/false,
tf_warning_or_error);
if (lambda)
tree fn = convfn;
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
SET_DECL_ALIGN (fn, MINIMUM_METHOD_BOUNDARY);
- SET_OVERLOADED_OPERATOR_CODE (fn, TYPE_EXPR);
grokclassfn (type, fn, NO_SPECIAL);
set_linkage_according_to_type (type, fn);
rest_of_decl_compilation (fn, namespace_bindings_p (), at_eof);
fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
if (flag_sanitize & SANITIZE_NULL)
- {
- /* Don't UBsan this function; we're deliberately calling op() with a null
- object argument. */
- add_no_sanitize_value (fn, SANITIZE_UNDEFINED);
- }
+ /* Don't UBsan this function; we're deliberately calling op() with a null
+ object argument. */
+ add_no_sanitize_value (fn, SANITIZE_UNDEFINED);
add_method (type, fn, false);
else
oni = operator_name_info;
- write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
+ write_string (oni[DECL_OVERLOADED_OPERATOR_CODE (decl)].mangled_name);
}
else if (UDLIT_OPER_P (DECL_NAME (decl)))
write_literal_operator_name (DECL_NAME (decl));
parmvec = make_tree_vector_single (converted_parm);
finish_expr_stmt
(build_special_member_call (current_class_ref,
- cp_assignment_operator_id (NOP_EXPR),
+ assign_op_identifier,
&parmvec,
base_binfo,
flags,
start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
stmt = begin_function_body ();
- if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
+ if (DECL_ASSIGNMENT_OPERATOR_P (fndecl)
+ && DECL_OVERLOADED_OPERATOR_IS (fndecl, NOP_EXPR))
{
do_build_copy_assign (fndecl);
need_body = false;
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, cp_assignment_operator_id (NOP_EXPR), argtype,
+ tree fn = locate_fn_flags (type, assign_op_identifier, argtype,
LOOKUP_NORMAL, tf_warning_or_error);
if (fn == error_mark_node)
return NULL_TREE;
case sfk_move_assignment:
case sfk_copy_assignment:
assign_p = true;
- fnname = cp_assignment_operator_id (NOP_EXPR);
+ fnname = assign_op_identifier;
break;
case sfk_destructor:
else if (DECL_DESTRUCTOR_P (fn))
kind = sfk_destructor;
else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
- && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+ && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR))
{
if (copy_fn_p (fn))
kind = sfk_copy_assignment;
p = obstack_alloc (&declarator_obstack, 0);
- declarator = make_id_declarator (NULL_TREE, cp_operator_id (CALL_EXPR),
- sfk_none);
+ declarator = make_id_declarator (NULL_TREE, call_op_identifier, sfk_none);
quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
tree fns = NULL_TREE;
if (assign_p || TYPE_HAS_COPY_CTOR (type))
- fns = get_class_binding (type,
- assign_p ? cp_assignment_operator_id (NOP_EXPR)
+ fns = get_class_binding (type, assign_p ? assign_op_identifier
: ctor_identifier);
bool saw_copy = false;
return sfk_move_constructor;
if (DECL_CONSTRUCTOR_P (decl))
return sfk_constructor;
- if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
+ if (DECL_ASSIGNMENT_OPERATOR_P (decl)
+ && DECL_OVERLOADED_OPERATOR_IS (decl, NOP_EXPR))
{
if (copy_fn_p (decl))
return sfk_copy_assignment;
}
/* Only operator new(...) throw(), can return NULL [expr.new/13]. */
- if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
- || DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
+ if (DECL_OVERLOADED_OPERATOR_P (current_function_decl)
+ && (DECL_OVERLOADED_OPERATOR_CODE (current_function_decl) == NEW_EXPR
+ || (DECL_OVERLOADED_OPERATOR_CODE (current_function_decl)
+ == VEC_NEW_EXPR))
&& !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
&& ! flag_check_new
&& retval && null_ptr_cst_p (retval))
/* Effective C++ rule 15. See also start_function. */
if (warn_ecpp
- && DECL_NAME (current_function_decl) == cp_assignment_operator_id (NOP_EXPR))
+ && DECL_NAME (current_function_decl) == assign_op_identifier)
{
bool warn = true;