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
This commit is contained in:
Jason Merrill 2018-05-14 16:08:11 -04:00 committed by Jason Merrill
parent dc05c538c9
commit 403f22aae5
10 changed files with 170 additions and 244 deletions

View File

@ -1,3 +1,30 @@
2018-05-14 Jason Merrill <jason@redhat.com>
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 <paolo.carlini@oracle.com>
* cp-tree.h (TYPE_REF_P): New.

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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:;
}

View File

@ -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

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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,47 +2606,66 @@ canonical_eh_spec (tree raises)
return NULL_TREE;
}
tree
build_cp_fntype_variant (tree type, cp_ref_qualifier rqual,
tree raises, bool late)
{
cp_cv_quals type_quals = TYPE_QUALS (type);
if (cp_check_qualified_type (type, type, type_quals, rqual, raises, late))
return type;
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;
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 = 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 || late)
/* Build the underlying canonical type, since it is different
from TYPE. */
TYPE_CANONICAL (v) = build_cp_fntype_variant (TYPE_CANONICAL (type),
rqual, cr, false);
else
/* T is its own canonical type. */
TYPE_CANONICAL (v) = v;
return v;
}
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
tree
build_exception_variant (tree type, tree raises)
{
tree v;
int type_quals;
if (comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (type), ce_exact))
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))
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;
/* Canonicalize the exception specification. */
tree cr = canonical_eh_spec (raises);
if (TYPE_STRUCTURAL_EQUALITY_P (type))
/* Propagate structural equality. */
SET_TYPE_STRUCTURAL_EQUALITY (v);
else if (TYPE_CANONICAL (type) != type || cr != raises)
/* Build the underlying canonical type, since it is different
from TYPE. */
TYPE_CANONICAL (v) = build_exception_variant (TYPE_CANONICAL (type), cr);
else
/* T is its own canonical type. */
TYPE_CANONICAL (v) = v;
return v;
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
@ -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;
}

View File

@ -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;
}