summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2018-05-14 20:08:11 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2018-05-14 20:08:11 +0000
commite51229316f15024ab6f9ed174ffddc67cf7c11c3 (patch)
tree44823e1213f902339f160615a5c9aef85d4f9e09
parentc6c9d80c309d9fa776839c97b44facbcf765e1a8 (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@260238 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog27
-rw-r--r--gcc/cp/class.c33
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c28
-rw-r--r--gcc/cp/decl2.c82
-rw-r--r--gcc/cp/mangle.c6
-rw-r--r--gcc/cp/parser.c10
-rw-r--r--gcc/cp/pt.c17
-rw-r--r--gcc/cp/tree.c145
-rw-r--r--gcc/cp/typeck.c32
10 files changed, 155 insertions, 229 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c4214716d021..27ff8f353b98 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index e51946d3d83e..306ee294d8ab 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 4b4f88212fe9..398f7adc0511 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 59d6badf481e..92639a886a17 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 0a6cf91a82d0..14a3cddacb88 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 58b331174159..387990b76a35 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 a06516b645df..c0058085ee92 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 ddfda2e08ce1..1e4204043bb6 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 b2efab68a8c2..463a06d83707 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 e5eb35d75c6f..ecb334d19d20 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;
}