aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
authorBronek Kozicki <b.kozicki@gmail.com>2013-04-01 19:04:59 +0000
committerJason Merrill <jason@gcc.gnu.org>2013-04-01 15:04:59 -0400
commit2eed8e37019cecd79d95b81ecfb6f8605b6361fa (patch)
treeb559fa7f7e6f0e57d15a631da9a9be7802955ac1 /gcc/cp/tree.c
parent5bc08e85f179b65b4e8f4bb70421216805c5c6bf (diff)
downloadgcc-2eed8e37019cecd79d95b81ecfb6f8605b6361fa.zip
gcc-2eed8e37019cecd79d95b81ecfb6f8605b6361fa.tar.gz
gcc-2eed8e37019cecd79d95b81ecfb6f8605b6361fa.tar.bz2
Implement N2439 (ref-qualifiers for 'this')
Implement N2439 (ref-qualifiers for 'this') * cp-tree.h (FUNCTION_REF_QUALIFIED): New. (FUNCTION_RVALUE_QUALIFIED): New. (FUNCTION_OR_METHOD_TYPE_CHECK): New. (cpp0x_warn_str): Add CPP0X_REF_QUALIFIER. (cp_ref_qualifier): New enum. (cp_declarator): Add ref_qualifier. * parser.c (cp_parser_ref_qualifier_seq_opt): New. (cp_parser_direct_declarator): Use it. (make_call_declarator): Adjust. (cp_parser_lambda_declarator_opt): Adjust. * call.c (add_function_candidate): Handle ref-qualifier overload resolution semantics. (standard_conversion): Adjust. * class.c (add_method, same_signature_p): Compare ref-qualifiers. * decl.c (grokdeclarator): Handle ref-qualifiers. (grokfndecl): Check for invalid ref-qualifiers. (static_fn_type, revert_static_member_fn): Adjust. * decl2.c (build_memfn_type): Handle ref-qualifiers. (check_classfn): Check them. (cp_reconstruct_complex_type): Retain them. * error.c (dump_ref_qualifier): New. (dump_type_suffix, dump_function_decl): Use it. (maybe_warn_cpp0x): Handle CPP0X_REF_QUALIFIER. * pt.c (tsubst, tsubst_function_type): Instantiate ref-quals. (unify): Retain them. * tree.c (cp_check_qualified_type): New. (cp_build_qualified_type_real): Keep exception spec and ref-qual. (build_ref_qualified_type): New. (strip_typedefs, build_exception_variant): Keep ref-qualifier. (cp_build_type_attribute_variant): Keep ref-qualifier. * typeck.c (merge_types): Keep ref-qualifier. (structural_comptypes): Compare ref-qualifier. (type_memfn_rqual): New. (apply_memfn_quals): Take ref-qual argument. * typeck2.c (build_m_component_ref): Check ref-qualifier. Co-Authored-By: Jason Merrill <jason@redhat.com> From-SVN: r197315
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r--gcc/cp/tree.c83
1 files changed, 78 insertions, 5 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7fb8698..ce9568c 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1081,6 +1081,15 @@ 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));
+ }
+
/* If this was a pointer-to-method type, and we just made a copy,
then we need to unshare the record that holds the cached
pointer-to-member-function type, because these will be distinct
@@ -1214,7 +1223,9 @@ strip_typedefs (tree t)
{
result = build_function_type (type,
arg_types);
- result = apply_memfn_quals (result, type_memfn_quals (t));
+ result = apply_memfn_quals (result,
+ type_memfn_quals (t),
+ type_memfn_rqual (t));
}
if (TYPE_RAISES_EXCEPTIONS (t))
@@ -1702,6 +1713,64 @@ 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. */
+
+static bool
+cp_check_qualified_type (const_tree cand, const_tree base, int type_quals,
+ cp_ref_qualifier rqual, tree raises)
+{
+ return (check_qualified_type (cand, base, type_quals)
+ && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand),
+ ce_exact)
+ && type_memfn_rqual (cand) == rqual);
+}
+
+/* Build the FUNCTION_TYPE or METHOD_TYPE with the ref-qualifier RQUAL. */
+
+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;
+ /* Intentional fall through */
+ case REF_QUAL_LVALUE:
+ 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;
+}
+
/* Returns nonzero if X is an expression for a (possibly overloaded)
function. If "f" is a function or function template, "f", "c->f",
"c.f", "C::f", and "f<int>" will all be considered possibly
@@ -1907,9 +1976,9 @@ build_exception_variant (tree type, tree raises)
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 (check_qualified_type (v, type, type_quals)
- && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), ce_exact))
+ if (cp_check_qualified_type (v, type, type_quals, rqual, raises))
return v;
/* Need to build a new variant. */
@@ -3308,8 +3377,12 @@ 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_exception_variant (new_type,
+ TYPE_RAISES_EXCEPTIONS (type));
+ new_type = build_ref_qualified_type (new_type,
+ type_memfn_rqual (type));
+ }
/* Making a new main variant of a class type is broken. */
gcc_assert (!CLASS_TYPE_P (type) || new_type == type);