summaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-01 19:04:59 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-01 19:04:59 +0000
commite116411c3efd8aa1b5ee556b16275c460a143849 (patch)
treeb559fa7f7e6f0e57d15a631da9a9be7802955ac1 /gcc/cp/decl.c
parent1a05e335520ee86c1c59c973f338a1271d1e530c (diff)
downloadgcc-e116411c3efd8aa1b5ee556b16275c460a143849.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@197315 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c88
1 files changed, 64 insertions, 24 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 98d30dd99eb..9e280eac9f7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7319,6 +7319,7 @@ grokfndecl (tree ctype,
int virtualp,
enum overload_flags flags,
cp_cv_quals quals,
+ cp_ref_qualifier rqual,
tree raises,
int check,
int friendp,
@@ -7335,6 +7336,8 @@ grokfndecl (tree ctype,
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
tree t;
+ if (rqual)
+ type = build_ref_qualified_type (type, rqual);
if (raises)
type = build_exception_variant (type, raises);
@@ -7542,13 +7545,25 @@ grokfndecl (tree ctype,
DECL_DECLARED_CONSTEXPR_P (decl) = true;
DECL_EXTERNAL (decl) = 1;
- if (quals && TREE_CODE (type) == FUNCTION_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error (ctype
- ? G_("static member function %qD cannot have cv-qualifier")
- : G_("non-member function %qD cannot have cv-qualifier"),
- decl);
- quals = TYPE_UNQUALIFIED;
+ if (quals)
+ {
+ error (ctype
+ ? G_("static member function %qD cannot have cv-qualifier")
+ : G_("non-member function %qD cannot have cv-qualifier"),
+ decl);
+ quals = TYPE_UNQUALIFIED;
+ }
+
+ if (rqual)
+ {
+ error (ctype
+ ? G_("static member function %qD cannot have ref-qualifier")
+ : G_("non-member function %qD cannot have ref-qualifier"),
+ decl);
+ rqual = REF_QUAL_NONE;
+ }
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))
@@ -7986,7 +8001,8 @@ build_ptrmem_type (tree class_type, tree member_type)
if (TREE_CODE (member_type) == METHOD_TYPE)
{
cp_cv_quals quals = type_memfn_quals (member_type);
- member_type = build_memfn_type (member_type, class_type, quals);
+ cp_ref_qualifier rqual = type_memfn_rqual (member_type);
+ member_type = build_memfn_type (member_type, class_type, quals, rqual);
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
else
@@ -8635,6 +8651,9 @@ grokdeclarator (const cp_declarator *declarator,
/* virt-specifiers that apply to the declarator, for a declaration of
a member function. */
cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
+ /* ref-qualifier that applies to the declarator, for a declaration of
+ a member function. */
+ cp_ref_qualifier rqual = REF_QUAL_NONE;
/* cv-qualifiers that apply to the type specified by the DECLSPECS. */
int type_quals;
tree raises = NULL_TREE;
@@ -9444,6 +9463,8 @@ grokdeclarator (const cp_declarator *declarator,
memfn_quals = declarator->u.function.qualifiers;
/* Pick up virt-specifiers. */
virt_specifiers = declarator->u.function.virt_specifiers;
+ /* And ref-qualifier, too */
+ rqual = declarator->u.function.ref_qualifier;
/* Pick up the exception specifications. */
raises = declarator->u.function.exception_specification;
/* If the exception-specification is ill-formed, let's pretend
@@ -9511,12 +9532,13 @@ grokdeclarator (const cp_declarator *declarator,
therefore returns a void type. */
/* ISO C++ 12.4/2. A destructor may not be declared
- const or volatile. A destructor may not be
- static.
+ const or volatile. A destructor may not be static.
+ A destructor may not be declared with ref-qualifier.
ISO C++ 12.1. A constructor may not be declared
const or volatile. A constructor may not be
- virtual. A constructor may not be static. */
+ virtual. A constructor may not be static.
+ A constructor may not be declared with ref-qualifier. */
if (staticp == 2)
error ((flags == DTOR_FLAG)
? G_("destructor cannot be static member function")
@@ -9529,6 +9551,14 @@ grokdeclarator (const cp_declarator *declarator,
memfn_quals = TYPE_UNQUALIFIED;
}
+ if (rqual)
+ {
+ error ((flags == DTOR_FLAG)
+ ? "destructors may not be ref-qualified"
+ : "constructors may not be ref-qualified");
+ rqual = REF_QUAL_NONE;
+ }
+
if (decl_context == FIELD
&& !member_function_or_else (ctype,
current_class_type,
@@ -9650,14 +9680,18 @@ grokdeclarator (const cp_declarator *declarator,
memfn_quals |= type_memfn_quals (type);
type = build_memfn_type (type,
declarator->u.pointer.class_type,
- memfn_quals);
+ memfn_quals,
+ rqual);
if (type == error_mark_node)
return error_mark_node;
+
+ rqual = REF_QUAL_NONE;
memfn_quals = TYPE_UNQUALIFIED;
}
if (TREE_CODE (type) == FUNCTION_TYPE
- && type_memfn_quals (type) != TYPE_UNQUALIFIED)
+ && (type_memfn_quals (type) != TYPE_UNQUALIFIED
+ || type_memfn_rqual (type) != REF_QUAL_NONE))
error (declarator->kind == cdk_reference
? G_("cannot declare reference to qualified function type %qT")
: G_("cannot declare pointer to qualified function type %qT"),
@@ -10002,12 +10036,13 @@ grokdeclarator (const cp_declarator *declarator,
example "f S::*" declares a pointer to a const-qualified
member function of S. We record the cv-qualification in the
function type. */
- if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
+ if ((rqual || memfn_quals) && TREE_CODE (type) == FUNCTION_TYPE)
{
- type = apply_memfn_quals (type, memfn_quals);
+ type = apply_memfn_quals (type, memfn_quals, rqual);
/* We have now dealt with these qualifiers. */
memfn_quals = TYPE_UNQUALIFIED;
+ rqual = REF_QUAL_NONE;
}
if (type_uses_auto (type))
@@ -10137,8 +10172,10 @@ grokdeclarator (const cp_declarator *declarator,
if (decl_context != TYPENAME)
{
/* A cv-qualifier-seq shall only be part of the function type
- for a non-static member function. [8.3.5/4 dcl.fct] */
- if (type_memfn_quals (type) != TYPE_UNQUALIFIED
+ for a non-static member function. A ref-qualifier shall only
+ .... /same as above/ [dcl.fct] */
+ if ((type_memfn_quals (type) != TYPE_UNQUALIFIED
+ || type_memfn_rqual (type) != REF_QUAL_NONE)
&& (current_class_type == NULL_TREE || staticp) )
{
error (staticp
@@ -10152,6 +10189,7 @@ grokdeclarator (const cp_declarator *declarator,
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
memfn_quals |= type_memfn_quals (type);
+ rqual = type_memfn_rqual (type);
type_quals = TYPE_UNQUALIFIED;
}
}
@@ -10216,10 +10254,10 @@ grokdeclarator (const cp_declarator *declarator,
ctype = TYPE_METHOD_BASETYPE (type);
if (ctype)
- type = build_memfn_type (type, ctype, memfn_quals);
+ type = build_memfn_type (type, ctype, memfn_quals, rqual);
/* Core issue #547: need to allow this in template type args. */
else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
- type = apply_memfn_quals (type, memfn_quals);
+ type = apply_memfn_quals (type, memfn_quals, rqual);
else
error ("invalid qualifiers on non-member function type");
}
@@ -10288,7 +10326,7 @@ grokdeclarator (const cp_declarator *declarator,
cp_cv_quals real_quals = memfn_quals;
if (constexpr_p && sfk != sfk_constructor && sfk != sfk_destructor)
real_quals |= TYPE_QUAL_CONST;
- type = build_memfn_type (type, ctype, real_quals);
+ type = build_memfn_type (type, ctype, real_quals, rqual);
}
{
@@ -10420,7 +10458,7 @@ grokdeclarator (const cp_declarator *declarator,
? unqualified_id : dname,
parms,
unqualified_id,
- virtualp, flags, memfn_quals, raises,
+ virtualp, flags, memfn_quals, rqual, raises,
friendp ? -1 : 0, friendp, publicp,
inlinep | (2 * constexpr_p),
sfk,
@@ -10641,7 +10679,7 @@ grokdeclarator (const cp_declarator *declarator,
|| storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
- virtualp, flags, memfn_quals, raises,
+ virtualp, flags, memfn_quals, rqual, raises,
1, friendp,
publicp, inlinep | (2 * constexpr_p), sfk,
funcdef_flag,
@@ -14216,8 +14254,9 @@ 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));
+ fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype), rqual);
fntype = (cp_build_type_attribute_variant
(fntype, TYPE_ATTRIBUTES (memfntype)));
fntype = (build_exception_variant
@@ -14233,9 +14272,10 @@ revert_static_member_fn (tree decl)
{
tree stype = static_fn_type (decl);
cp_cv_quals quals = type_memfn_quals (stype);
+ cp_ref_qualifier rqual = type_memfn_rqual (stype);
- if (quals != TYPE_UNQUALIFIED)
- stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED);
+ if (quals != TYPE_UNQUALIFIED || rqual != REF_QUAL_NONE)
+ stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED, REF_QUAL_NONE);
TREE_TYPE (decl) = stype;