diff options
author | Bronek Kozicki <b.kozicki@gmail.com> | 2013-04-01 19:04:59 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-04-01 15:04:59 -0400 |
commit | 2eed8e37019cecd79d95b81ecfb6f8605b6361fa (patch) | |
tree | b559fa7f7e6f0e57d15a631da9a9be7802955ac1 /gcc/cp/tree.c | |
parent | 5bc08e85f179b65b4e8f4bb70421216805c5c6bf (diff) | |
download | gcc-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.c | 83 |
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); |