From 403f22aae5b6e4e8f0e50b89b41a82aaf910931e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 14 May 2018 16:08:11 -0400 Subject: [PATCH] Handle TYPE_HAS_LATE_RETURN_TYPE like ref-qualifier and eh spec. * tree.c (build_cp_fntype_variant): New. (build_ref_qualified_type, build_exception_variant) (strip_typedefs, cxx_copy_lang_qualifiers): Use it. (cxx_type_hash_eq, cp_check_qualified_type): Check TYPE_HAS_LATE_RETURN_TYPE. (cp_build_type_attribute_variant): Check cxx_type_hash_eq. (cp_build_qualified_type_real): No need to preserve C++ qualifiers. * class.c (build_clone): Use cxx_copy_lang_qualifiers. (adjust_clone_args): Likewise. * decl.c (grokfndecl): Add late_return_type_p parameter. Use build_cp_fntype_variant. (grokdeclarator): Pass late_return_type_p to grokfndecl. (check_function_type): Use cxx_copy_lang_qualifiers. (static_fn_type): Use cxx_copy_lang_qualifiers. * decl2.c (build_memfn_type, maybe_retrofit_in_chrg) (cp_reconstruct_complex_type, coerce_new_type, coerce_delete_type) (change_return_type): Use cxx_copy_lang_qualifiers. * mangle.c (write_type): Use cxx_copy_lang_qualifiers. * parser.c (cp_parser_lambda_declarator_opt): Represent an explicit return type on the declarator like a normal trailing return type. * pt.c (tsubst_function_type): Use build_cp_fntype_variant. (copy_default_args_to_explicit_spec): Use cxx_copy_lang_qualifiers. * typeck.c (merge_types): Use build_cp_fntype_variant. From-SVN: r260238 --- gcc/cp/ChangeLog | 27 +++++++++ gcc/cp/class.c | 33 ++++------- gcc/cp/cp-tree.h | 4 +- gcc/cp/decl.c | 28 +++------ gcc/cp/decl2.c | 82 +++++++++------------------ gcc/cp/mangle.c | 6 +- gcc/cp/parser.c | 10 +--- gcc/cp/pt.c | 17 ++---- gcc/cp/tree.c | 145 ++++++++++++++++++----------------------------- gcc/cp/typeck.c | 32 ++++------- 10 files changed, 155 insertions(+), 229 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c4214716d02..27ff8f353b9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,30 @@ +2018-05-14 Jason Merrill + + Handle TYPE_HAS_LATE_RETURN_TYPE like ref-qualifier and eh spec. + * tree.c (build_cp_fntype_variant): New. + (build_ref_qualified_type, build_exception_variant) + (strip_typedefs, cxx_copy_lang_qualifiers): Use it. + (cxx_type_hash_eq, cp_check_qualified_type): Check + TYPE_HAS_LATE_RETURN_TYPE. + (cp_build_type_attribute_variant): Check cxx_type_hash_eq. + (cp_build_qualified_type_real): No need to preserve C++ qualifiers. + * class.c (build_clone): Use cxx_copy_lang_qualifiers. + (adjust_clone_args): Likewise. + * decl.c (grokfndecl): Add late_return_type_p parameter. Use + build_cp_fntype_variant. + (grokdeclarator): Pass late_return_type_p to grokfndecl. + (check_function_type): Use cxx_copy_lang_qualifiers. + (static_fn_type): Use cxx_copy_lang_qualifiers. + * decl2.c (build_memfn_type, maybe_retrofit_in_chrg) + (cp_reconstruct_complex_type, coerce_new_type, coerce_delete_type) + (change_return_type): Use cxx_copy_lang_qualifiers. + * mangle.c (write_type): Use cxx_copy_lang_qualifiers. + * parser.c (cp_parser_lambda_declarator_opt): Represent an explicit + return type on the declarator like a normal trailing return type. + * pt.c (tsubst_function_type): Use build_cp_fntype_variant. + (copy_default_args_to_explicit_spec): Use cxx_copy_lang_qualifiers. + * typeck.c (merge_types): Use build_cp_fntype_variant. + 2018-05-14 Paolo Carlini * cp-tree.h (TYPE_REF_P): New. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index e51946d3d83..306ee294d8a 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4469,13 +4469,8 @@ build_clone (tree fn, tree name) type. */ if (DECL_HAS_IN_CHARGE_PARM_P (clone)) { - tree basetype; - tree parmtypes; - tree exceptions; - - exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone)); - basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); - parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone)); + tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); + tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone)); /* Skip the `this' parameter. */ parmtypes = TREE_CHAIN (parmtypes); /* Skip the in-charge parameter. */ @@ -4494,12 +4489,11 @@ build_clone (tree fn, tree name) = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (clone)), parmtypes); - if (exceptions) - TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), - exceptions); TREE_TYPE (clone) = cp_build_type_attribute_variant (TREE_TYPE (clone), TYPE_ATTRIBUTES (TREE_TYPE (fn))); + TREE_TYPE (clone) + = cxx_copy_lang_qualifiers (TREE_TYPE (clone), TREE_TYPE (fn)); } /* Copy the function parameters. */ @@ -4687,11 +4681,6 @@ adjust_clone_args (tree decl) { /* A default parameter has been added. Adjust the clone's parameters. */ - tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone)); - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (clone)); - tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); - tree type; - clone_parms = orig_decl_parms; if (DECL_HAS_VTT_PARM_P (clone)) @@ -4701,13 +4690,15 @@ adjust_clone_args (tree decl) clone_parms); TREE_TYPE (clone_parms) = TREE_TYPE (orig_clone_parms); } - type = build_method_type_directly (basetype, - TREE_TYPE (TREE_TYPE (clone)), - clone_parms); - if (exceptions) - type = build_exception_variant (type, exceptions); - if (attrs) + + tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); + tree type + = build_method_type_directly (basetype, + TREE_TYPE (TREE_TYPE (clone)), + clone_parms); + if (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (clone))) type = cp_build_type_attribute_variant (type, attrs); + type = cxx_copy_lang_qualifiers (type, TREE_TYPE (clone)); TREE_TYPE (clone) = type; clone_parms = NULL_TREE; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4b4f88212fe..398f7adc051 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7103,6 +7103,7 @@ extern tree ovl_scope (tree); extern const char *cxx_printable_name (tree, int); extern const char *cxx_printable_name_translate (tree, int); extern tree canonical_eh_spec (tree); +extern tree build_cp_fntype_variant (tree, cp_ref_qualifier, tree, bool); extern tree build_exception_variant (tree, tree); extern tree bind_template_template_parm (tree, tree); extern tree array_type_nelts_total (tree); @@ -7262,7 +7263,8 @@ extern tree build_ptrmemfunc (tree, tree, int, bool, extern int cp_type_quals (const_tree); extern int type_memfn_quals (const_tree); extern cp_ref_qualifier type_memfn_rqual (const_tree); -extern tree apply_memfn_quals (tree, cp_cv_quals, cp_ref_qualifier); +extern tree apply_memfn_quals (tree, cp_cv_quals, + cp_ref_qualifier = REF_QUAL_NONE); extern bool cp_has_mutable_p (const_tree); extern bool at_least_as_qualified_p (const_tree, const_tree); extern void cp_apply_type_quals_to_decl (int, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 59d6badf481..92639a886a1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8592,6 +8592,7 @@ grokfndecl (tree ctype, bool deletedp, special_function_kind sfk, bool funcdef_flag, + bool late_return_type_p, int template_count, tree in_namespace, tree* attrlist, @@ -8611,10 +8612,7 @@ grokfndecl (tree ctype, return NULL_TREE; } - if (rqual) - type = build_ref_qualified_type (type, rqual); - if (raises) - type = build_exception_variant (type, raises); + type = build_cp_fntype_variant (type, rqual, raises, late_return_type_p); decl = build_lang_decl (FUNCTION_DECL, declarator, type); @@ -12136,9 +12134,6 @@ grokdeclarator (const cp_declarator *declarator, publicp = (! friendp || ! staticp) && function_context == NULL_TREE; - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (type) = 1; - decl = grokfndecl (ctype, type, TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR ? unqualified_id : dname, @@ -12149,7 +12144,8 @@ grokdeclarator (const cp_declarator *declarator, friendp ? -1 : 0, friendp, publicp, inlinep | (2 * constexpr_p) | (4 * concept_p), initialized == SD_DELETED, sfk, - funcdef_flag, template_count, in_namespace, + funcdef_flag, late_return_type_p, + template_count, in_namespace, attrlist, declarator->id_loc); decl = set_virt_specifiers (decl, virt_specifiers); if (decl == NULL_TREE) @@ -12386,9 +12382,6 @@ grokdeclarator (const cp_declarator *declarator, publicp = (ctype != NULL_TREE || storage_class != sc_static); - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (type) = 1; - decl = grokfndecl (ctype, type, original_name, parms, unqualified_id, reqs, virtualp, flags, memfn_quals, rqual, raises, 1, friendp, @@ -12397,6 +12390,7 @@ grokdeclarator (const cp_declarator *declarator, initialized == SD_DELETED, sfk, funcdef_flag, + late_return_type_p, template_count, in_namespace, attrlist, declarator->id_loc); if (decl == NULL_TREE) @@ -14753,11 +14747,9 @@ check_function_type (tree decl, tree current_function_parms) TREE_CHAIN (args)); else fntype = build_function_type (void_type_node, args); - fntype - = build_exception_variant (fntype, - TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl))); fntype = (cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (TREE_TYPE (decl)))); + fntype = cxx_copy_lang_qualifiers (fntype, TREE_TYPE (decl)); TREE_TYPE (decl) = fntype; } else @@ -16161,15 +16153,11 @@ static_fn_type (tree memfntype) return memfntype; gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE); args = TYPE_ARG_TYPES (memfntype); - cp_ref_qualifier rqual = type_memfn_rqual (memfntype); fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args)); - fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype), rqual); + fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype)); fntype = (cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (memfntype))); - fntype = (build_exception_variant - (fntype, TYPE_RAISES_EXCEPTIONS (memfntype))); - if (TYPE_HAS_LATE_RETURN_TYPE (memfntype)) - TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1; + fntype = cxx_copy_lang_qualifiers (fntype, memfntype); return fntype; } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0a6cf91a82d..14a3cddacb8 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -155,36 +155,27 @@ tree build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals, cp_ref_qualifier rqual) { - tree raises; - tree attrs; - int type_quals; - bool late_return_type_p; - if (fntype == error_mark_node || ctype == error_mark_node) return error_mark_node; gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE || TREE_CODE (fntype) == METHOD_TYPE); - type_quals = quals & ~TYPE_QUAL_RESTRICT; + cp_cv_quals type_quals = quals & ~TYPE_QUAL_RESTRICT; ctype = cp_build_qualified_type (ctype, type_quals); - raises = TYPE_RAISES_EXCEPTIONS (fntype); - attrs = TYPE_ATTRIBUTES (fntype); - late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (fntype); - fntype = build_method_type_directly (ctype, TREE_TYPE (fntype), - (TREE_CODE (fntype) == METHOD_TYPE - ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) - : TYPE_ARG_TYPES (fntype))); - if (attrs) - fntype = cp_build_type_attribute_variant (fntype, attrs); - if (rqual) - fntype = build_ref_qualified_type (fntype, rqual); - if (raises) - fntype = build_exception_variant (fntype, raises); - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1; - - return fntype; + + tree newtype + = build_method_type_directly (ctype, TREE_TYPE (fntype), + (TREE_CODE (fntype) == METHOD_TYPE + ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) + : TYPE_ARG_TYPES (fntype))); + if (tree attrs = TYPE_ATTRIBUTES (fntype)) + newtype = cp_build_type_attribute_variant (newtype, attrs); + newtype = build_cp_fntype_variant (newtype, rqual, + TYPE_RAISES_EXCEPTIONS (fntype), + TYPE_HAS_LATE_RETURN_TYPE (fntype)); + + return newtype; } /* Return a variant of FNTYPE, a FUNCTION_TYPE or METHOD_TYPE, with its @@ -193,36 +184,28 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals, tree change_return_type (tree new_ret, tree fntype) { - tree newtype; - tree args = TYPE_ARG_TYPES (fntype); - tree raises = TYPE_RAISES_EXCEPTIONS (fntype); - tree attrs = TYPE_ATTRIBUTES (fntype); - bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (fntype); - if (new_ret == error_mark_node) return fntype; if (same_type_p (new_ret, TREE_TYPE (fntype))) return fntype; + tree newtype; + tree args = TYPE_ARG_TYPES (fntype); + if (TREE_CODE (fntype) == FUNCTION_TYPE) { newtype = build_function_type (new_ret, args); newtype = apply_memfn_quals (newtype, - type_memfn_quals (fntype), - type_memfn_rqual (fntype)); + type_memfn_quals (fntype)); } else newtype = build_method_type_directly (class_of_this_parm (fntype), new_ret, TREE_CHAIN (args)); - if (FUNCTION_REF_QUALIFIED (fntype)) - newtype = build_ref_qualified_type (newtype, type_memfn_rqual (fntype)); - if (raises) - newtype = build_exception_variant (newtype, raises); - if (attrs) + + if (tree attrs = TYPE_ATTRIBUTES (fntype)) newtype = cp_build_type_attribute_variant (newtype, attrs); - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (newtype) = 1; + newtype = cxx_copy_lang_qualifiers (newtype, fntype); return newtype; } @@ -326,12 +309,10 @@ maybe_retrofit_in_chrg (tree fn) /* And rebuild the function type. */ fntype = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (fn)), arg_types); - if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) - fntype = build_exception_variant (fntype, - TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); if (TYPE_ATTRIBUTES (TREE_TYPE (fn))) fntype = (cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (TREE_TYPE (fn)))); + fntype = cxx_copy_lang_qualifiers (fntype, TREE_TYPE (fn)); TREE_TYPE (fn) = fntype; /* Now we've got the in-charge parameter. */ @@ -1337,7 +1318,6 @@ tree cp_reconstruct_complex_type (tree type, tree bottom) { tree inner, outer; - bool late_return_type_p = false; if (TYPE_PTR_P (type)) { @@ -1363,16 +1343,12 @@ cp_reconstruct_complex_type (tree type, tree bottom) } else if (TREE_CODE (type) == FUNCTION_TYPE) { - late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (type); inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom); outer = build_function_type (inner, TYPE_ARG_TYPES (type)); - outer = apply_memfn_quals (outer, - type_memfn_quals (type), - type_memfn_rqual (type)); + outer = apply_memfn_quals (outer, type_memfn_quals (type)); } else if (TREE_CODE (type) == METHOD_TYPE) { - late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (type); inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom); /* The build_method_type_directly() routine prepends 'this' to argument list, so we must compensate by getting rid of it. */ @@ -1392,9 +1368,7 @@ cp_reconstruct_complex_type (tree type, tree bottom) if (TYPE_ATTRIBUTES (type)) outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (type)); outer = cp_build_qualified_type (outer, cp_type_quals (type)); - - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (outer) = 1; + outer = cxx_copy_lang_qualifiers (outer, type); return outer; } @@ -1748,9 +1722,9 @@ coerce_new_type (tree type) args = tree_cons (NULL_TREE, size_type_node, args); /* Fall through. */ case 1: - type = build_exception_variant + type = (cxx_copy_lang_qualifiers (build_function_type (ptr_type_node, args), - TYPE_RAISES_EXCEPTIONS (type)); + type)); /* Fall through. */ default:; } @@ -1786,9 +1760,9 @@ coerce_delete_type (tree type) args = tree_cons (NULL_TREE, ptr_type_node, args); /* Fall through. */ case 1: - type = build_exception_variant + type = (cxx_copy_lang_qualifiers (build_function_type (void_type_node, args), - TYPE_RAISES_EXCEPTIONS (type)); + type)); /* Fall through. */ default:; } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 58b33117415..387990b76a3 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2155,11 +2155,7 @@ write_type (tree type) type = TYPE_MAIN_VARIANT (type); if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) - { - type = build_ref_qualified_type (type, type_memfn_rqual (type_orig)); - type = build_exception_variant (type, - TYPE_RAISES_EXCEPTIONS (type_orig)); - } + type = cxx_copy_lang_qualifiers (type, type_orig); /* According to the C++ ABI, some library classes are passed the same as the scalar type of their single member and use the same diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a06516b645d..c0058085ee9 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10563,11 +10563,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) void *p; clear_decl_specs (&return_type_specs); - if (return_type) - return_type_specs.type = return_type; - else - /* Maybe we will deduce the return type later. */ - return_type_specs.type = make_auto (); + return_type_specs.type = make_auto (); if (lambda_specs.locations[ds_constexpr]) { @@ -10593,6 +10589,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) /*late_return_type=*/NULL_TREE, /*requires_clause*/NULL_TREE); declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr); + if (return_type) + declarator->u.function.late_return_type = return_type; fco = grokmethod (&return_type_specs, declarator, @@ -10603,8 +10601,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) DECL_ARTIFICIAL (fco) = 1; /* Give the object parameter a different name. */ DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure"); - if (return_type) - TYPE_HAS_LATE_RETURN_TYPE (TREE_TYPE (fco)) = 1; } if (template_param_list) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ddfda2e08ce..1e4204043bb 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2528,11 +2528,7 @@ copy_default_args_to_explicit_spec (tree decl) new_spec_types); new_type = cp_build_type_attribute_variant (new_type, TYPE_ATTRIBUTES (old_type)); - new_type = build_exception_variant (new_type, - TYPE_RAISES_EXCEPTIONS (old_type)); - - if (TYPE_HAS_LATE_RETURN_TYPE (old_type)) - TYPE_HAS_LATE_RETURN_TYPE (new_type) = 1; + new_type = cxx_copy_lang_qualifiers (new_type, old_type); TREE_TYPE (decl) = new_type; } @@ -14020,9 +14016,7 @@ tsubst_function_type (tree t, if (TREE_CODE (t) == FUNCTION_TYPE) { fntype = build_function_type (return_type, arg_types); - fntype = apply_memfn_quals (fntype, - type_memfn_quals (t), - type_memfn_rqual (t)); + fntype = apply_memfn_quals (fntype, type_memfn_quals (t)); } else { @@ -14046,12 +14040,13 @@ tsubst_function_type (tree t, fntype = build_method_type_directly (r, return_type, TREE_CHAIN (arg_types)); - fntype = build_ref_qualified_type (fntype, type_memfn_rqual (t)); } fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t)); - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1; + /* See comment above. */ + tree raises = NULL_TREE; + cp_ref_qualifier rqual = type_memfn_rqual (t); + fntype = build_cp_fntype_variant (fntype, rqual, raises, late_return_type_p); return fntype; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index b2efab68a8c..463a06d8370 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1299,15 +1299,6 @@ cp_build_qualified_type_real (tree type, /* Retrieve (or create) the appropriately qualified variant. */ result = build_qualified_type (type, type_quals); - /* Preserve exception specs and ref-qualifier since build_qualified_type - doesn't know about them. */ - if (TREE_CODE (result) == FUNCTION_TYPE - || TREE_CODE (result) == METHOD_TYPE) - { - result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type)); - result = build_ref_qualified_type (result, type_memfn_rqual (type)); - } - return result; } @@ -1535,22 +1526,16 @@ strip_typedefs (tree t, bool *remove_attributes) result = build_method_type_directly (class_type, type, TREE_CHAIN (arg_types)); - result - = build_ref_qualified_type (result, type_memfn_rqual (t)); } else { - result = build_function_type (type, - arg_types); - result = apply_memfn_quals (result, - type_memfn_quals (t), - type_memfn_rqual (t)); + result = build_function_type (type, arg_types); + result = apply_memfn_quals (result, type_memfn_quals (t)); } - if (canon_spec) - result = build_exception_variant (result, canon_spec); - if (TYPE_HAS_LATE_RETURN_TYPE (t)) - TYPE_HAS_LATE_RETURN_TYPE (result) = 1; + result = build_cp_fntype_variant (result, + type_memfn_rqual (t), canon_spec, + TYPE_HAS_LATE_RETURN_TYPE (t)); } break; case TYPENAME_TYPE: @@ -2093,17 +2078,19 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p) return t; } -/* Like check_qualified_type, but also check ref-qualifier and exception - specification. */ +/* Like check_qualified_type, but also check ref-qualifier, exception + specification, and whether the return type was specified after the + parameters. */ static bool cp_check_qualified_type (const_tree cand, const_tree base, int type_quals, - cp_ref_qualifier rqual, tree raises) + cp_ref_qualifier rqual, tree raises, bool late) { return (TYPE_QUALS (cand) == type_quals && check_base_type (cand, base) && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand), ce_exact) + && TYPE_HAS_LATE_RETURN_TYPE (cand) == late && type_memfn_rqual (cand) == rqual); } @@ -2112,46 +2099,9 @@ cp_check_qualified_type (const_tree cand, const_tree base, int type_quals, tree build_ref_qualified_type (tree type, cp_ref_qualifier rqual) { - tree t; - - if (rqual == type_memfn_rqual (type)) - return type; - - int type_quals = TYPE_QUALS (type); tree raises = TYPE_RAISES_EXCEPTIONS (type); - for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) - if (cp_check_qualified_type (t, type, type_quals, rqual, raises)) - return t; - - t = build_variant_type_copy (type); - switch (rqual) - { - case REF_QUAL_RVALUE: - FUNCTION_RVALUE_QUALIFIED (t) = 1; - FUNCTION_REF_QUALIFIED (t) = 1; - break; - case REF_QUAL_LVALUE: - FUNCTION_RVALUE_QUALIFIED (t) = 0; - FUNCTION_REF_QUALIFIED (t) = 1; - break; - default: - FUNCTION_REF_QUALIFIED (t) = 0; - break; - } - - if (TYPE_STRUCTURAL_EQUALITY_P (type)) - /* Propagate structural equality. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); - else if (TYPE_CANONICAL (type) != type) - /* Build the underlying canonical type, since it is different - from TYPE. */ - TYPE_CANONICAL (t) = build_ref_qualified_type (TYPE_CANONICAL (type), - rqual); - else - /* T is its own canonical type. */ - TYPE_CANONICAL (t) = t; - - return t; + bool late = TYPE_HAS_LATE_RETURN_TYPE (type); + return build_cp_fntype_variant (type, rqual, raises, late); } /* Cache of free ovl nodes. Uses OVL_FUNCTION for chaining. */ @@ -2656,42 +2606,50 @@ canonical_eh_spec (tree raises) return NULL_TREE; } -/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions - listed in RAISES. */ - tree -build_exception_variant (tree type, tree raises) +build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, + tree raises, bool late) { - tree v; - int type_quals; + cp_cv_quals type_quals = TYPE_QUALS (type); - if (comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (type), ce_exact)) + if (cp_check_qualified_type (type, type, type_quals, rqual, raises, late)) return type; - type_quals = TYPE_QUALS (type); - cp_ref_qualifier rqual = type_memfn_rqual (type); - for (v = TYPE_MAIN_VARIANT (type); v; v = TYPE_NEXT_VARIANT (v)) - if (cp_check_qualified_type (v, type, type_quals, rqual, raises)) + tree v = TYPE_MAIN_VARIANT (type); + for (; v; v = TYPE_NEXT_VARIANT (v)) + if (cp_check_qualified_type (v, type, type_quals, rqual, raises, late)) return v; /* Need to build a new variant. */ v = build_variant_type_copy (type); TYPE_RAISES_EXCEPTIONS (v) = raises; - - if (!flag_noexcept_type) - /* The exception-specification is not part of the canonical type. */ - return v; + TYPE_HAS_LATE_RETURN_TYPE (v) = late; + switch (rqual) + { + case REF_QUAL_RVALUE: + FUNCTION_RVALUE_QUALIFIED (v) = 1; + FUNCTION_REF_QUALIFIED (v) = 1; + break; + case REF_QUAL_LVALUE: + FUNCTION_RVALUE_QUALIFIED (v) = 0; + FUNCTION_REF_QUALIFIED (v) = 1; + break; + default: + FUNCTION_REF_QUALIFIED (v) = 0; + break; + } /* Canonicalize the exception specification. */ - tree cr = canonical_eh_spec (raises); + tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE; if (TYPE_STRUCTURAL_EQUALITY_P (type)) /* Propagate structural equality. */ SET_TYPE_STRUCTURAL_EQUALITY (v); - else if (TYPE_CANONICAL (type) != type || cr != raises) + else if (TYPE_CANONICAL (type) != type || cr != raises || late) /* Build the underlying canonical type, since it is different from TYPE. */ - TYPE_CANONICAL (v) = build_exception_variant (TYPE_CANONICAL (type), cr); + TYPE_CANONICAL (v) = build_cp_fntype_variant (TYPE_CANONICAL (type), + rqual, cr, false); else /* T is its own canonical type. */ TYPE_CANONICAL (v) = v; @@ -2699,6 +2657,17 @@ build_exception_variant (tree type, tree raises) return v; } +/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions + listed in RAISES. */ + +tree +build_exception_variant (tree type, tree raises) +{ + cp_ref_qualifier rqual = type_memfn_rqual (type); + bool late = TYPE_HAS_LATE_RETURN_TYPE (type); + return build_cp_fntype_variant (type, rqual, raises, late); +} + /* Given a TEMPLATE_TEMPLATE_PARM node T, create a new BOUND_TEMPLATE_TEMPLATE_PARM bound with NEWARGS as its template arguments. */ @@ -4736,12 +4705,7 @@ cp_build_type_attribute_variant (tree type, tree attributes) new_type = build_type_attribute_variant (type, attributes); if (TREE_CODE (new_type) == FUNCTION_TYPE || TREE_CODE (new_type) == METHOD_TYPE) - { - new_type = build_exception_variant (new_type, - TYPE_RAISES_EXCEPTIONS (type)); - new_type = build_ref_qualified_type (new_type, - type_memfn_rqual (type)); - } + gcc_checking_assert (cxx_type_hash_eq (type, new_type)); /* Making a new main variant of a class type is broken. */ gcc_assert (!CLASS_TYPE_P (type) || new_type == type); @@ -4760,6 +4724,8 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb) if (type_memfn_rqual (typea) != type_memfn_rqual (typeb)) return false; + if (TYPE_HAS_LATE_RETURN_TYPE (typea) != TYPE_HAS_LATE_RETURN_TYPE (typeb)) + return false; return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea), TYPE_RAISES_EXCEPTIONS (typeb), ce_exact); } @@ -4772,10 +4738,9 @@ cxx_copy_lang_qualifiers (const_tree typea, const_tree typeb) { tree type = CONST_CAST_TREE (typea); if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) - { - type = build_exception_variant (type, TYPE_RAISES_EXCEPTIONS (typeb)); - type = build_ref_qualified_type (type, type_memfn_rqual (typeb)); - } + type = build_cp_fntype_variant (type, type_memfn_rqual (typeb), + TYPE_RAISES_EXCEPTIONS (typeb), + TYPE_HAS_LATE_RETURN_TYPE (typeb)); return type; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e5eb35d75c6..ecb334d19d2 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -830,8 +830,6 @@ merge_types (tree t1, tree t2) tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); tree parms; - tree rval, raises; - bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t1); /* Save space: see if the result is identical to one of the args. */ if (valtype == TREE_TYPE (t1) && ! p2) @@ -847,17 +845,17 @@ merge_types (tree t1, tree t2) else parms = commonparms (p1, p2); - rval = build_function_type (valtype, parms); - gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2)); - gcc_assert (type_memfn_rqual (t1) == type_memfn_rqual (t2)); - rval = apply_memfn_quals (rval, - type_memfn_quals (t1), - type_memfn_rqual (t1)); - raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), - TYPE_RAISES_EXCEPTIONS (t2)); - t1 = build_exception_variant (rval, raises); - if (late_return_type_p) - TYPE_HAS_LATE_RETURN_TYPE (t1) = 1; + cp_cv_quals quals = type_memfn_quals (t1); + cp_ref_qualifier rqual = type_memfn_rqual (t1); + gcc_assert (quals == type_memfn_quals (t2)); + gcc_assert (rqual == type_memfn_rqual (t2)); + + tree rval = build_function_type (valtype, parms); + rval = apply_memfn_quals (rval, quals); + tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), + TYPE_RAISES_EXCEPTIONS (t2)); + bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t1); + t1 = build_cp_fntype_variant (rval, rqual, raises, late_return_type_p); break; } @@ -871,7 +869,6 @@ merge_types (tree t1, tree t2) cp_ref_qualifier rqual = type_memfn_rqual (t1); tree t3; bool late_return_type_1_p = TYPE_HAS_LATE_RETURN_TYPE (t1); - bool late_return_type_2_p = TYPE_HAS_LATE_RETURN_TYPE (t2); /* If this was a member function type, get back to the original type of type member function (i.e., without @@ -883,12 +880,7 @@ merge_types (tree t1, tree t2) t3 = merge_types (t1, t2); t3 = build_method_type_directly (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3)); - t1 = build_exception_variant (t3, raises); - t1 = build_ref_qualified_type (t1, rqual); - if (late_return_type_1_p) - TYPE_HAS_LATE_RETURN_TYPE (t1) = 1; - if (late_return_type_2_p) - TYPE_HAS_LATE_RETURN_TYPE (t2) = 1; + t1 = build_cp_fntype_variant (t3, rqual, raises, late_return_type_1_p); break; } -- 2.30.2