* [C++ PATCH] overloaded operator fns [1/N] @ 2017-10-31 13:12 Nathan Sidwell 2017-10-31 14:45 ` [C++ PATCH] overloaded operator fns [2/N] Nathan Sidwell 0 siblings, 1 reply; 10+ messages in thread From: Nathan Sidwell @ 2017-10-31 13:12 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 767 bytes --] This patch breaks DECL_OVERLOADED_OPERATOR_P apart into a predicate (as its name suggests) and DECL_OVERLOADED_OPERATOR_CODE, an accessor. I also add DECL_OVERLOADED_OPERATOR_IS, whose current implementation is a stepping stone to more a compressed operator enumeration. Also add assign_op_identifier and call_op_identifier, which we use reasonably commonly. I also notice that we're marking a lambda's conversion operator as an overloaded TYPE_EXPR. That's weird and unnecessary, so this marks it simply as a conversion operator. We're a little inconsistent in whether we check those two overloads by looking for identifier equivalence or examining the operator code enumeration. I've not addressed that. Applying to trunk. nathan -- Nathan Sidwell [-- Attachment #2: op_idents.diff --] [-- Type: text/x-patch, Size: 23487 bytes --] 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. Index: call.c =================================================================== --- call.c (revision 254243) +++ call.c (working copy) @@ -2082,7 +2082,7 @@ add_function_candidate (struct z_candida 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; @@ -4474,7 +4474,7 @@ build_op_call_1 (tree obj, vec<tree, va_ 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; } @@ -4557,11 +4557,9 @@ build_op_call_1 (tree obj, vec<tree, va_ } 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 { @@ -8116,7 +8114,8 @@ build_over_call (struct z_candidate *can 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)) { @@ -8284,7 +8283,7 @@ first_non_public_field (tree type) 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 @@ -8784,8 +8783,7 @@ build_special_member_call (tree instance 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. */ @@ -8811,7 +8809,7 @@ build_special_member_call (tree instance 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 @@ -8819,10 +8817,13 @@ build_special_member_call (tree instance 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); + } } } Index: class.c =================================================================== --- class.c (revision 254243) +++ class.c (working copy) @@ -3011,7 +3011,7 @@ static tree 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); @@ -5038,7 +5038,7 @@ vbase_has_user_provided_move_assign (tre /* 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; @@ -5186,7 +5186,7 @@ classtype_has_move_assign_or_move_ctor_p 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; Index: cp-tree.h =================================================================== --- cp-tree.h (revision 254243) +++ cp-tree.h (working copy) @@ -217,7 +217,7 @@ extern GTY(()) tree cp_global_trees[CPTI 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) { ... } @@ -244,6 +244,9 @@ extern GTY(()) tree cp_global_trees[CPTI /* 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. */ @@ -1203,9 +1206,10 @@ struct GTY (()) tree_trait_expr { (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 { @@ -2810,19 +2814,24 @@ struct GTY(()) lang_decl { #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. */ Index: decl.c =================================================================== --- decl.c (revision 254243) +++ decl.c (working copy) @@ -1921,9 +1921,9 @@ next_arg:; 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 @@ -12816,7 +12816,7 @@ grok_special_member_properties (tree dec && !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] @@ -14769,9 +14769,11 @@ start_preparsed_function (tree decl1, tr /* 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. */ Index: decl2.c =================================================================== --- decl2.c (revision 254243) +++ decl2.c (working copy) @@ -5101,11 +5101,11 @@ mark_used (tree decl, tsubst_flags_t com && 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); Index: dump.c =================================================================== --- dump.c (revision 254243) +++ dump.c (working copy) @@ -24,10 +24,6 @@ along with GCC; see the file COPYING3. #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. */ @@ -42,163 +38,6 @@ dump_access (dump_info_p di, tree 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 @@ -303,10 +142,8 @@ cp_dump_tree (void* dump_info, tree t) 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"); Index: lambda.c =================================================================== --- lambda.c (revision 254243) +++ lambda.c (working copy) @@ -201,7 +201,7 @@ lambda_function (tree lambda) 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) @@ -1258,7 +1258,6 @@ maybe_add_lambda_conv_op (tree type) 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); @@ -1312,11 +1311,9 @@ maybe_add_lambda_conv_op (tree type) 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); Index: mangle.c =================================================================== --- mangle.c (revision 254243) +++ mangle.c (working copy) @@ -1351,7 +1351,7 @@ write_unqualified_name (tree decl) 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)); Index: method.c =================================================================== --- method.c (revision 254243) +++ method.c (working copy) @@ -815,7 +815,7 @@ do_build_copy_assign (tree fndecl) 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, @@ -929,7 +929,8 @@ synthesize_method (tree fndecl) 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; @@ -1108,7 +1109,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, 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; @@ -1565,7 +1566,7 @@ synthesized_method_walk (tree ctype, spe 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: @@ -2318,7 +2319,7 @@ defaultable_fn_check (tree fn) 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; Index: parser.c =================================================================== --- parser.c (revision 254243) +++ parser.c (working copy) @@ -10614,8 +10614,7 @@ cp_parser_lambda_declarator_opt (cp_pars 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); Index: semantics.c =================================================================== --- semantics.c (revision 254243) +++ semantics.c (working copy) @@ -9020,8 +9020,7 @@ classtype_has_nothrow_assign_or_copy_p ( 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; Index: tree.c =================================================================== --- tree.c (revision 254243) +++ tree.c (working copy) @@ -4847,7 +4847,8 @@ special_function_p (const_tree decl) 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; Index: typeck.c =================================================================== --- typeck.c (revision 254243) +++ typeck.c (working copy) @@ -9073,8 +9073,10 @@ check_return_expr (tree retval, bool *no } /* 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)) @@ -9083,7 +9085,7 @@ check_return_expr (tree retval, bool *no /* 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; ^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] overloaded operator fns [2/N] 2017-10-31 13:12 [C++ PATCH] overloaded operator fns [1/N] Nathan Sidwell @ 2017-10-31 14:45 ` Nathan Sidwell 2017-10-31 16:30 ` [C++ PATCH] overloaded operator fns [3/N] Nathan Sidwell 0 siblings, 1 reply; 10+ messages in thread From: Nathan Sidwell @ 2017-10-31 14:45 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 355 bytes --] This patch removes cp_operator_id(C) and cp_assignment_operator_id(C), replacing them with a singlle ovl_op_identifier(A,C) macro. There's also OVL_OP_INFO(A,C) to get at the other information. The implementation of that macro will change later in this patch series, so don't freak on the (A ? assop_ary : op_ary) idiom. nathan -- Nathan Sidwell [-- Attachment #2: op-ident-2.diff --] [-- Type: text/x-patch, Size: 24552 bytes --] 2017-10-31 Nathan Sidwell <nathan@acm.org> gcc/cp/ * cp-tree.h (ovl_op_identifier): New. (assign_op_identifier, call_op_identifier): Adjust. (cp_operator_id, cp_assignment_operator_ide): Delete. (SET_OVERLOADED_OPERATOR_CODE): Delete. (OVL_OP_INFO): New. * call.c (op_error): Use OVL_OP_INFO. (build_conditional_expr_1): Use ovl_op_identifier. (build_new_op_1): Use OVL_OP_INFO & ovl_op_identifier. (build_op_delete_call): Likewise. * class.c (type_requires_array_cookie): Use ovl_op_identifier. * decl.c (duplicate_decls): Directly copy operator code. (builtin_function_1): Do not set operator code. (build_library_fn): Directly set operator code. (push_cp_library_fn): Use ovl_op_identifier. (grok_op_properties): Directly set operator code. * decl2.c (maybe_warn_sized_delete): Use ovl_op_identifier. * error.c (dump_expr): Use OVL_OP_INFO. (op_to_string): Add assop arg. Use OVL_OP_INFO. (assop_to_string): Delete. (args_to_string): Adjust. * init.c (build_new_1): Use ovl_op_identifier. * mangle.c (write_unqualified_name): Use OVL_OP_INFO. (write_expression): Likewise. * method.c (synthesized_method_walk): Use ovl_op_identifier. (implicitly_declare_fn): Use assign_op_identifier. Directly set operator code. * name-lookup.c (get_class_binding): Use assign_op_identifier. * parser.c (cp_parser_operator): Use ovl_op_identifier. (cp_parser_omp_clause_reduction): Likewise. * semantics.c (omp_reduction_id): Likewise. * typeck.c (cxx_sizeof_or_alignof_type): Use OVL_OP_INFO. libcc1/ * libcp1plugin.cc (plugin_build_decl): Use ovl_op_identifier. Directly set operator code. (plugin_build_dependent_expr): Use ovl_op_identifier. Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 254263) +++ gcc/cp/call.c (working copy) @@ -4620,12 +4620,8 @@ static void op_error (location_t loc, enum tree_code code, enum tree_code code2, tree arg1, tree arg2, tree arg3, bool match) { - const char *opname; - - if (code == MODIFY_EXPR) - opname = assignment_operator_name_info[code2].name; - else - opname = operator_name_info[code].name; + bool assop = code == MODIFY_EXPR; + const char *opname = OVL_OP_INFO (assop, assop ? code2 : code)->name; switch (code) { @@ -5184,7 +5180,7 @@ build_conditional_expr_1 (location_t loc add_builtin_candidates (&candidates, COND_EXPR, NOP_EXPR, - cp_operator_id (COND_EXPR), + ovl_op_identifier (false, COND_EXPR), args, LOOKUP_NORMAL, complain); @@ -5574,7 +5570,6 @@ build_new_op_1 (location_t loc, enum tre { struct z_candidate *candidates = 0, *cand; vec<tree, va_gc> *arglist; - tree fnname; tree args[3]; tree result = NULL_TREE; bool result_valid_p = false; @@ -5591,14 +5586,13 @@ build_new_op_1 (location_t loc, enum tre || error_operand_p (arg3)) return error_mark_node; - if (code == MODIFY_EXPR) + bool ismodop = code == MODIFY_EXPR; + if (ismodop) { code2 = TREE_CODE (arg3); arg3 = NULL_TREE; - fnname = cp_assignment_operator_id (code2); } - else - fnname = cp_operator_id (code); + tree fnname = ovl_op_identifier (ismodop, ismodop ? code2 : code); arg1 = prep_operand (arg1); @@ -5793,7 +5787,7 @@ build_new_op_1 (location_t loc, enum tre ? G_("no %<%D(int)%> declared for postfix %qs," " trying prefix operator instead") : G_("no %<%D(int)%> declared for postfix %qs"); - permerror (loc, msg, fnname, operator_name_info[code].name); + permerror (loc, msg, fnname, OVL_OP_INFO (false, code)->name); } if (!flag_permissive) @@ -6205,7 +6199,7 @@ build_op_delete_call (enum tree_code cod type = strip_array_types (TREE_TYPE (TREE_TYPE (addr))); - fnname = cp_operator_id (code); + fnname = ovl_op_identifier (false, code); if (CLASS_TYPE_P (type) && COMPLETE_TYPE_P (complete_type (type)) @@ -6434,7 +6428,7 @@ build_op_delete_call (enum tree_code cod if (complain & tf_error) error ("no suitable %<operator %s%> for %qT", - operator_name_info[(int)code].name, type); + OVL_OP_INFO (false, code)->name, type); return error_mark_node; } Index: gcc/cp/class.c =================================================================== --- gcc/cp/class.c (revision 254263) +++ gcc/cp/class.c (working copy) @@ -5304,7 +5304,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), - cp_operator_id (VEC_DELETE_EXPR), + ovl_op_identifier (false, VEC_DELETE_EXPR), /*protect=*/0); /* If there are no `operator []' members, or the lookup is ambiguous, then we don't need a cookie. */ Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 254263) +++ gcc/cp/cp-tree.h (working copy) @@ -245,24 +245,14 @@ extern GTY(()) tree cp_global_trees[CPTI 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)) +#define ovl_op_identifier(ISASS, CODE) (OVL_OP_INFO(ISASS, CODE)->identifier) +#define assign_op_identifier (ovl_op_identifier (true, NOP_EXPR)) +#define call_op_identifier (ovl_op_identifier (false, CALL_EXPR)) /* The name used for conversion operators -- but note that actual conversion functions use special identifiers outside the identifier table. */ #define conv_op_identifier cp_global_trees[CPTI_CONV_OP_IDENTIFIER] -/* The name of the identifier used internally to represent operator CODE. */ -#define cp_operator_id(CODE) \ - (operator_name_info[(int) (CODE)].identifier) - -/* The name of the identifier used to represent assignment operator CODE, - both simple (i.e., operator= with CODE == NOP_EXPR) and compound (e.g., - operator+= with CODE == PLUS_EXPR). Includes copy and move assignment. - Use copy_fn_p() to test specifically for copy assignment. */ -#define cp_assignment_operator_id(CODE) \ - (assignment_operator_name_info[(int) (CODE)].identifier) - #define delta_identifier cp_global_trees[CPTI_DELTA_IDENTIFIER] #define in_charge_identifier cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER] /* The name of the parameter that contains a pointer to the VTT to use @@ -2810,10 +2800,6 @@ struct GTY(()) lang_decl { #define SET_VAR_HAD_UNKNOWN_BOUND(NODE) \ (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.unknown_bound_p = true) -/* Set the overloaded operator code for NODE to CODE. */ -#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \ - (LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE)) - /* True iff decl NODE is for an overloaded operator. */ #define DECL_OVERLOADED_OPERATOR_P(NODE) \ IDENTIFIER_ANY_OP_P (DECL_NAME (NODE)) @@ -5506,6 +5492,12 @@ extern GTY(()) operator_name_info_t oper extern GTY(()) operator_name_info_t assignment_operator_name_info [(int) MAX_TREE_CODES]; +/* Given an ass_op_p boolean and a tree code, return a pointer to its + overloaded operator info. */ +#define OVL_OP_INFO(IS_ASS_P, TREE_CODE) \ + (((IS_ASS_P) ? assignment_operator_name_info : operator_name_info) \ + + (TREE_CODE)) + /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL constants. */ Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 254263) +++ gcc/cp/decl.c (working copy) @@ -1922,8 +1922,8 @@ next_arg:; DECL_OVERRIDE_P (newdecl) |= DECL_OVERRIDE_P (olddecl); DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl); if (DECL_OVERLOADED_OPERATOR_P (olddecl)) - SET_OVERLOADED_OPERATOR_CODE - (newdecl, DECL_OVERLOADED_OPERATOR_CODE (olddecl)); + DECL_OVERLOADED_OPERATOR_CODE (newdecl) + = DECL_OVERLOADED_OPERATOR_CODE (olddecl); new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE; /* Optionally warn about more than one declaration for the same @@ -4359,7 +4359,6 @@ builtin_function_1 (tree decl, tree cont retrofit_lang_decl (decl); DECL_ARTIFICIAL (decl) = 1; - SET_OVERLOADED_OPERATOR_CODE (decl, ERROR_MARK); SET_DECL_LANGUAGE (decl, lang_c); /* Runtime library routines are, by definition, available in an external shared object. */ @@ -4447,7 +4446,7 @@ build_library_fn (tree name, enum tree_c DECL_EXTERNAL (fn) = 1; TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; - SET_OVERLOADED_OPERATOR_CODE (fn, operator_code); + DECL_OVERLOADED_OPERATOR_CODE (fn) = operator_code; SET_DECL_LANGUAGE (fn, lang_c); /* Runtime library routines are, by definition, available in an external shared object. */ @@ -4512,9 +4511,8 @@ static tree push_cp_library_fn (enum tree_code operator_code, tree type, int ecf_flags) { - tree fn = build_cp_library_fn (cp_operator_id (operator_code), - operator_code, - type, ecf_flags); + tree fn = build_cp_library_fn (ovl_op_identifier (false, operator_code), + operator_code, type, ecf_flags); pushdecl (fn); if (flag_tm) apply_tm_attr (fn, get_identifier ("transaction_safe")); @@ -12938,7 +12936,7 @@ grok_op_properties (tree decl, bool comp } while (0); gcc_assert (operator_code != MAX_TREE_CODES); - SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); + DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR) @@ -13111,7 +13109,7 @@ grok_op_properties (tree decl, bool comp gcc_unreachable (); } - SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); + DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; if ((operator_code == POSTINCREMENT_EXPR || operator_code == POSTDECREMENT_EXPR) Index: gcc/cp/decl2.c =================================================================== --- gcc/cp/decl2.c (revision 254263) +++ gcc/cp/decl2.c (working copy) @@ -4455,7 +4455,7 @@ maybe_warn_sized_delete (enum tree_code tree sized = NULL_TREE; tree unsized = NULL_TREE; - for (ovl_iterator iter (get_global_binding (cp_operator_id (code))); + for (ovl_iterator iter (get_global_binding (ovl_op_identifier (false, code))); iter; ++iter) { tree fn = *iter; Index: gcc/cp/error.c =================================================================== --- gcc/cp/error.c (revision 254263) +++ gcc/cp/error.c (working copy) @@ -50,13 +50,12 @@ static cxx_pretty_printer * const cxx_pp # define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T))) static const char *args_to_string (tree, int); -static const char *assop_to_string (enum tree_code); static const char *code_to_string (enum tree_code); static const char *cv_to_string (tree, int); static const char *decl_to_string (tree, int); static const char *expr_to_string (tree); static const char *fndecl_to_string (tree, int); -static const char *op_to_string (enum tree_code); +static const char *op_to_string (bool, enum tree_code); static const char *parm_to_string (int); static const char *type_to_string (tree, int); @@ -2230,8 +2229,7 @@ dump_expr (cxx_pretty_printer *pp, tree case INIT_EXPR: case MODIFY_EXPR: - dump_binary_op (pp, assignment_operator_name_info[NOP_EXPR].name, - t, flags); + dump_binary_op (pp, OVL_OP_INFO (true, NOP_EXPR)->name, t, flags); break; case PLUS_EXPR: @@ -2255,7 +2253,7 @@ dump_expr (cxx_pretty_printer *pp, tree case EQ_EXPR: case NE_EXPR: case EXACT_DIV_EXPR: - dump_binary_op (pp, operator_name_info[TREE_CODE (t)].name, t, flags); + dump_binary_op (pp, OVL_OP_INFO (false, TREE_CODE (t))->name, t, flags); break; case CEIL_DIV_EXPR: @@ -2386,14 +2384,14 @@ dump_expr (cxx_pretty_printer *pp, tree case TRUTH_NOT_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: - dump_unary_op (pp, operator_name_info [TREE_CODE (t)].name, t, flags); + dump_unary_op (pp, OVL_OP_INFO (false, TREE_CODE (t))->name, t, flags); break; case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: pp_cxx_left_paren (pp); dump_expr (pp, TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS); - pp_cxx_ws_string (pp, operator_name_info[TREE_CODE (t)].name); + pp_cxx_ws_string (pp, OVL_OP_INFO (false, TREE_CODE (t))->name); pp_cxx_right_paren (pp); break; @@ -2656,7 +2654,7 @@ dump_expr (cxx_pretty_printer *pp, tree case REALPART_EXPR: case IMAGPART_EXPR: - pp_cxx_ws_string (pp, operator_name_info[TREE_CODE (t)].name); + pp_cxx_ws_string (pp, OVL_OP_INFO (false, TREE_CODE (t))->name); pp_cxx_whitespace (pp); dump_expr (pp, TREE_OPERAND (t, 0), flags); break; @@ -3136,9 +3134,9 @@ parm_to_string (int p) } static const char * -op_to_string (enum tree_code p) +op_to_string (bool assop, enum tree_code p) { - tree id = operator_name_info[p].identifier; + tree id = ovl_op_identifier (assop, p); return id ? IDENTIFIER_POINTER (id) : M_("<unknown>"); } @@ -3180,13 +3178,6 @@ type_to_string (tree typ, int verbose) } static const char * -assop_to_string (enum tree_code p) -{ - tree id = assignment_operator_name_info[(int) p].identifier; - return id ? IDENTIFIER_POINTER (id) : M_("{unknown}"); -} - -static const char * args_to_string (tree p, int verbose) { int flags = 0; @@ -4044,9 +4035,9 @@ cp_printer (pretty_printer *pp, text_inf case 'E': result = expr_to_string (next_tree); break; case 'F': result = fndecl_to_string (next_tree, verbose); break; case 'L': result = language_to_string (next_lang); break; - case 'O': result = op_to_string (next_tcode); break; + case 'O': result = op_to_string (false, next_tcode); break; case 'P': result = parm_to_string (next_int); break; - case 'Q': result = assop_to_string (next_tcode); break; + case 'Q': result = op_to_string (true, next_tcode); break; case 'S': result = subst_to_string (next_tree); break; case 'T': result = type_to_string (next_tree, verbose); break; case 'V': result = cv_to_string (next_tree, verbose); break; Index: gcc/cp/init.c =================================================================== --- gcc/cp/init.c (revision 254263) +++ gcc/cp/init.c (working copy) @@ -3055,7 +3055,7 @@ build_new_1 (vec<tree, va_gc> **placemen tree fnname; tree fns; - fnname = cp_operator_id (array_p ? VEC_NEW_EXPR : NEW_EXPR); + fnname = ovl_op_identifier (false, array_p ? VEC_NEW_EXPR : NEW_EXPR); member_new_p = !globally_qualified_p && CLASS_TYPE_P (elt_type) Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 254263) +++ gcc/cp/mangle.c (working copy) @@ -1345,13 +1345,10 @@ write_unqualified_name (tree decl) } else if (DECL_OVERLOADED_OPERATOR_P (decl)) { - operator_name_info_t *oni; - if (DECL_ASSIGNMENT_OPERATOR_P (decl)) - oni = assignment_operator_name_info; - else - oni = operator_name_info; - - write_string (oni[DECL_OVERLOADED_OPERATOR_CODE (decl)].mangled_name); + const char *mangled_name + = (OVL_OP_INFO (DECL_ASSIGNMENT_OPERATOR_P (decl), + DECL_OVERLOADED_OPERATOR_CODE (decl))->mangled_name); + write_string (mangled_name); } else if (UDLIT_OPER_P (DECL_NAME (decl))) write_literal_operator_name (DECL_NAME (decl)); @@ -3064,8 +3061,8 @@ write_expression (tree expr) else if (TREE_CODE (expr) == MODOP_EXPR) { enum tree_code subop = TREE_CODE (TREE_OPERAND (expr, 1)); - const char *name = (assignment_operator_name_info[(int) subop] - .mangled_name); + const char *name = OVL_OP_INFO (true, subop)->mangled_name; + write_string (name); write_expression (TREE_OPERAND (expr, 0)); write_expression (TREE_OPERAND (expr, 2)); @@ -3090,7 +3087,7 @@ write_expression (tree expr) if (NEW_EXPR_USE_GLOBAL (expr)) write_string ("gs"); - write_string (operator_name_info[(int) code].mangled_name); + write_string (OVL_OP_INFO (false, code)->mangled_name); for (t = placement; t; t = TREE_CHAIN (t)) write_expression (TREE_VALUE (t)); @@ -3130,7 +3127,7 @@ write_expression (tree expr) if (DELETE_EXPR_USE_GLOBAL (expr)) write_string ("gs"); - write_string (operator_name_info[(int) code].mangled_name); + write_string (OVL_OP_INFO (false, code)->mangled_name); write_expression (TREE_OPERAND (expr, 0)); } @@ -3195,7 +3192,7 @@ write_expression (tree expr) if (TREE_CODE (ob) == ARROW_EXPR) { - write_string (operator_name_info[(int)code].mangled_name); + write_string (OVL_OP_INFO (false, code)->mangled_name); ob = TREE_OPERAND (ob, 0); write_expression (ob); } @@ -3212,7 +3209,7 @@ write_expression (tree expr) } /* If it wasn't any of those, recursively expand the expression. */ - name = operator_name_info[(int) code].mangled_name; + name = OVL_OP_INFO (false, code)->mangled_name; /* We used to mangle const_cast and static_cast like a C cast. */ if (code == CONST_CAST_EXPR @@ -3221,7 +3218,7 @@ write_expression (tree expr) if (abi_warn_or_compat_version_crosses (6)) G.need_abi_warning = 1; if (!abi_version_at_least (6)) - name = operator_name_info[CAST_EXPR].mangled_name; + name = OVL_OP_INFO (false, CAST_EXPR)->mangled_name; } if (name == NULL) @@ -3322,7 +3319,7 @@ write_expression (tree expr) if (i == 0) { int fcode = TREE_INT_CST_LOW (operand); - write_string (operator_name_info[fcode].mangled_name); + write_string (OVL_OP_INFO (false, fcode)->mangled_name); continue; } else if (code == BINARY_LEFT_FOLD_EXPR) Index: gcc/cp/method.c =================================================================== --- gcc/cp/method.c (revision 254263) +++ gcc/cp/method.c (working copy) @@ -1703,12 +1703,12 @@ synthesized_method_walk (tree ctype, spe { /* Unlike for base ctor/op=/dtor, for operator delete it's fine to have a null fn (no class-specific op delete). */ - fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR), + fn = locate_fn_flags (ctype, ovl_op_identifier (false, DELETE_EXPR), ptr_type_node, flags, tf_none); if (fn && fn == error_mark_node) { if (complain & tf_error) - locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR), + locate_fn_flags (ctype, ovl_op_identifier (false, DELETE_EXPR), ptr_type_node, flags, complain); if (deleted_p) *deleted_p = true; @@ -2008,7 +2008,7 @@ implicitly_declare_fn (special_function_ || kind == sfk_move_assignment) { return_type = build_reference_type (type); - name = cp_assignment_operator_id (NOP_EXPR); + name = assign_op_identifier; } else name = ctor_identifier; @@ -2078,7 +2078,7 @@ implicitly_declare_fn (special_function_ if (!IDENTIFIER_CDTOR_P (name)) /* Assignment operator. */ - SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR); + DECL_OVERLOADED_OPERATOR_CODE (fn) = NOP_EXPR; else if (IDENTIFIER_CTOR_P (name)) DECL_CXX_CONSTRUCTOR_P (fn) = true; else Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 254263) +++ gcc/cp/name-lookup.c (working copy) @@ -1299,7 +1299,7 @@ get_class_binding (tree klass, tree name if (CLASSTYPE_LAZY_DESTRUCTOR (klass)) lazily_declare_fn (sfk_destructor, klass); } - else if (name == cp_assignment_operator_id (NOP_EXPR)) + else if (name == assign_op_identifier) { if (CLASSTYPE_LAZY_COPY_ASSIGN (klass)) lazily_declare_fn (sfk_copy_assignment, klass); Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 254263) +++ gcc/cp/parser.c (working copy) @@ -15006,7 +15006,7 @@ cp_parser_operator (cp_parser* parser) operator token. */ if (op != ERROR_MARK) { - id = assop ? cp_assignment_operator_id (op) : cp_operator_id (op); + id = ovl_op_identifier (assop, op); if (!consumed) cp_lexer_consume_token (parser->lexer); } @@ -32588,21 +32588,21 @@ cp_parser_omp_clause_reduction (cp_parse code = MIN_EXPR; else if (strcmp (p, "max") == 0) code = MAX_EXPR; - else if (id == cp_operator_id (PLUS_EXPR)) + else if (id == ovl_op_identifier (false, PLUS_EXPR)) code = PLUS_EXPR; - else if (id == cp_operator_id (MULT_EXPR)) + else if (id == ovl_op_identifier (false, MULT_EXPR)) code = MULT_EXPR; - else if (id == cp_operator_id (MINUS_EXPR)) + else if (id == ovl_op_identifier (false, MINUS_EXPR)) code = MINUS_EXPR; - else if (id == cp_operator_id (BIT_AND_EXPR)) + else if (id == ovl_op_identifier (false, BIT_AND_EXPR)) code = BIT_AND_EXPR; - else if (id == cp_operator_id (BIT_IOR_EXPR)) + else if (id == ovl_op_identifier (false, BIT_IOR_EXPR)) code = BIT_IOR_EXPR; - else if (id == cp_operator_id (BIT_XOR_EXPR)) + else if (id == ovl_op_identifier (false, BIT_XOR_EXPR)) code = BIT_XOR_EXPR; - else if (id == cp_operator_id (TRUTH_ANDIF_EXPR)) + else if (id == ovl_op_identifier (false, TRUTH_ANDIF_EXPR)) code = TRUTH_ANDIF_EXPR; - else if (id == cp_operator_id (TRUTH_ORIF_EXPR)) + else if (id == ovl_op_identifier (false, TRUTH_ORIF_EXPR)) code = TRUTH_ORIF_EXPR; id = omp_reduction_id (code, id, NULL_TREE); tree scope = parser->scope; Index: gcc/cp/semantics.c =================================================================== --- gcc/cp/semantics.c (revision 254263) +++ gcc/cp/semantics.c (working copy) @@ -5099,7 +5099,7 @@ omp_reduction_id (enum tree_code reducti case BIT_IOR_EXPR: case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: - reduction_id = cp_operator_id (reduction_code); + reduction_id = ovl_op_identifier (false, reduction_code); break; case MIN_EXPR: p = "min"; Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 254263) +++ gcc/cp/typeck.c (working copy) @@ -1562,7 +1562,7 @@ cxx_sizeof_or_alignof_type (tree type, e if (complain) pedwarn (input_location, OPT_Wpointer_arith, "invalid application of %qs to a member function", - operator_name_info[(int) op].name); + OVL_OP_INFO (false, op)->name); else return error_mark_node; value = size_one_node; Index: libcc1/libcp1plugin.cc =================================================================== --- libcc1/libcp1plugin.cc (revision 254263) +++ libcc1/libcp1plugin.cc (working copy) @@ -1346,12 +1346,7 @@ plugin_build_decl (cc1_plugin::connectio } if (opcode != ERROR_MARK) - { - if (assop) - identifier = cp_assignment_operator_id (opcode); - else - identifier = cp_operator_id (opcode); - } + identifier = ovl_op_identifier (assop, opcode); } decl = build_lang_decl_loc (loc, code, identifier, sym_type); /* FIXME: current_lang_name is lang_name_c while compiling an @@ -1410,19 +1405,14 @@ plugin_build_decl (cc1_plugin::connectio DECL_DECLARED_INLINE_P (decl) = 1; DECL_INITIAL (decl) = error_mark_node; } - if (ctor || dtor) - { - if (ctor) - DECL_CXX_CONSTRUCTOR_P (decl) = 1; - if (dtor) - DECL_CXX_DESTRUCTOR_P (decl) = 1; - } - else - { - if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION) - && opcode != ERROR_MARK) - SET_OVERLOADED_OPERATOR_CODE (decl, opcode); - } + + if (ctor) + DECL_CXX_CONSTRUCTOR_P (decl) = 1; + else if (dtor) + DECL_CXX_DESTRUCTOR_P (decl) = 1; + else if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION) + && opcode != ERROR_MARK) + DECL_OVERLOADED_OPERATOR_CODE (decl) = opcode; } else if (RECORD_OR_UNION_CODE_P (code)) { @@ -2649,12 +2639,7 @@ plugin_build_dependent_expr (cc1_plugin: gcc_assert (convop || !conv_type); if (opcode != ERROR_MARK) - { - if (assop) - identifier = cp_assignment_operator_id (opcode); - else - identifier = cp_operator_id (opcode); - } + identifier = ovl_op_identifier (assop, opcode); gcc_assert (identifier); } ^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] overloaded operator fns [3/N] 2017-10-31 14:45 ` [C++ PATCH] overloaded operator fns [2/N] Nathan Sidwell @ 2017-10-31 16:30 ` Nathan Sidwell 2017-10-31 18:45 ` [C++ PATCH] overloaded operator fns [4/N] Nathan Sidwell 0 siblings, 1 reply; 10+ messages in thread From: Nathan Sidwell @ 2017-10-31 16:30 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 220 bytes --] This patch replaces the operator info 'arity' field with a 'flags' field that encodes more information. Adjusted the few places that look at this. More use will be made in future patches. nathan -- Nathan Sidwell [-- Attachment #2: op-ident-3.diff --] [-- Type: text/x-patch, Size: 14210 bytes --] 2017-10-31 Nathan Sidwell <nathan@acm.org> * cp-tree.h (enum ovl_op_flags): New. (struct operator_name_info_t): Rename arity to flags. * lex.c (set_operator_ident): New. (init_operators): Use it. Adjust for flags. * mangle.c (write_unqualified_id): Adjust for flags. * operators.def: Replace arity with flags. Index: cp-tree.h =================================================================== --- cp-tree.h (revision 254267) +++ cp-tree.h (working copy) @@ -5474,16 +5474,27 @@ enum auto_deduction_context extern void init_reswords (void); -typedef struct GTY(()) operator_name_info_t { +/* Various flags for the overloaded operator information. */ +enum ovl_op_flags + { + OVL_OP_FLAG_NONE = 0, + OVL_OP_FLAG_UNARY = 1, + OVL_OP_FLAG_BINARY = 2, + OVL_OP_FLAG_ALLOC = 4, /* operator new or delete */ + OVL_OP_FLAG_DELETE = 1, /* operator delete */ + OVL_OP_FLAG_VEC = 2 /* vector new or delete */ + }; + +struct GTY(()) operator_name_info_t { /* The IDENTIFIER_NODE for the operator. */ tree identifier; /* The name of the operator. */ const char *name; /* The mangled name of the operator. */ const char *mangled_name; - /* The arity of the operator. */ - int arity; -} operator_name_info_t; + /* The ovl_op_flags of the operator */ + unsigned flags : 8; +}; /* A mapping from tree codes to operator name information. */ extern GTY(()) operator_name_info_t operator_name_info Index: lex.c =================================================================== --- lex.c (revision 254263) +++ lex.c (working copy) @@ -82,13 +82,6 @@ operator_name_info_t operator_name_info[ /* Similar, but for assignment operators. */ operator_name_info_t assignment_operator_name_info[(int) MAX_TREE_CODES]; -/* Initialize data structures that keep track of operator names. */ - -#define DEF_OPERATOR(NAME, C, M, AR, AP) \ - CONSTRAINT (C, sizeof "operator " + sizeof NAME <= 256); -#include "operators.def" -#undef DEF_OPERATOR - /* Get the name of the kind of identifier T. */ const char * @@ -120,28 +113,40 @@ set_identifier_kind (tree id, cp_identif IDENTIFIER_KIND_BIT_0 (id) |= (kind >> 0) & 1; } +/* Create and tag the internal operator name for the overloaded + operator PTR describes. */ + +static tree +set_operator_ident (operator_name_info_t *ptr) +{ + char buffer[32]; + size_t len = snprintf (buffer, sizeof (buffer), "operator%s%s", + &" "[ptr->name[0] && ptr->name[0] != '_' + && !ISALPHA (ptr->name[0])], + ptr->name); + gcc_checking_assert (len < sizeof (buffer)); + + tree ident = get_identifier_with_length (buffer, len); + ptr->identifier = ident; + + return ident; +} + static void init_operators (void) { tree identifier; - char buffer[256]; - struct operator_name_info_t *oni; + operator_name_info_t *oni; -#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND) \ - sprintf (buffer, "operator%s%s", !NAME[0] \ - || NAME[0] == '_' || ISALPHA (NAME[0]) ? " " : "", NAME); \ - identifier = get_identifier (buffer); \ - \ - if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \ - set_identifier_kind (identifier, KIND); \ - \ - oni = (KIND == cik_assign_op \ - ? &assignment_operator_name_info[(int) CODE] \ - : &operator_name_info[(int) CODE]); \ - oni->identifier = identifier; \ +#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \ + oni = OVL_OP_INFO (KIND == cik_assign_op, CODE); \ oni->name = NAME; \ oni->mangled_name = MANGLING; \ - oni->arity = ARITY; + oni->flags = FLAGS; \ + identifier = set_operator_ident (oni); \ + \ + if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \ + set_identifier_kind (identifier, KIND); #include "operators.def" #undef DEF_OPERATOR Index: mangle.c =================================================================== --- mangle.c (revision 254267) +++ mangle.c (working copy) @@ -1276,7 +1276,7 @@ write_unqualified_id (tree identifier) { /* The ABI says that we prefer binary operator names to unary operator names. */ - if (operator_name_info[i].arity == 2) + if (operator_name_info[i].flags == OVL_OP_FLAG_BINARY) { mangled_name = operator_name_info[i].mangled_name; break; Index: operators.def =================================================================== --- operators.def (revision 254263) +++ operators.def (working copy) @@ -45,11 +45,10 @@ along with GCC; see the file COPYING3. mangled under the new ABI. For `operator +', for example, this would be "pl". - ARITY + FLAGS - The arity of the operator, or -1 if any arity is allowed. (As - for `operator ()'.) Postincrement and postdecrement operators - are marked as binary. + ovl_op_flags bits. Postincrement and postdecrement operators are + marked as binary. ASSN_P @@ -66,95 +65,99 @@ along with GCC; see the file COPYING3. arguments are as for DEF_OPERATOR, but there is no need to provide an ASSIGNMENT_P argument; it is always zero. */ -#define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, ARITY) \ - DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, cik_simple_op) +#define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, FLAGS) \ + DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_simple_op) /* Use DEF_ASSN_OPERATOR to define an assignment operator. Its arguments are as for DEF_OPERATOR, but there is no need to provide an ASSIGNMENT_P argument; it is always one. */ -#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, ARITY) \ - DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, cik_assign_op) +#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, FLAGS) \ + DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_assign_op) /* Memory allocation operators. */ -DEF_OPERATOR ("new", NEW_EXPR, "nw", -1, cik_newdel_op) -DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na", -1, cik_newdel_op) -DEF_OPERATOR ("delete", DELETE_EXPR, "dl", -1, cik_newdel_op) -DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", -1, cik_newdel_op) +DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC, cik_newdel_op) +DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na", + OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC, cik_newdel_op) +DEF_OPERATOR ("delete", DELETE_EXPR, "dl", + OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE, cik_newdel_op) +DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", + OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC, + cik_newdel_op) /* Unary operators. */ -DEF_SIMPLE_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", 1) -DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", 1) -DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", 1) -DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", 1) -DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", 1) -DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", 1) -DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", 1) -DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", 1) -DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", 1) +DEF_SIMPLE_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", OVL_OP_FLAG_UNARY) /* These are extensions. */ -DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", 1) -DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 1) -DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1) +DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY) /* The cast operators. */ -DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", 1) -DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", 1) -DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", 1) -DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", 1) -DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", 1) +DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_UNARY) /* Binary operators. */ -DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", 2) -DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", 2) -DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", 2) -DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", 2) -DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", 2) -DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", 2) -DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", 2) -DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", 2) -DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", 2) -DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", 2) -DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", 2) -DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", 2) -DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", 2) -DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", 2) -DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", 2) -DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", 2) -DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2) -DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2) -DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2) -DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2) -DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", 2) -DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2) -DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2) -DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2) -DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2) +DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", OVL_OP_FLAG_BINARY) /* This one is needed for mangling. */ -DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", 2) +DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", OVL_OP_FLAG_BINARY) /* Assignment operators. */ -DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", 2) -DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", 2) -DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", 2) -DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", 2) -DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", 2) -DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", 2) -DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", 2) -DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", 2) -DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", 2) -DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", 2) -DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", 2) +DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", OVL_OP_FLAG_BINARY) /* Ternary operators. */ -DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3) +DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE) /* Miscellaneous. */ -DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1) +DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE) /* Variadic templates extension. */ -DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", 1) -DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", 2) -DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", 2) -DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", 3) -DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", 3) +DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_UNARY) +DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_BINARY) +DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE) ^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] overloaded operator fns [4/N] 2017-10-31 16:30 ` [C++ PATCH] overloaded operator fns [3/N] Nathan Sidwell @ 2017-10-31 18:45 ` Nathan Sidwell 2017-10-31 20:20 ` [C++ PATCH] overloaded operator fns [5/N] Nathan Sidwell 0 siblings, 1 reply; 10+ messages in thread From: Nathan Sidwell @ 2017-10-31 18:45 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 440 bytes --] The overloaded operator table conflates a couple of things -- both mangling and special names. Entries just for mangling do not need a special name. This sets them to NULL and no associated identifier is created. init_operators created a bunch of pseudo entries, ostensibly 'because errors', with a comment that we shouldn't be generating them. Turns out we don't appear to be using them, so also nuked. nathan -- Nathan Sidwell [-- Attachment #2: op-ident-4.diff --] [-- Type: text/x-patch, Size: 6111 bytes --] 2017-10-31 Nathan Sidwell <nathan@acm.org> * lex.c (init_operators): Allow NULL operator name. Don't add special cases. * operators.def: Use NULL for mangling only operators. Move to after regular operators but move assignment operators last. Index: lex.c =================================================================== --- lex.c (revision 254271) +++ lex.c (working copy) @@ -143,48 +143,14 @@ init_operators (void) oni->name = NAME; \ oni->mangled_name = MANGLING; \ oni->flags = FLAGS; \ - identifier = set_operator_ident (oni); \ - \ - if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \ - set_identifier_kind (identifier, KIND); + if (NAME) { \ + identifier = set_operator_ident (oni); \ + if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \ + set_identifier_kind (identifier, KIND); \ + } #include "operators.def" #undef DEF_OPERATOR - - operator_name_info[(int) TYPE_EXPR] = operator_name_info[(int) CAST_EXPR]; - operator_name_info[(int) ERROR_MARK].identifier - = get_identifier ("<invalid operator>"); - - /* Handle some special cases. These operators are not defined in - the language, but can be produced internally. We may need them - for error-reporting. (Eventually, we should ensure that this - does not happen. Error messages involving these operators will - be confusing to users.) */ - - operator_name_info [(int) INIT_EXPR].name - = operator_name_info [(int) MODIFY_EXPR].name; - - operator_name_info [(int) EXACT_DIV_EXPR].name = "(ceiling /)"; - operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /)"; - operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /)"; - operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /)"; - operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %)"; - operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %)"; - operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %)"; - - operator_name_info [(int) ABS_EXPR].name = "abs"; - operator_name_info [(int) TRUTH_AND_EXPR].name = "strict &&"; - operator_name_info [(int) TRUTH_OR_EXPR].name = "strict ||"; - operator_name_info [(int) RANGE_EXPR].name = "..."; - operator_name_info [(int) UNARY_PLUS_EXPR].name = "+"; - - assignment_operator_name_info [(int) EXACT_DIV_EXPR].name = "(exact /=)"; - assignment_operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /=)"; - assignment_operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /=)"; - assignment_operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /=)"; - assignment_operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %=)"; - assignment_operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %=)"; - assignment_operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %=)"; } /* Initialize the reserved words. */ Index: operators.def =================================================================== --- operators.def (revision 254271) +++ operators.def (working copy) @@ -100,13 +100,6 @@ DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_ DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY) DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY) -/* The cast operators. */ -DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_UNARY) - /* Binary operators. */ DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", OVL_OP_FLAG_BINARY) DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", OVL_OP_FLAG_BINARY) @@ -133,8 +126,23 @@ DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", OVL_OP_FLAG_BINARY) DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", OVL_OP_FLAG_BINARY) DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", OVL_OP_FLAG_BINARY) -/* This one is needed for mangling. */ -DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", OVL_OP_FLAG_BINARY) + +/* Miscellaneous. */ +DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE) + +/* Operators needed for mangling. */ +DEF_SIMPLE_OPERATOR (NULL, CAST_EXPR, "cv", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, CONST_CAST_EXPR, "cc", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, SCOPE_REF, "sr", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE) +DEF_SIMPLE_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE) /* Assignment operators. */ DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", OVL_OP_FLAG_BINARY) @@ -149,15 +157,3 @@ DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, " DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", OVL_OP_FLAG_BINARY) DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", OVL_OP_FLAG_BINARY) -/* Ternary operators. */ -DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE) - -/* Miscellaneous. */ -DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE) - -/* Variadic templates extension. */ -DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE) ^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] overloaded operator fns [5/N] 2017-10-31 18:45 ` [C++ PATCH] overloaded operator fns [4/N] Nathan Sidwell @ 2017-10-31 20:20 ` Nathan Sidwell 2017-11-01 14:02 ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell 0 siblings, 1 reply; 10+ messages in thread From: Nathan Sidwell @ 2017-10-31 20:20 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 496 bytes --] This patch replaces the separate operator_name_info & assignment_operator_name_info arrays with a single 2D ovl_op_info array. I also add a tree_code field to the renamed ovl_op_info_t, which although in this instance is simply a 1:1 mapping to the array index, will morph soon as the indices will not be by tree_code. Although this tweaks the array scanning, the ultimate aim is that that scanning goes away, and a simple indirection gets us to what we want. nathan -- Nathan Sidwell [-- Attachment #2: op-ident-5.diff --] [-- Type: text/x-patch, Size: 8787 bytes --] 2017-10-31 Nathan Sidwell <nathan@acm.org> * cp-tree.h (struct operator_name_info_t): Rename to ... (struct ovl_op_info_t): ... here. Add tree_code field. (operator_name_info, assignment_operator_name_info): Delete. (ovl_op_info): Declare. (OVL_OP_INFO): Adjust. * decl.c (grok_op_properties): Use ovl_op_flags. * lex.c (operator_name_info, assignment_operator_name_info): Delete. (ovl_op_info): Define. (set_operator_ident): Adjust. (init_operators): Set tree_code. * mangle.c (write_unqualified_id): Adjust operator array scan. Index: cp-tree.h =================================================================== --- cp-tree.h (revision 254271) +++ cp-tree.h (working copy) @@ -5485,29 +5485,26 @@ enum ovl_op_flags OVL_OP_FLAG_VEC = 2 /* vector new or delete */ }; -struct GTY(()) operator_name_info_t { +struct GTY(()) ovl_op_info_t { /* The IDENTIFIER_NODE for the operator. */ tree identifier; /* The name of the operator. */ const char *name; /* The mangled name of the operator. */ const char *mangled_name; + /* The tree code. */ + enum tree_code tree_code : 16; /* The ovl_op_flags of the operator */ unsigned flags : 8; }; -/* A mapping from tree codes to operator name information. */ -extern GTY(()) operator_name_info_t operator_name_info - [(int) MAX_TREE_CODES]; -/* Similar, but for assignment operators. */ -extern GTY(()) operator_name_info_t assignment_operator_name_info - [(int) MAX_TREE_CODES]; +/* Overloaded operator info indexed by ass_op_p & tree_code. */ +extern GTY(()) ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES]; /* Given an ass_op_p boolean and a tree code, return a pointer to its overloaded operator info. */ #define OVL_OP_INFO(IS_ASS_P, TREE_CODE) \ - (((IS_ASS_P) ? assignment_operator_name_info : operator_name_info) \ - + (TREE_CODE)) + (&ovl_op_info[(IS_ASS_P) != 0][(TREE_CODE)]) /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL constants. */ Index: decl.c =================================================================== --- decl.c (revision 254267) +++ decl.c (working copy) @@ -12898,8 +12898,8 @@ unary_op_p (enum tree_code code) || code == TYPE_EXPR); } -/* DECL is a declaration for an overloaded operator. If COMPLAIN is true, - errors are issued for invalid declarations. */ +/* DECL is a declaration for an overloaded or conversion operator. If + COMPLAIN is true, errors are issued for invalid declarations. */ bool grok_op_properties (tree decl, bool complain) @@ -12912,52 +12912,54 @@ grok_op_properties (tree decl, bool comp if (class_type && !CLASS_TYPE_P (class_type)) class_type = NULL_TREE; - enum tree_code operator_code = ERROR_MARK; + tree_code operator_code = ERROR_MARK; + unsigned op_flags = OVL_OP_FLAG_NONE; if (IDENTIFIER_CONV_OP_P (name)) - operator_code = TYPE_EXPR; + { + /* Conversion operators are TYPE_EXPR for the purposes of this + function. */ + operator_code = TYPE_EXPR; + op_flags = OVL_OP_FLAG_UNARY; + } else { /* It'd be nice to hang something else of the identifier to find CODE more directly. */ bool assign_op = IDENTIFIER_ASSIGN_OP_P (name); - const operator_name_info_t *oni - = (assign_op ? assignment_operator_name_info : operator_name_info); - + const ovl_op_info_t *ovl_op = OVL_OP_INFO (assign_op, 0); if (false) ; -#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND) \ - else if (assign_op == (KIND == cik_assign_op) \ - && oni[int (CODE)].identifier == name) \ +#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \ + else if (ovl_op[CODE].identifier == name) \ operator_code = (CODE); #include "operators.def" #undef DEF_OPERATOR else gcc_unreachable (); - } - while (0); - gcc_assert (operator_code != MAX_TREE_CODES); - DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; + gcc_assert (operator_code != ERROR_MARK); + op_flags = ovl_op[operator_code].flags; + DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; + } - if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR - || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR) + if (op_flags & OVL_OP_FLAG_ALLOC) { /* operator new and operator delete are quite special. */ if (class_type) - switch (operator_code) + switch (op_flags) { - case NEW_EXPR: + case OVL_OP_FLAG_ALLOC: TYPE_HAS_NEW_OPERATOR (class_type) = 1; break; - case DELETE_EXPR: + case OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE: TYPE_GETS_DELETE (class_type) |= 1; break; - case VEC_NEW_EXPR: + case OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC: TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1; break; - case VEC_DELETE_EXPR: + case OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC: TYPE_GETS_DELETE (class_type) |= 2; break; @@ -12987,12 +12989,12 @@ grok_op_properties (tree decl, bool comp } } - if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR) + if (op_flags & OVL_OP_FLAG_DELETE) TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl)); else { - TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); DECL_IS_OPERATOR_NEW (decl) = 1; + TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); } return true; @@ -13043,9 +13045,9 @@ grok_op_properties (tree decl, bool comp } } - /* There are no restrictions on the arguments to an overloaded - "operator ()". */ if (operator_code == CALL_EXPR) + /* There are no further restrictions on the arguments to an overloaded + "operator ()". */ return true; if (operator_code == COND_EXPR) Index: lex.c =================================================================== --- lex.c (revision 254276) +++ lex.c (working copy) @@ -77,10 +77,7 @@ cxx_finish (void) c_common_finish (); } -/* A mapping from tree codes to operator name information. */ -operator_name_info_t operator_name_info[(int) MAX_TREE_CODES]; -/* Similar, but for assignment operators. */ -operator_name_info_t assignment_operator_name_info[(int) MAX_TREE_CODES]; +ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES]; /* Get the name of the kind of identifier T. */ @@ -117,7 +114,7 @@ set_identifier_kind (tree id, cp_identif operator PTR describes. */ static tree -set_operator_ident (operator_name_info_t *ptr) +set_operator_ident (ovl_op_info_t *ptr) { char buffer[32]; size_t len = snprintf (buffer, sizeof (buffer), "operator%s%s", @@ -136,12 +133,13 @@ static void init_operators (void) { tree identifier; - operator_name_info_t *oni; + ovl_op_info_t *oni; #define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \ oni = OVL_OP_INFO (KIND == cik_assign_op, CODE); \ oni->name = NAME; \ oni->mangled_name = MANGLING; \ + oni->tree_code = CODE; \ oni->flags = FLAGS; \ if (NAME) { \ identifier = set_operator_ident (oni); \ Index: mangle.c =================================================================== --- mangle.c (revision 254271) +++ mangle.c (working copy) @@ -1265,32 +1265,29 @@ write_unqualified_id (tree identifier) write_conversion_operator_name (TREE_TYPE (identifier)); else if (IDENTIFIER_ANY_OP_P (identifier)) { - int i; const char *mangled_name = NULL; + bool assop = IDENTIFIER_ASSIGN_OP_P (identifier); /* Unfortunately, there is no easy way to go from the name of the operator back to the corresponding tree code. */ - for (i = 0; i < MAX_TREE_CODES; ++i) - if (operator_name_info[i].identifier == identifier) - { - /* The ABI says that we prefer binary operator - names to unary operator names. */ - if (operator_name_info[i].flags == OVL_OP_FLAG_BINARY) - { - mangled_name = operator_name_info[i].mangled_name; - break; - } - else if (!mangled_name) - mangled_name = operator_name_info[i].mangled_name; - } - else if (assignment_operator_name_info[i].identifier - == identifier) - { - mangled_name - = assignment_operator_name_info[i].mangled_name; - break; - } + for (unsigned i = 0; i < MAX_TREE_CODES; ++i) + { + const ovl_op_info_t *ovl_op = OVL_OP_INFO (assop, i); + + if (ovl_op->identifier == identifier) + { + /* The ABI says that we prefer binary operator + names to unary operator names. */ + if (ovl_op->flags == OVL_OP_FLAG_BINARY) + { + mangled_name = ovl_op->mangled_name; + break; + } + else if (!mangled_name) + mangled_name = ovl_op->mangled_name; + } + } write_string (mangled_name); } else if (UDLIT_OPER_P (identifier)) ^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] overloaded operator fns [6/N] 2017-10-31 20:20 ` [C++ PATCH] overloaded operator fns [5/N] Nathan Sidwell @ 2017-11-01 14:02 ` Nathan Sidwell 2017-11-01 15:45 ` Nathan Sidwell 2017-11-01 18:29 ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell 0 siblings, 2 replies; 10+ messages in thread From: Nathan Sidwell @ 2017-11-01 14:02 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 711 bytes --] This patch adds a new enum for the overloaded operators, we only enumerate the codes we need, and thus can shrink the ovl_op_info array. We do need to create a mapping array to go from tree_code to ovl_op_code. More significantly is the use of the base.u.bits.address_space field, which is otherwise unused in an identifier. We can use this as an arbitrary 8-bit index. Which indeed this patch does for the overloaded operators. This means grok_op_properties and mangling can directly index the operator information, rather than search for them. We also simplify the ambi-ary operators by detecting these cases during initialization and constructing an alternate array. nathan -- Nathan Sidwell [-- Attachment #2: op-ident-6.diff --] [-- Type: text/x-patch, Size: 26043 bytes --] 2017-11-01 Nathan Sidwell <nathan@acm.org> * cp-tree.h (IDENTIFIER_CP_INDEX): Define. (enum ovl_op_flags): Add OVL_OP_FLAG_AMBIARY. (enum ovl_op_code): New. (struct ovl_op_info): Add ovl_op_code field. (ovl_op_info): Size by OVL_OP_MAX. (ovl_op_mapping, ovl_op_alternate): Declare. (OVL_OP_INFO): Adjust for mapping array. (IDENTIFIER_OVL_OP_INFO): New. * decl.c (ambi_op_p, unary_op_p): Delete. (grok_op_properties): Use IDENTIFIER_OVL_OP_INFO and ovl_op_alternate. * lex.c (ovl_op_info): Adjust and static initialize. (ovl_op_mappings, ovl_op_alternate): Define. (init_operators): Iterate over ovl_op_info array and init mappings & alternate arrays. * mangle.c (write_unqualified_id): Use IDENTIFIER_OVL_OP_INFO. * operators.def (DEF_OPERATOR): Remove KIND parm. (DEF_SIMPLE_OPERATOR): Delete. (OPERATOR_TRANSITION): Expand if defined. Index: cp-tree.h =================================================================== --- cp-tree.h (revision 254279) +++ cp-tree.h (working copy) @@ -1072,6 +1072,11 @@ enum cp_identifier_kind { & IDENTIFIER_KIND_BIT_1 (NODE) \ & IDENTIFIER_KIND_BIT_0 (NODE)) +/* Access a C++-specific index for identifier NODE. + Used to optimize operator mappings etc. */ +#define IDENTIFIER_CP_INDEX(NODE) \ + (IDENTIFIER_NODE_CHECK(NODE)->base.u.bits.address_space) + /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */ #define C_TYPE_FIELDS_READONLY(TYPE) \ (LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly) @@ -5477,12 +5482,25 @@ extern void init_reswords (void); /* Various flags for the overloaded operator information. */ enum ovl_op_flags { - OVL_OP_FLAG_NONE = 0, - OVL_OP_FLAG_UNARY = 1, - OVL_OP_FLAG_BINARY = 2, - OVL_OP_FLAG_ALLOC = 4, /* operator new or delete */ - OVL_OP_FLAG_DELETE = 1, /* operator delete */ - OVL_OP_FLAG_VEC = 2 /* vector new or delete */ + OVL_OP_FLAG_NONE = 0, /* Don't care. */ + OVL_OP_FLAG_UNARY = 1, /* Is unary. */ + OVL_OP_FLAG_BINARY = 2, /* Is binary. */ + OVL_OP_FLAG_AMBIARY = 3, /* May be unary or binary. */ + OVL_OP_FLAG_ALLOC = 4, /* operator new or delete. */ + OVL_OP_FLAG_DELETE = 1, /* operator delete. */ + OVL_OP_FLAG_VEC = 2 /* vector new or delete. */ + }; + +/* Compressed operator codes. Order is determined by operators.def + and does not match that of tree_codes. */ +enum ovl_op_code + { + OVL_OP_ERROR_MARK, + OVL_OP_NOP_EXPR, +#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) OVL_OP_##CODE, +#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING) /* NOTHING */ +#include "operators.def" + OVL_OP_MAX }; struct GTY(()) ovl_op_info_t { @@ -5492,19 +5510,29 @@ struct GTY(()) ovl_op_info_t { const char *name; /* The mangled name of the operator. */ const char *mangled_name; - /* The tree code. */ + /* The (regular) tree code. */ enum tree_code tree_code : 16; + /* The (compressed) operator code. */ + enum ovl_op_code ovl_op_code : 8; /* The ovl_op_flags of the operator */ unsigned flags : 8; }; -/* Overloaded operator info indexed by ass_op_p & tree_code. */ -extern GTY(()) ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES]; +/* Overloaded operator info indexed by ass_op_p & ovl_op_code. */ +extern GTY(()) ovl_op_info_t ovl_op_info[2][OVL_OP_MAX]; +/* Mapping from tree_codes to ovl_op_codes. */ +extern GTY(()) unsigned char ovl_op_mapping[MAX_TREE_CODES]; +/* Mapping for ambi-ary operators from the binary to the unary. */ +extern GTY(()) unsigned char ovl_op_alternate[OVL_OP_MAX]; /* Given an ass_op_p boolean and a tree code, return a pointer to its overloaded operator info. */ #define OVL_OP_INFO(IS_ASS_P, TREE_CODE) \ - (&ovl_op_info[(IS_ASS_P) != 0][(TREE_CODE)]) + (&ovl_op_info[(IS_ASS_P) != 0][ovl_op_mapping[(TREE_CODE)]]) +/* Overloaded operator info for an identifier for which + IDENTIFIER_ANY_OP_P is true. */ +#define IDENTIFIER_OVL_OP_INFO(NODE) \ + (&ovl_op_info[IDENTIFIER_ASSIGN_OP_P (NODE)][IDENTIFIER_CP_INDEX (NODE)]) /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL constants. */ Index: decl.c =================================================================== --- decl.c (revision 254279) +++ decl.c (working copy) @@ -65,8 +65,6 @@ static const char *redeclaration_error_m static int decl_jump_unsafe (tree); static void require_complete_types_for_parms (tree); -static bool ambi_op_p (enum tree_code); -static bool unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, @@ -12874,30 +12872,6 @@ grok_ctor_properties (const_tree ctype, return true; } -/* An operator with this code is unary, but can also be binary. */ - -static bool -ambi_op_p (enum tree_code code) -{ - return (code == INDIRECT_REF - || code == ADDR_EXPR - || code == UNARY_PLUS_EXPR - || code == NEGATE_EXPR - || code == PREINCREMENT_EXPR - || code == PREDECREMENT_EXPR); -} - -/* An operator with this name can only be unary. */ - -static bool -unary_op_p (enum tree_code code) -{ - return (code == TRUTH_NOT_EXPR - || code == BIT_NOT_EXPR - || code == COMPONENT_REF - || code == TYPE_EXPR); -} - /* DECL is a declaration for an overloaded or conversion operator. If COMPLAIN is true, errors are issued for invalid declarations. */ @@ -12905,15 +12879,15 @@ bool grok_op_properties (tree decl, bool complain) { tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); - int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); + bool methodp = TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE; tree name = DECL_NAME (decl); tree class_type = DECL_CONTEXT (decl); if (class_type && !CLASS_TYPE_P (class_type)) class_type = NULL_TREE; - tree_code operator_code = ERROR_MARK; - unsigned op_flags = OVL_OP_FLAG_NONE; + tree_code operator_code; + unsigned op_flags; if (IDENTIFIER_CONV_OP_P (name)) { /* Conversion operators are TYPE_EXPR for the purposes of this @@ -12923,21 +12897,11 @@ grok_op_properties (tree decl, bool comp } else { - /* It'd be nice to hang something else of the identifier to - find CODE more directly. */ - bool assign_op = IDENTIFIER_ASSIGN_OP_P (name); - const ovl_op_info_t *ovl_op = OVL_OP_INFO (assign_op, 0); - if (false) - ; -#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \ - else if (ovl_op[CODE].identifier == name) \ - operator_code = (CODE); -#include "operators.def" -#undef DEF_OPERATOR - else - gcc_unreachable (); - gcc_assert (operator_code != ERROR_MARK); - op_flags = ovl_op[operator_code].flags; + const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (name); + + operator_code = ovl_op->tree_code; + op_flags = ovl_op->flags; + gcc_checking_assert (operator_code != ERROR_MARK); DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; } @@ -13071,70 +13035,43 @@ grok_op_properties (tree decl, bool comp } /* Verify correct number of arguments. */ - if (ambi_op_p (operator_code)) + switch (op_flags) { + case OVL_OP_FLAG_AMBIARY: if (arity == 1) - /* We pick the one-argument operator codes by default, so - we don't have to change anything. */ - ; - else if (arity == 2) { - /* If we thought this was a unary operator, we now know - it to be a binary operator. */ - switch (operator_code) - { - case INDIRECT_REF: - operator_code = MULT_EXPR; - break; - - case ADDR_EXPR: - operator_code = BIT_AND_EXPR; - break; - - case UNARY_PLUS_EXPR: - operator_code = PLUS_EXPR; - break; - - case NEGATE_EXPR: - operator_code = MINUS_EXPR; - break; - - case PREINCREMENT_EXPR: - operator_code = POSTINCREMENT_EXPR; - break; - - case PREDECREMENT_EXPR: - operator_code = POSTDECREMENT_EXPR; - break; - - default: - gcc_unreachable (); - } - + /* We have a unary instance of an ambi-ary op. Remap to the + unary one. */ + unsigned alt = ovl_op_alternate[ovl_op_mapping [operator_code]]; + const ovl_op_info_t *ovl_op = &ovl_op_info[false][alt]; + gcc_checking_assert (ovl_op->flags == OVL_OP_FLAG_UNARY); + operator_code = ovl_op->tree_code; DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; - - if ((operator_code == POSTINCREMENT_EXPR - || operator_code == POSTDECREMENT_EXPR) - && ! processing_template_decl - && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node)) - { - error (methodp - ? G_("postfix %qD must have %<int%> as its argument") - : G_("postfix %qD must have %<int%> as its second argument"), - decl); - return false; - } } - else + else if (arity != 2) { + /* This was an ambiguous operator but is invalid. */ error (methodp ? G_("%qD must have either zero or one argument") : G_("%qD must have either one or two arguments"), decl); return false; } - } - else if (unary_op_p (operator_code)) - { + else if ((operator_code == POSTINCREMENT_EXPR + || operator_code == POSTDECREMENT_EXPR) + && ! processing_template_decl + /* x++ and x--'s second argument must be an int. */ + && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), + integer_type_node)) + { + error (methodp + ? G_("postfix %qD must have %<int%> as its argument") + : G_("postfix %qD must have %<int%> as its second argument"), + decl); + return false; + } + break; + + case OVL_OP_FLAG_UNARY: if (arity != 1) { error (methodp @@ -13142,9 +13079,9 @@ grok_op_properties (tree decl, bool comp : G_("%qD must have exactly one argument"), decl); return false; } - } - else - { + break; + + case OVL_OP_FLAG_BINARY: if (arity != 2) { error (methodp @@ -13152,8 +13089,12 @@ grok_op_properties (tree decl, bool comp : G_("%qD must have exactly two arguments"), decl); return false; } + break; + + default: + gcc_unreachable (); } - + /* There can be no default arguments. */ for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg)) if (TREE_PURPOSE (arg)) Index: lex.c =================================================================== --- lex.c (revision 254279) +++ lex.c (working copy) @@ -77,7 +77,20 @@ cxx_finish (void) c_common_finish (); } -ovl_op_info_t ovl_op_info[2][MAX_TREE_CODES]; +ovl_op_info_t ovl_op_info[2][OVL_OP_MAX] = + { + { + {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0}, + {NULL_TREE, NULL, NULL, NOP_EXPR, OVL_OP_NOP_EXPR, 0}, +#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) \ + {NULL_TREE, NAME, MANGLING, CODE, OVL_OP_##CODE, FLAGS}, +#define OPERATOR_TRANSITION }, { \ + {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0}, +#include "operators.def" + } + }; +unsigned char ovl_op_mapping[MAX_TREE_CODES]; +unsigned char ovl_op_alternate[OVL_OP_MAX]; /* Get the name of the kind of identifier T. */ @@ -129,26 +142,77 @@ set_operator_ident (ovl_op_info_t *ptr) return ident; } +/* Initialize data structures that keep track of operator names. */ + static void init_operators (void) { - tree identifier; - ovl_op_info_t *oni; + /* We rely on both these being zero. */ + gcc_checking_assert (!OVL_OP_ERROR_MARK && !ERROR_MARK); -#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, KIND) \ - oni = OVL_OP_INFO (KIND == cik_assign_op, CODE); \ - oni->name = NAME; \ - oni->mangled_name = MANGLING; \ - oni->tree_code = CODE; \ - oni->flags = FLAGS; \ - if (NAME) { \ - identifier = set_operator_ident (oni); \ - if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \ - set_identifier_kind (identifier, KIND); \ - } - -#include "operators.def" -#undef DEF_OPERATOR + /* This loop iterates backwards because we need to move the + assignment operators down to their correct slots. I.e. morally + equivalent to an overlapping memmove where dest > src. Slot + zero is for error_mark, so hae no operator. */ + for (unsigned ix = OVL_OP_MAX; --ix;) + { + ovl_op_info_t *op_ptr = &ovl_op_info[false][ix]; + + if (op_ptr->name) + { + /* Make sure it fits in lang_decl_fn::operator_code. */ + gcc_checking_assert (op_ptr->ovl_op_code < (1 << 6)); + tree ident = set_operator_ident (op_ptr); + if (unsigned index = IDENTIFIER_CP_INDEX (ident)) + { + ovl_op_info_t *bin_ptr = &ovl_op_info[false][index]; + + /* They should only differ in unary/binary ness. */ + gcc_checking_assert ((op_ptr->flags ^ bin_ptr->flags) + == OVL_OP_FLAG_AMBIARY); + bin_ptr->flags |= op_ptr->flags; + ovl_op_alternate[index] = ix; + } + else + { + IDENTIFIER_CP_INDEX (ident) = ix; + set_identifier_kind (ident, + op_ptr->flags & OVL_OP_FLAG_ALLOC + ? cik_newdel_op : cik_simple_op); + } + } + if (op_ptr->tree_code) + { + gcc_checking_assert (op_ptr->ovl_op_code == ix + && !ovl_op_mapping[op_ptr->tree_code]); + ovl_op_mapping[op_ptr->tree_code] = op_ptr->ovl_op_code; + } + + ovl_op_info_t *as_ptr = &ovl_op_info[true][ix]; + if (as_ptr->name) + { + /* These will be placed at the start of the array, move to + the correct slot and initialize. */ + if (as_ptr->ovl_op_code != ix) + { + ovl_op_info_t *dst_ptr = &ovl_op_info[true][as_ptr->ovl_op_code]; + gcc_assert (as_ptr->ovl_op_code > ix && !dst_ptr->tree_code); + memcpy (dst_ptr, as_ptr, sizeof (*dst_ptr)); + memset (as_ptr, 0, sizeof (*as_ptr)); + as_ptr = dst_ptr; + } + + tree ident = set_operator_ident (as_ptr); + gcc_checking_assert (!IDENTIFIER_CP_INDEX (ident)); + IDENTIFIER_CP_INDEX (ident) = as_ptr->ovl_op_code; + set_identifier_kind (ident, cik_assign_op); + + gcc_checking_assert (!ovl_op_mapping[as_ptr->tree_code] + || (ovl_op_mapping[as_ptr->tree_code] + == as_ptr->ovl_op_code)); + ovl_op_mapping[as_ptr->tree_code] = as_ptr->ovl_op_code; + } + } } /* Initialize the reserved words. */ Index: mangle.c =================================================================== --- mangle.c (revision 254279) +++ mangle.c (working copy) @@ -1265,30 +1265,8 @@ write_unqualified_id (tree identifier) write_conversion_operator_name (TREE_TYPE (identifier)); else if (IDENTIFIER_ANY_OP_P (identifier)) { - const char *mangled_name = NULL; - bool assop = IDENTIFIER_ASSIGN_OP_P (identifier); - - /* Unfortunately, there is no easy way to go from the - name of the operator back to the corresponding tree - code. */ - for (unsigned i = 0; i < MAX_TREE_CODES; ++i) - { - const ovl_op_info_t *ovl_op = OVL_OP_INFO (assop, i); - - if (ovl_op->identifier == identifier) - { - /* The ABI says that we prefer binary operator - names to unary operator names. */ - if (ovl_op->flags == OVL_OP_FLAG_BINARY) - { - mangled_name = ovl_op->mangled_name; - break; - } - else if (!mangled_name) - mangled_name = ovl_op->mangled_name; - } - } - write_string (mangled_name); + const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (identifier); + write_string (ovl_op->mangled_name); } else if (UDLIT_OPER_P (identifier)) write_literal_operator_name (identifier); Index: operators.def =================================================================== --- operators.def (revision 254279) +++ operators.def (working copy) @@ -50,110 +50,109 @@ along with GCC; see the file COPYING3. ovl_op_flags bits. Postincrement and postdecrement operators are marked as binary. - ASSN_P - - A boolean value. If nonzero, this is an assignment operator. - Before including this file, you should define DEF_OPERATOR to take these arguments. There is code (such as in grok_op_properties) that depends on the - order the operators are presented in this file. In particular, - unary operators must precede binary operators. */ - -/* Use DEF_SIMPLE_OPERATOR to define a non-assignment operator. Its - arguments are as for DEF_OPERATOR, but there is no need to provide - an ASSIGNMENT_P argument; it is always zero. */ - -#define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, FLAGS) \ - DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_simple_op) + order the operators are presented in this file. Unary_ops must + preceed a matching binary op (i.e. '+'). Assignment operators must + be last, after OPERATOR_TRANSITION. */ /* Use DEF_ASSN_OPERATOR to define an assignment operator. Its arguments are as for DEF_OPERATOR, but there is no need to provide - an ASSIGNMENT_P argument; it is always one. */ + FLAGS (OVL_OP_FLAG_BINARY). */ -#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, FLAGS) \ - DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, cik_assign_op) +#ifndef DEF_ASSN_OPERATOR +#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING) \ + DEF_OPERATOR(NAME, CODE, MANGLING, OVL_OP_FLAG_BINARY) +#endif -/* Memory allocation operators. */ -DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC, cik_newdel_op) +/* Memory allocation operators. ARITY has special meaning. */ +DEF_OPERATOR ("new", NEW_EXPR, "nw", OVL_OP_FLAG_ALLOC) DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na", - OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC, cik_newdel_op) + OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC) DEF_OPERATOR ("delete", DELETE_EXPR, "dl", - OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE, cik_newdel_op) + OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE) DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", - OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC, - cik_newdel_op) + OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC) /* Unary operators. */ -DEF_SIMPLE_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("-", NEGATE_EXPR, "ng", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("&", ADDR_EXPR, "ad", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("*", INDIRECT_REF, "de", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("~", BIT_NOT_EXPR, "co", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("-", NEGATE_EXPR, "ng", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("&", ADDR_EXPR, "ad", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("*", INDIRECT_REF, "de", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("~", BIT_NOT_EXPR, "co", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("!", TRUTH_NOT_EXPR, "nt", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("++", PREINCREMENT_EXPR, "pp", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("--", PREDECREMENT_EXPR, "mm", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("->", COMPONENT_REF, "pt", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", OVL_OP_FLAG_UNARY) + /* These are extensions. */ -DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY) -DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("alignof", ALIGNOF_EXPR, "az", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", OVL_OP_FLAG_UNARY) +DEF_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", OVL_OP_FLAG_UNARY) /* Binary operators. */ -DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("-", MINUS_EXPR, "mi", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("*", MULT_EXPR, "ml", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("&", BIT_AND_EXPR, "an", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("|", BIT_IOR_EXPR, "or", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("^", BIT_XOR_EXPR, "eo", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("<<", LSHIFT_EXPR, "ls", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR (">>", RSHIFT_EXPR, "rs", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("==", EQ_EXPR, "eq", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("!=", NE_EXPR, "ne", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("<", LT_EXPR, "lt", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR (">", GT_EXPR, "gt", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("<=", LE_EXPR, "le", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR (">=", GE_EXPR, "ge", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", OVL_OP_FLAG_BINARY) -DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("+", PLUS_EXPR, "pl", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("-", MINUS_EXPR, "mi", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("*", MULT_EXPR, "ml", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("/", TRUNC_DIV_EXPR, "dv", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("%", TRUNC_MOD_EXPR, "rm", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("&", BIT_AND_EXPR, "an", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("|", BIT_IOR_EXPR, "or", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("^", BIT_XOR_EXPR, "eo", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("<<", LSHIFT_EXPR, "ls", OVL_OP_FLAG_BINARY) +DEF_OPERATOR (">>", RSHIFT_EXPR, "rs", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("==", EQ_EXPR, "eq", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("!=", NE_EXPR, "ne", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("<", LT_EXPR, "lt", OVL_OP_FLAG_BINARY) +DEF_OPERATOR (">", GT_EXPR, "gt", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("<=", LE_EXPR, "le", OVL_OP_FLAG_BINARY) +DEF_OPERATOR (">=", GE_EXPR, "ge", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", OVL_OP_FLAG_BINARY) +DEF_OPERATOR (",", COMPOUND_EXPR, "cm", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("->*", MEMBER_REF, "pm", OVL_OP_FLAG_BINARY) +DEF_OPERATOR (".*", DOTSTAR_EXPR, "ds", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("[]", ARRAY_REF, "ix", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", OVL_OP_FLAG_BINARY) +DEF_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", OVL_OP_FLAG_BINARY) /* Miscellaneous. */ -DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE) +DEF_OPERATOR ("?:", COND_EXPR, "qu", OVL_OP_FLAG_NONE) +DEF_OPERATOR ("()", CALL_EXPR, "cl", OVL_OP_FLAG_NONE) /* Operators needed for mangling. */ -DEF_SIMPLE_OPERATOR (NULL, CAST_EXPR, "cv", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, CONST_CAST_EXPR, "cc", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, SCOPE_REF, "sr", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE) -DEF_SIMPLE_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE) +DEF_OPERATOR (NULL, CAST_EXPR, "cv", OVL_OP_FLAG_UNARY) +DEF_OPERATOR (NULL, DYNAMIC_CAST_EXPR, "dc", OVL_OP_FLAG_UNARY) +DEF_OPERATOR (NULL, REINTERPRET_CAST_EXPR, "rc", OVL_OP_FLAG_UNARY) +DEF_OPERATOR (NULL, CONST_CAST_EXPR, "cc", OVL_OP_FLAG_UNARY) +DEF_OPERATOR (NULL, STATIC_CAST_EXPR, "sc", OVL_OP_FLAG_UNARY) +DEF_OPERATOR (NULL, SCOPE_REF, "sr", OVL_OP_FLAG_NONE) +DEF_OPERATOR (NULL, EXPR_PACK_EXPANSION, "sp", OVL_OP_FLAG_NONE) +DEF_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, "fl", OVL_OP_FLAG_NONE) +DEF_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, "fr", OVL_OP_FLAG_NONE) +DEF_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, "fL", OVL_OP_FLAG_NONE) +DEF_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, "fR", OVL_OP_FLAG_NONE) + +#ifdef OPERATOR_TRANSITION +OPERATOR_TRANSITION +#undef OPERATOR_TRANSITION +#endif /* Assignment operators. */ -DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", OVL_OP_FLAG_BINARY) -DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", OVL_OP_FLAG_BINARY) +DEF_ASSN_OPERATOR ("=", NOP_EXPR, "aS") +DEF_ASSN_OPERATOR ("+=", PLUS_EXPR, "pL") +DEF_ASSN_OPERATOR ("-=", MINUS_EXPR, "mI") +DEF_ASSN_OPERATOR ("*=", MULT_EXPR, "mL") +DEF_ASSN_OPERATOR ("/=", TRUNC_DIV_EXPR, "dV") +DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR, "rM") +DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN") +DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR") +DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO") +DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS") +DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS") +#undef DEF_ASSN_OPERATOR +#undef DEF_OPERATOR ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] overloaded operator fns [6/N] 2017-11-01 14:02 ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell @ 2017-11-01 15:45 ` Nathan Sidwell 2017-11-01 18:29 ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell 1 sibling, 0 replies; 10+ messages in thread From: Nathan Sidwell @ 2017-11-01 15:45 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 506 bytes --] This patch shrinks the lang_fn_decl's operator_code field from 16 to 6 bits, by storing the compressed operator code instead of the tree_code. I rename DECL_OVERLOADED_OPERATOR_CODE to DECL_OVERLOADED_OPERATOR_CODE_RAW, to remind that it's not a tree_code. DECL_OVERLOADED_OPERATOR_CODE_IS remains with checking a literal tree code. It uses preprocessor concatenation to directly map the tree_code name to the compressed operator enumeration. So no runtime indirection! nathan -- Nathan Sidwell [-- Attachment #2: op-ident-7.diff --] [-- Type: text/x-patch, Size: 8237 bytes --] 2017-11-01 Nathan Sidwell <nathan@acm.org> gcc/cp/ * cp-tree.h (assign_op_identifier, call_op_identifier): Use compressed code. (struct lang_decl_fn): Use compressed operator code. (DECL_OVERLOADED_OPERATOR_CODE): Replace with ... (DECL_OVERLOADED_OPERATOR_CODE_RAW): ... this. (DECL_OVERLOADED_OPERATOR_CODE_IS): Use it. * decl.c (duplicate_decls): Use DECL_OVERLOADED_OPERATOR_CODE_RAW. (build_library_fn): Likewise. (grok_op_properties): Likewise. * mangle.c (write_unqualified_name): Likewise. * method.c (implicitly_declare_fn): Likewise. * typeck.c (check_return_expr): Use DECL_OVERLOADED_OPERATOR_IS. libcc1/ * libcp1plugin.cc (plugin_build_decl): Use DECL_OVERLOADED_OPERATOR_CODE_RAW. Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 254311) +++ gcc/cp/cp-tree.h (working copy) @@ -246,8 +246,8 @@ extern GTY(()) tree cp_global_trees[CPTI #define deleting_dtor_identifier cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER] #define ovl_op_identifier(ISASS, CODE) (OVL_OP_INFO(ISASS, CODE)->identifier) -#define assign_op_identifier (ovl_op_identifier (true, NOP_EXPR)) -#define call_op_identifier (ovl_op_identifier (false, CALL_EXPR)) +#define assign_op_identifier (ovl_op_info[true][OVL_OP_NOP_EXPR].identifier) +#define call_op_identifier (ovl_op_info[false][OVL_OP_CALL_EXPR].identifier) /* The name used for conversion operators -- but note that actual conversion functions use special identifiers outside the identifier table. */ @@ -2479,26 +2479,24 @@ struct GTY(()) lang_decl_min { struct GTY(()) lang_decl_fn { struct lang_decl_min min; - /* In an overloaded operator, this is the value of - DECL_OVERLOADED_OPERATOR_P. - FIXME: We should really do better in compressing this. */ - ENUM_BITFIELD (tree_code) operator_code : 16; - + /* In a overloaded operator, this is the compressed operator code. */ + unsigned ovl_op_code : 6; unsigned global_ctor_p : 1; unsigned global_dtor_p : 1; + unsigned static_function : 1; unsigned pure_virtual : 1; unsigned defaulted_p : 1; unsigned has_in_charge_parm_p : 1; unsigned has_vtt_parm_p : 1; unsigned pending_inline_p : 1; - unsigned nonconverting : 1; unsigned thunk_p : 1; + unsigned this_thunk_p : 1; unsigned hidden_friend_p : 1; unsigned omp_declare_reduction_p : 1; - /* 3 spare bits. */ + unsigned spare : 13; /* 32-bits padding on 64-bit host. */ @@ -2814,14 +2812,14 @@ struct GTY(()) lang_decl { 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) + compressed (raw) operator code. Note that this is not a TREE_CODE. */ +#define DECL_OVERLOADED_OPERATOR_CODE_RAW(NODE) \ + (LANG_DECL_FN_CHECK (NODE)->ovl_op_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) + (DECL_OVERLOADED_OPERATOR_CODE_RAW (DECL) == OVL_OP_##CODE) /* For FUNCTION_DECLs: nonzero means that this function is a constructor or a destructor with an extra in-charge parameter to @@ -5526,7 +5524,8 @@ extern GTY(()) unsigned char ovl_op_mapp extern GTY(()) unsigned char ovl_op_alternate[OVL_OP_MAX]; /* Given an ass_op_p boolean and a tree code, return a pointer to its - overloaded operator info. */ + overloaded operator info. Tree codes for non-overloaded operators + map to the error-operator. */ #define OVL_OP_INFO(IS_ASS_P, TREE_CODE) \ (&ovl_op_info[(IS_ASS_P) != 0][ovl_op_mapping[(TREE_CODE)]]) /* Overloaded operator info for an identifier for which Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 254311) +++ gcc/cp/decl.c (working copy) @@ -1920,8 +1920,8 @@ next_arg:; DECL_OVERRIDE_P (newdecl) |= DECL_OVERRIDE_P (olddecl); DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl); if (DECL_OVERLOADED_OPERATOR_P (olddecl)) - DECL_OVERLOADED_OPERATOR_CODE (newdecl) - = DECL_OVERLOADED_OPERATOR_CODE (olddecl); + DECL_OVERLOADED_OPERATOR_CODE_RAW (newdecl) + = DECL_OVERLOADED_OPERATOR_CODE_RAW (olddecl); new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE; /* Optionally warn about more than one declaration for the same @@ -4444,7 +4444,8 @@ build_library_fn (tree name, enum tree_c DECL_EXTERNAL (fn) = 1; TREE_PUBLIC (fn) = 1; DECL_ARTIFICIAL (fn) = 1; - DECL_OVERLOADED_OPERATOR_CODE (fn) = operator_code; + DECL_OVERLOADED_OPERATOR_CODE_RAW (fn) + = OVL_OP_INFO (false, operator_code)->ovl_op_code; SET_DECL_LANGUAGE (fn, lang_c); /* Runtime library routines are, by definition, available in an external shared object. */ @@ -12902,7 +12903,7 @@ grok_op_properties (tree decl, bool comp operator_code = ovl_op->tree_code; op_flags = ovl_op->flags; gcc_checking_assert (operator_code != ERROR_MARK); - DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; + DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) = ovl_op->ovl_op_code; } if (op_flags & OVL_OP_FLAG_ALLOC) @@ -13046,7 +13047,7 @@ grok_op_properties (tree decl, bool comp const ovl_op_info_t *ovl_op = &ovl_op_info[false][alt]; gcc_checking_assert (ovl_op->flags == OVL_OP_FLAG_UNARY); operator_code = ovl_op->tree_code; - DECL_OVERLOADED_OPERATOR_CODE (decl) = operator_code; + DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) = ovl_op->ovl_op_code; } else if (arity != 2) { Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 254311) +++ gcc/cp/mangle.c (working copy) @@ -1321,8 +1321,8 @@ write_unqualified_name (tree decl) else if (DECL_OVERLOADED_OPERATOR_P (decl)) { const char *mangled_name - = (OVL_OP_INFO (DECL_ASSIGNMENT_OPERATOR_P (decl), - DECL_OVERLOADED_OPERATOR_CODE (decl))->mangled_name); + = (ovl_op_info[DECL_ASSIGNMENT_OPERATOR_P (decl)] + [DECL_OVERLOADED_OPERATOR_CODE_RAW (decl)].mangled_name); write_string (mangled_name); } else if (UDLIT_OPER_P (DECL_NAME (decl))) Index: gcc/cp/method.c =================================================================== --- gcc/cp/method.c (revision 254311) +++ gcc/cp/method.c (working copy) @@ -2078,7 +2078,7 @@ implicitly_declare_fn (special_function_ if (!IDENTIFIER_CDTOR_P (name)) /* Assignment operator. */ - DECL_OVERLOADED_OPERATOR_CODE (fn) = NOP_EXPR; + DECL_OVERLOADED_OPERATOR_CODE_RAW (fn) = OVL_OP_NOP_EXPR; else if (IDENTIFIER_CTOR_P (name)) DECL_CXX_CONSTRUCTOR_P (fn) = true; else Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 254311) +++ gcc/cp/typeck.c (working copy) @@ -9074,9 +9074,8 @@ check_return_expr (tree retval, bool *no /* Only operator new(...) throw(), can return NULL [expr.new/13]. */ 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)) + && (DECL_OVERLOADED_OPERATOR_IS (current_function_decl, NEW_EXPR) + || DECL_OVERLOADED_OPERATOR_IS (current_function_decl, VEC_NEW_EXPR)) && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl)) && ! flag_check_new && retval && null_ptr_cst_p (retval)) Index: libcc1/libcp1plugin.cc =================================================================== --- libcc1/libcp1plugin.cc (revision 254311) +++ libcc1/libcp1plugin.cc (working copy) @@ -1412,7 +1412,7 @@ plugin_build_decl (cc1_plugin::connectio DECL_CXX_DESTRUCTOR_P (decl) = 1; else if ((sym_flags & GCC_CP_FLAG_SPECIAL_FUNCTION) && opcode != ERROR_MARK) - DECL_OVERLOADED_OPERATOR_CODE (decl) = opcode; + DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) = ovl_op_mapping[opcode]; } else if (RECORD_OR_UNION_CODE_P (code)) { ^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] overloaded operator fns [8/N] 2017-11-01 14:02 ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell 2017-11-01 15:45 ` Nathan Sidwell @ 2017-11-01 18:29 ` Nathan Sidwell 2017-11-01 20:09 ` Jason Merrill 1 sibling, 1 reply; 10+ messages in thread From: Nathan Sidwell @ 2017-11-01 18:29 UTC (permalink / raw) To: GCC Patches [-- Attachment #1: Type: text/plain, Size: 538 bytes --] This is the last of the overloaded operator reworking. Now we can cheaply go from identifier->overload info, there's no need to specially mark identifiers as new or delete operators themselves. Thus we can reorder the cp_identifier_kind enumeration and leave space in it for udlit operators. This patch does that renumbering, and reserves a value for udlit operators. Those are currently detected by string compare, which isn't the most satisfactory way to do it. But it's a change for another day. nathan -- Nathan Sidwell [-- Attachment #2: op-ident-8.diff --] [-- Type: text/x-patch, Size: 7169 bytes --] 2017-11-01 Nathan Sidwell <nathan@acm.org> * cp-tree.h (enum cp_identifier_kind): Delete cik_newdel_op. Renumber and reserve udlit value. (IDENTIFIER_NEWDEL_OP): Delete. (IDENTIFIER_OVL_OP): New. (IDENTIFIER_ASSIGN_OP): Adjust. (IDENTIFIER_CONV_OP): Adjust. (IDENTIFIER_OVL_OP_INFO): Adjust. (IDENTIFIER_OVL_OP_FLAGS): New. * decl.c (grokdeclarator): Use IDENTIFIER_OVL_OP_FLAGS. * lex.c (get_identifier_kind_name): Adjust. (init_operators): Don't special case new/delete ops. * mangle.c (write_unqualified_id): Use IDENTIFIER_OVL_OP. * pt.c (push_template_decl_real): Use IDENTIFIER_OVL_OP_FLAGS. * typeck.c (check_return_expr): Likewise. Index: cp-tree.h =================================================================== --- cp-tree.h (revision 254314) +++ cp-tree.h (working copy) @@ -996,9 +996,9 @@ enum cp_identifier_kind { cik_dtor = 3, /* Destructor (in-chg, deleting, complete or base). */ cik_simple_op = 4, /* Non-assignment operator name. */ - cik_newdel_op = 5, /* New or delete operator name. */ - cik_assign_op = 6, /* An assignment operator name. */ - cik_conv_op = 7, /* Conversion operator name. */ + cik_assign_op = 5, /* An assignment operator name. */ + cik_conv_op = 6, /* Conversion operator name. */ + cik_reserved_for_udlit = 7, /* Not yet in use */ cik_max }; @@ -1053,24 +1053,22 @@ enum cp_identifier_kind { #define IDENTIFIER_ANY_OP_P(NODE) \ (IDENTIFIER_KIND_BIT_2 (NODE)) -/* True if this identifier is for new or delete operator. Value 5. */ -#define IDENTIFIER_NEWDEL_OP_P(NODE) \ - (IDENTIFIER_KIND_BIT_2 (NODE) \ - & (!IDENTIFIER_KIND_BIT_1 (NODE)) \ - & IDENTIFIER_KIND_BIT_0 (NODE)) +/* True if this identifier is for an overloaded operator. Values 4, 5. */ +#define IDENTIFIER_OVL_OP_P(NODE) \ + (IDENTIFIER_ANY_OP_P (NODE) \ + & (!IDENTIFIER_KIND_BIT_1 (NODE))) -/* True if this identifier is for any assignment. Values 6. */ +/* True if this identifier is for any assignment. Values 5. */ #define IDENTIFIER_ASSIGN_OP_P(NODE) \ - (IDENTIFIER_KIND_BIT_2 (NODE) \ - & IDENTIFIER_KIND_BIT_1 (NODE) \ - & (!IDENTIFIER_KIND_BIT_0 (NODE))) + (IDENTIFIER_OVL_OP_P (NODE) \ + & IDENTIFIER_KIND_BIT_0 (NODE)) /* True if this identifier is the name of a type-conversion operator. Value 7. */ #define IDENTIFIER_CONV_OP_P(NODE) \ - (IDENTIFIER_KIND_BIT_2 (NODE) \ + (IDENTIFIER_ANY_OP_P (NODE) \ & IDENTIFIER_KIND_BIT_1 (NODE) \ - & IDENTIFIER_KIND_BIT_0 (NODE)) + & (!IDENTIFIER_KIND_BIT_0 (NODE))) /* Access a C++-specific index for identifier NODE. Used to optimize operator mappings etc. */ @@ -5529,9 +5527,11 @@ extern GTY(()) unsigned char ovl_op_alte #define OVL_OP_INFO(IS_ASS_P, TREE_CODE) \ (&ovl_op_info[(IS_ASS_P) != 0][ovl_op_mapping[(TREE_CODE)]]) /* Overloaded operator info for an identifier for which - IDENTIFIER_ANY_OP_P is true. */ + IDENTIFIER_OVL_OP_P is true. */ #define IDENTIFIER_OVL_OP_INFO(NODE) \ - (&ovl_op_info[IDENTIFIER_ASSIGN_OP_P (NODE)][IDENTIFIER_CP_INDEX (NODE)]) + (&ovl_op_info[IDENTIFIER_KIND_BIT_0 (NODE)][IDENTIFIER_CP_INDEX (NODE)]) +#define IDENTIFIER_OVL_OP_FLAGS(NODE) \ + (IDENTIFIER_OVL_OP_INFO (NODE)->flags) /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL constants. */ Index: decl.c =================================================================== --- decl.c (revision 254314) +++ decl.c (working copy) @@ -11744,7 +11744,8 @@ grokdeclarator (const cp_declarator *dec if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 && !(identifier_p (unqualified_id) - && IDENTIFIER_NEWDEL_OP_P (unqualified_id))) + && IDENTIFIER_OVL_OP_P (unqualified_id) + && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC))) { cp_cv_quals real_quals = memfn_quals; if (cxx_dialect < cxx14 && constexpr_p @@ -11857,7 +11858,9 @@ grokdeclarator (const cp_declarator *dec if (virtualp && identifier_p (unqualified_id) - && IDENTIFIER_NEWDEL_OP_P (unqualified_id)) + && IDENTIFIER_OVL_OP_P (unqualified_id) + && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) + & OVL_OP_FLAG_ALLOC)) { error ("%qD cannot be declared %<virtual%>, since it " "is always static", unqualified_id); Index: lex.c =================================================================== --- lex.c (revision 254314) +++ lex.c (working copy) @@ -100,7 +100,8 @@ get_identifier_kind_name (tree id) /* Keep in sync with cp_id_kind enumeration. */ static const char *const names[cik_max] = { "normal", "keyword", "constructor", "destructor", - "assign-op", "op-assign-op", "simple-op", "conv-op", }; + "simple-op", "assign-op", "conv-op", "<reserved>udlit-op" + }; unsigned kind = 0; kind |= IDENTIFIER_KIND_BIT_2 (id) << 2; @@ -176,9 +177,7 @@ init_operators (void) else { IDENTIFIER_CP_INDEX (ident) = ix; - set_identifier_kind (ident, - op_ptr->flags & OVL_OP_FLAG_ALLOC - ? cik_newdel_op : cik_simple_op); + set_identifier_kind (ident, cik_simple_op); } } if (op_ptr->tree_code) Index: mangle.c =================================================================== --- mangle.c (revision 254314) +++ mangle.c (working copy) @@ -1263,7 +1263,7 @@ write_unqualified_id (tree identifier) { if (IDENTIFIER_CONV_OP_P (identifier)) write_conversion_operator_name (TREE_TYPE (identifier)); - else if (IDENTIFIER_ANY_OP_P (identifier)) + else if (IDENTIFIER_OVL_OP_P (identifier)) { const ovl_op_info_t *ovl_op = IDENTIFIER_OVL_OP_INFO (identifier); write_string (ovl_op->mangled_name); Index: pt.c =================================================================== --- pt.c (revision 254314) +++ pt.c (working copy) @@ -5329,7 +5329,9 @@ push_template_decl_real (tree decl, bool error ("destructor %qD declared as member template", decl); return error_mark_node; } - if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl)) + if (IDENTIFIER_OVL_OP_P (DECL_NAME (decl)) + && (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (decl)) + & OVL_OP_FLAG_ALLOC) && (!prototype_p (TREE_TYPE (decl)) || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) Index: typeck.c =================================================================== --- typeck.c (revision 254314) +++ typeck.c (working copy) @@ -9073,9 +9073,9 @@ check_return_expr (tree retval, bool *no } /* Only operator new(...) throw(), can return NULL [expr.new/13]. */ - if (DECL_OVERLOADED_OPERATOR_P (current_function_decl) - && (DECL_OVERLOADED_OPERATOR_IS (current_function_decl, NEW_EXPR) - || DECL_OVERLOADED_OPERATOR_IS (current_function_decl, VEC_NEW_EXPR)) + if (IDENTIFIER_OVL_OP_P (DECL_NAME (current_function_decl)) + && ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (current_function_decl)) + & (OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)) == OVL_OP_FLAG_ALLOC) && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl)) && ! flag_check_new && retval && null_ptr_cst_p (retval)) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] overloaded operator fns [8/N] 2017-11-01 18:29 ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell @ 2017-11-01 20:09 ` Jason Merrill 2017-11-02 14:15 ` Nathan Sidwell 0 siblings, 1 reply; 10+ messages in thread From: Jason Merrill @ 2017-11-01 20:09 UTC (permalink / raw) To: Nathan Sidwell; +Cc: GCC Patches On Wed, Nov 1, 2017 at 2:29 PM, Nathan Sidwell <nathan@acm.org> wrote: > This is the last of the overloaded operator reworking. Now we can cheaply > go from identifier->overload info, there's no need to specially mark > identifiers as new or delete operators themselves. Thus we can reorder the > cp_identifier_kind enumeration and leave space in it for udlit operators. > > This patch does that renumbering, and reserves a value for udlit operators. > Those are currently detected by string compare, which isn't the most > satisfactory way to do it. But it's a change for another day. > - && IDENTIFIER_NEWDEL_OP_P (unqualified_id))) > + && IDENTIFIER_OVL_OP_P (unqualified_id) > + && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC))) Why not keep the name IDENTIFIER_NEWDEL_OP_P, which expands to this? Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] overloaded operator fns [8/N] 2017-11-01 20:09 ` Jason Merrill @ 2017-11-02 14:15 ` Nathan Sidwell 0 siblings, 0 replies; 10+ messages in thread From: Nathan Sidwell @ 2017-11-02 14:15 UTC (permalink / raw) To: Jason Merrill; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 534 bytes --] On 11/01/2017 04:08 PM, Jason Merrill wrote: > On Wed, Nov 1, 2017 at 2:29 PM, Nathan Sidwell <nathan@acm.org> wrote: >> - && IDENTIFIER_NEWDEL_OP_P (unqualified_id))) >> + && IDENTIFIER_OVL_OP_P (unqualified_id) >> + && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC))) > > Why not keep the name IDENTIFIER_NEWDEL_OP_P, which expands to this? Hm, I guess that would be better. This patch does that, and introduces IDENTIFIER_NEW_OP_P, for when we just want the new operators. nathan -- Nathan Sidwell [-- Attachment #2: op-newdel.diff --] [-- Type: text/x-patch, Size: 3517 bytes --] 2017-11-02 Nathan Sidwell <nathan@acm.org> * cp-tree.h (IDENTIFIER_NEWDEL_OP_P): Restore, adjust. (IDENTIFIER_NEW_OP_P): New. * decl.c (grokdeclarator): Restore IDENTIFIER_NEWDEL_OP_P use. * pt.c (push_template_decl_real): Likewise. * typeck.c (check_return_expr): Use IDENTIFIER_NEW_OP_P. Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 254344) +++ cp/cp-tree.h (working copy) @@ -1070,6 +1070,17 @@ enum cp_identifier_kind { & IDENTIFIER_KIND_BIT_1 (NODE) \ & (!IDENTIFIER_KIND_BIT_0 (NODE))) +/* True if this identifier is a new or delete operator. */ +#define IDENTIFIER_NEWDEL_OP_P(NODE) \ + (IDENTIFIER_OVL_OP_P (NODE) \ + && IDENTIFIER_OVL_OP_FLAGS (NODE) & OVL_OP_FLAG_ALLOC) + +/* True if this identifier is a new operator. */ +#define IDENTIFIER_NEW_OP_P(NODE) \ + (IDENTIFIER_OVL_OP_P (NODE) \ + && (IDENTIFIER_OVL_OP_FLAGS (NODE) \ + & (OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)) == OVL_OP_FLAG_ALLOC) + /* Access a C++-specific index for identifier NODE. Used to optimize operator mappings etc. */ #define IDENTIFIER_CP_INDEX(NODE) \ Index: cp/decl.c =================================================================== --- cp/decl.c (revision 254344) +++ cp/decl.c (working copy) @@ -11744,8 +11744,7 @@ grokdeclarator (const cp_declarator *dec if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 && !(identifier_p (unqualified_id) - && IDENTIFIER_OVL_OP_P (unqualified_id) - && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) & OVL_OP_FLAG_ALLOC))) + && IDENTIFIER_NEWDEL_OP_P (unqualified_id))) { cp_cv_quals real_quals = memfn_quals; if (cxx_dialect < cxx14 && constexpr_p @@ -11858,9 +11857,7 @@ grokdeclarator (const cp_declarator *dec if (virtualp && identifier_p (unqualified_id) - && IDENTIFIER_OVL_OP_P (unqualified_id) - && (IDENTIFIER_OVL_OP_FLAGS (unqualified_id) - & OVL_OP_FLAG_ALLOC)) + && IDENTIFIER_NEWDEL_OP_P (unqualified_id)) { error ("%qD cannot be declared %<virtual%>, since it " "is always static", unqualified_id); Index: cp/pt.c =================================================================== --- cp/pt.c (revision 254344) +++ cp/pt.c (working copy) @@ -5329,9 +5329,7 @@ push_template_decl_real (tree decl, bool error ("destructor %qD declared as member template", decl); return error_mark_node; } - if (IDENTIFIER_OVL_OP_P (DECL_NAME (decl)) - && (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (decl)) - & OVL_OP_FLAG_ALLOC) + if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl)) && (!prototype_p (TREE_TYPE (decl)) || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 254344) +++ cp/typeck.c (working copy) @@ -9073,9 +9073,7 @@ check_return_expr (tree retval, bool *no } /* Only operator new(...) throw(), can return NULL [expr.new/13]. */ - if (IDENTIFIER_OVL_OP_P (DECL_NAME (current_function_decl)) - && ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (current_function_decl)) - & (OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)) == OVL_OP_FLAG_ALLOC) + if (IDENTIFIER_NEW_OP_P (DECL_NAME (current_function_decl)) && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl)) && ! flag_check_new && retval && null_ptr_cst_p (retval)) ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2017-11-02 14:15 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-10-31 13:12 [C++ PATCH] overloaded operator fns [1/N] Nathan Sidwell 2017-10-31 14:45 ` [C++ PATCH] overloaded operator fns [2/N] Nathan Sidwell 2017-10-31 16:30 ` [C++ PATCH] overloaded operator fns [3/N] Nathan Sidwell 2017-10-31 18:45 ` [C++ PATCH] overloaded operator fns [4/N] Nathan Sidwell 2017-10-31 20:20 ` [C++ PATCH] overloaded operator fns [5/N] Nathan Sidwell 2017-11-01 14:02 ` [C++ PATCH] overloaded operator fns [6/N] Nathan Sidwell 2017-11-01 15:45 ` Nathan Sidwell 2017-11-01 18:29 ` [C++ PATCH] overloaded operator fns [8/N] Nathan Sidwell 2017-11-01 20:09 ` Jason Merrill 2017-11-02 14:15 ` Nathan Sidwell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).