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
This commit is contained in:
parent
5bc08e85f1
commit
2eed8e3701
|
@ -1,3 +1,43 @@
|
||||||
|
2013-04-01 Bronek Kozicki <b.kozicki@gmail.com>
|
||||||
|
Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
2013-04-01 Paolo Carlini <paolo.carlini@oracle.com>
|
2013-04-01 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
* cp-tree.h (DECL_UNBOUND_CLASS_TEMPLATE_P): Remove.
|
* cp-tree.h (DECL_UNBOUND_CLASS_TEMPLATE_P): Remove.
|
||||||
|
|
|
@ -1276,7 +1276,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
||||||
static_fn_type (tofn)))
|
static_fn_type (tofn)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
from = build_memfn_type (fromfn, tbase, cp_type_quals (tbase));
|
from = build_memfn_type (fromfn,
|
||||||
|
tbase,
|
||||||
|
cp_type_quals (tbase),
|
||||||
|
type_memfn_rqual (tofn));
|
||||||
from = build_ptrmemfunc_type (build_pointer_type (from));
|
from = build_ptrmemfunc_type (build_pointer_type (from));
|
||||||
conv = build_conv (ck_pmem, from, conv);
|
conv = build_conv (ck_pmem, from, conv);
|
||||||
conv->base_p = true;
|
conv->base_p = true;
|
||||||
|
@ -1950,7 +1953,17 @@ add_function_candidate (struct z_candidate **candidates,
|
||||||
{
|
{
|
||||||
parmtype = cp_build_qualified_type
|
parmtype = cp_build_qualified_type
|
||||||
(ctype, cp_type_quals (TREE_TYPE (parmtype)));
|
(ctype, cp_type_quals (TREE_TYPE (parmtype)));
|
||||||
parmtype = build_pointer_type (parmtype);
|
if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn)))
|
||||||
|
{
|
||||||
|
/* If the function has a ref-qualifier, the implicit
|
||||||
|
object parameter has reference type. */
|
||||||
|
bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn));
|
||||||
|
parmtype = cp_build_reference_type (parmtype, rv);
|
||||||
|
arg = build_fold_indirect_ref (arg);
|
||||||
|
argtype = lvalue_type (arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
parmtype = build_pointer_type (parmtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Core issue 899: When [copy-]initializing a temporary to be bound
|
/* Core issue 899: When [copy-]initializing a temporary to be bound
|
||||||
|
|
|
@ -1045,6 +1045,12 @@ add_method (tree type, tree method, tree using_decl)
|
||||||
overloaded if any of them is a static member
|
overloaded if any of them is a static member
|
||||||
function declaration.
|
function declaration.
|
||||||
|
|
||||||
|
[over.load] Member function declarations with the same name and
|
||||||
|
the same parameter-type-list as well as member function template
|
||||||
|
declarations with the same name, the same parameter-type-list, and
|
||||||
|
the same template parameter lists cannot be overloaded if any of
|
||||||
|
them, but not all, have a ref-qualifier.
|
||||||
|
|
||||||
[namespace.udecl] When a using-declaration brings names
|
[namespace.udecl] When a using-declaration brings names
|
||||||
from a base class into a derived class scope, member
|
from a base class into a derived class scope, member
|
||||||
functions in the derived class override and/or hide member
|
functions in the derived class override and/or hide member
|
||||||
|
@ -1060,11 +1066,13 @@ add_method (tree type, tree method, tree using_decl)
|
||||||
coming from the using class in overload resolution. */
|
coming from the using class in overload resolution. */
|
||||||
if (! DECL_STATIC_FUNCTION_P (fn)
|
if (! DECL_STATIC_FUNCTION_P (fn)
|
||||||
&& ! DECL_STATIC_FUNCTION_P (method)
|
&& ! DECL_STATIC_FUNCTION_P (method)
|
||||||
&& TREE_TYPE (TREE_VALUE (parms1)) != error_mark_node
|
/* Either both or neither need to be ref-qualified for
|
||||||
&& TREE_TYPE (TREE_VALUE (parms2)) != error_mark_node
|
differing quals to allow overloading. */
|
||||||
&& (cp_type_quals (TREE_TYPE (TREE_VALUE (parms1)))
|
&& (FUNCTION_REF_QUALIFIED (fn_type)
|
||||||
!= cp_type_quals (TREE_TYPE (TREE_VALUE (parms2)))))
|
== FUNCTION_REF_QUALIFIED (method_type))
|
||||||
continue;
|
&& (type_memfn_quals (fn_type) != type_memfn_quals (method_type)
|
||||||
|
|| type_memfn_rqual (fn_type) != type_memfn_rqual (method_type)))
|
||||||
|
continue;
|
||||||
|
|
||||||
/* For templates, the return type and template parameters
|
/* For templates, the return type and template parameters
|
||||||
must be identical. */
|
must be identical. */
|
||||||
|
@ -2063,6 +2071,8 @@ same_signature_p (const_tree fndecl, const_tree base_fndecl)
|
||||||
base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
|
base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
|
||||||
if ((cp_type_quals (TREE_TYPE (TREE_VALUE (base_types)))
|
if ((cp_type_quals (TREE_TYPE (TREE_VALUE (base_types)))
|
||||||
== cp_type_quals (TREE_TYPE (TREE_VALUE (types))))
|
== cp_type_quals (TREE_TYPE (TREE_VALUE (types))))
|
||||||
|
&& (type_memfn_rqual (TREE_TYPE (fndecl))
|
||||||
|
== type_memfn_rqual (TREE_TYPE (base_fndecl)))
|
||||||
&& compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
|
&& compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,10 @@ c-common.h, not after.
|
||||||
or FIELD_DECL).
|
or FIELD_DECL).
|
||||||
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
|
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
|
||||||
DECL_TINFO_P (in VAR_DECL)
|
DECL_TINFO_P (in VAR_DECL)
|
||||||
|
FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
|
||||||
5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
|
5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
|
||||||
DECL_VTABLE_OR_VTT_P (in VAR_DECL)
|
DECL_VTABLE_OR_VTT_P (in VAR_DECL)
|
||||||
|
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
|
||||||
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
|
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
|
||||||
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
|
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
|
||||||
TYPE_MARKED_P (in _TYPE)
|
TYPE_MARKED_P (in _TYPE)
|
||||||
|
@ -221,6 +223,9 @@ c-common.h, not after.
|
||||||
#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
|
#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
|
||||||
TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
|
TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
|
||||||
|
|
||||||
|
#define FUNCTION_OR_METHOD_TYPE_CHECK(NODE) \
|
||||||
|
TREE_CHECK2(NODE,FUNCTION_TYPE,METHOD_TYPE)
|
||||||
|
|
||||||
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
|
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
|
||||||
#define THUNK_FUNCTION_CHECK(NODE) __extension__ \
|
#define THUNK_FUNCTION_CHECK(NODE) __extension__ \
|
||||||
({ __typeof (NODE) const __t = (NODE); \
|
({ __typeof (NODE) const __t = (NODE); \
|
||||||
|
@ -431,9 +436,11 @@ typedef enum cpp0x_warn_str
|
||||||
/* inheriting constructors */
|
/* inheriting constructors */
|
||||||
CPP0X_INHERITING_CTORS,
|
CPP0X_INHERITING_CTORS,
|
||||||
/* C++11 attributes */
|
/* C++11 attributes */
|
||||||
CPP0X_ATTRIBUTES
|
CPP0X_ATTRIBUTES,
|
||||||
|
/* ref-qualified member functions */
|
||||||
|
CPP0X_REF_QUALIFIER
|
||||||
} cpp0x_warn_str;
|
} cpp0x_warn_str;
|
||||||
|
|
||||||
/* The various kinds of operation used by composite_pointer_type. */
|
/* The various kinds of operation used by composite_pointer_type. */
|
||||||
|
|
||||||
typedef enum composite_pointer_operation
|
typedef enum composite_pointer_operation
|
||||||
|
@ -2527,6 +2534,14 @@ struct GTY((variable_size)) lang_decl {
|
||||||
/* 1 iff VAR_DECL node NODE is virtual table or VTT. */
|
/* 1 iff VAR_DECL node NODE is virtual table or VTT. */
|
||||||
#define DECL_VTABLE_OR_VTT_P(NODE) TREE_LANG_FLAG_5 (VAR_DECL_CHECK (NODE))
|
#define DECL_VTABLE_OR_VTT_P(NODE) TREE_LANG_FLAG_5 (VAR_DECL_CHECK (NODE))
|
||||||
|
|
||||||
|
/* 1 iff FUNCTION_TYPE or METHOD_TYPE has a ref-qualifier (either & or &&). */
|
||||||
|
#define FUNCTION_REF_QUALIFIED(NODE) \
|
||||||
|
TREE_LANG_FLAG_4 (FUNCTION_OR_METHOD_TYPE_CHECK (NODE))
|
||||||
|
|
||||||
|
/* 1 iff FUNCTION_TYPE or METHOD_TYPE has &&-ref-qualifier. */
|
||||||
|
#define FUNCTION_RVALUE_QUALIFIED(NODE) \
|
||||||
|
TREE_LANG_FLAG_5 (FUNCTION_OR_METHOD_TYPE_CHECK (NODE))
|
||||||
|
|
||||||
/* Returns 1 iff VAR_DECL is a construction virtual table.
|
/* Returns 1 iff VAR_DECL is a construction virtual table.
|
||||||
DECL_VTABLE_OR_VTT_P will be true in this case and must be checked
|
DECL_VTABLE_OR_VTT_P will be true in this case and must be checked
|
||||||
before using this macro. */
|
before using this macro. */
|
||||||
|
@ -4691,6 +4706,23 @@ enum virt_specifier
|
||||||
|
|
||||||
typedef int cp_virt_specifiers;
|
typedef int cp_virt_specifiers;
|
||||||
|
|
||||||
|
/* Wherever there is a function-cv-qual, there could also be a ref-qualifier:
|
||||||
|
|
||||||
|
[dcl.fct]
|
||||||
|
The return type, the parameter-type-list, the ref-qualifier, and
|
||||||
|
the cv-qualifier-seq, but not the default arguments or the exception
|
||||||
|
specification, are part of the function type.
|
||||||
|
|
||||||
|
REF_QUAL_NONE Ordinary member function with no ref-qualifier
|
||||||
|
REF_QUAL_LVALUE Member function with the &-ref-qualifier
|
||||||
|
REF_QUAL_RVALUE Member function with the &&-ref-qualifier */
|
||||||
|
|
||||||
|
enum cp_ref_qualifier {
|
||||||
|
REF_QUAL_NONE = 0,
|
||||||
|
REF_QUAL_LVALUE = 1,
|
||||||
|
REF_QUAL_RVALUE = 2
|
||||||
|
};
|
||||||
|
|
||||||
/* A storage class. */
|
/* A storage class. */
|
||||||
|
|
||||||
typedef enum cp_storage_class {
|
typedef enum cp_storage_class {
|
||||||
|
@ -4852,6 +4884,8 @@ struct cp_declarator {
|
||||||
cp_cv_quals qualifiers;
|
cp_cv_quals qualifiers;
|
||||||
/* The virt-specifiers for the function. */
|
/* The virt-specifiers for the function. */
|
||||||
cp_virt_specifiers virt_specifiers;
|
cp_virt_specifiers virt_specifiers;
|
||||||
|
/* The ref-qualifier for the function. */
|
||||||
|
cp_ref_qualifier ref_qualifier;
|
||||||
/* The exception-specification for the function. */
|
/* The exception-specification for the function. */
|
||||||
tree exception_specification;
|
tree exception_specification;
|
||||||
/* The late-specified return type, if any. */
|
/* The late-specified return type, if any. */
|
||||||
|
@ -5202,7 +5236,8 @@ extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t);
|
||||||
|
|
||||||
/* in decl2.c */
|
/* in decl2.c */
|
||||||
extern bool check_java_method (tree);
|
extern bool check_java_method (tree);
|
||||||
extern tree build_memfn_type (tree, tree, cp_cv_quals);
|
extern tree build_memfn_type (tree, tree, cp_cv_quals, cp_ref_qualifier);
|
||||||
|
extern tree build_pointer_ptrmemfn_type (tree);
|
||||||
extern tree change_return_type (tree, tree);
|
extern tree change_return_type (tree, tree);
|
||||||
extern void maybe_retrofit_in_chrg (tree);
|
extern void maybe_retrofit_in_chrg (tree);
|
||||||
extern void maybe_make_one_only (tree);
|
extern void maybe_make_one_only (tree);
|
||||||
|
@ -5809,6 +5844,7 @@ extern void diagnose_non_constexpr_vec_init (tree);
|
||||||
extern tree hash_tree_cons (tree, tree, tree);
|
extern tree hash_tree_cons (tree, tree, tree);
|
||||||
extern tree hash_tree_chain (tree, tree);
|
extern tree hash_tree_chain (tree, tree);
|
||||||
extern tree build_qualified_name (tree, tree, tree, bool);
|
extern tree build_qualified_name (tree, tree, tree, bool);
|
||||||
|
extern tree build_ref_qualified_type (tree, cp_ref_qualifier);
|
||||||
extern int is_overloaded_fn (tree);
|
extern int is_overloaded_fn (tree);
|
||||||
extern tree dependent_name (tree);
|
extern tree dependent_name (tree);
|
||||||
extern tree get_fns (tree);
|
extern tree get_fns (tree);
|
||||||
|
@ -5966,7 +6002,8 @@ extern tree build_ptrmemfunc (tree, tree, int, bool,
|
||||||
tsubst_flags_t);
|
tsubst_flags_t);
|
||||||
extern int cp_type_quals (const_tree);
|
extern int cp_type_quals (const_tree);
|
||||||
extern int type_memfn_quals (const_tree);
|
extern int type_memfn_quals (const_tree);
|
||||||
extern tree apply_memfn_quals (tree, cp_cv_quals);
|
extern cp_ref_qualifier type_memfn_rqual (const_tree);
|
||||||
|
extern tree apply_memfn_quals (tree, cp_cv_quals, cp_ref_qualifier);
|
||||||
extern bool cp_has_mutable_p (const_tree);
|
extern bool cp_has_mutable_p (const_tree);
|
||||||
extern bool at_least_as_qualified_p (const_tree, const_tree);
|
extern bool at_least_as_qualified_p (const_tree, const_tree);
|
||||||
extern void cp_apply_type_quals_to_decl (int, tree);
|
extern void cp_apply_type_quals_to_decl (int, tree);
|
||||||
|
|
|
@ -7319,6 +7319,7 @@ grokfndecl (tree ctype,
|
||||||
int virtualp,
|
int virtualp,
|
||||||
enum overload_flags flags,
|
enum overload_flags flags,
|
||||||
cp_cv_quals quals,
|
cp_cv_quals quals,
|
||||||
|
cp_ref_qualifier rqual,
|
||||||
tree raises,
|
tree raises,
|
||||||
int check,
|
int check,
|
||||||
int friendp,
|
int friendp,
|
||||||
|
@ -7335,6 +7336,8 @@ grokfndecl (tree ctype,
|
||||||
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
|
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
|
||||||
tree t;
|
tree t;
|
||||||
|
|
||||||
|
if (rqual)
|
||||||
|
type = build_ref_qualified_type (type, rqual);
|
||||||
if (raises)
|
if (raises)
|
||||||
type = build_exception_variant (type, raises);
|
type = build_exception_variant (type, raises);
|
||||||
|
|
||||||
|
@ -7542,13 +7545,25 @@ grokfndecl (tree ctype,
|
||||||
DECL_DECLARED_CONSTEXPR_P (decl) = true;
|
DECL_DECLARED_CONSTEXPR_P (decl) = true;
|
||||||
|
|
||||||
DECL_EXTERNAL (decl) = 1;
|
DECL_EXTERNAL (decl) = 1;
|
||||||
if (quals && TREE_CODE (type) == FUNCTION_TYPE)
|
if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||||
{
|
{
|
||||||
error (ctype
|
if (quals)
|
||||||
? G_("static member function %qD cannot have cv-qualifier")
|
{
|
||||||
: G_("non-member function %qD cannot have cv-qualifier"),
|
error (ctype
|
||||||
decl);
|
? G_("static member function %qD cannot have cv-qualifier")
|
||||||
quals = TYPE_UNQUALIFIED;
|
: 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))
|
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)
|
if (TREE_CODE (member_type) == METHOD_TYPE)
|
||||||
{
|
{
|
||||||
cp_cv_quals quals = type_memfn_quals (member_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));
|
return build_ptrmemfunc_type (build_pointer_type (member_type));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8635,6 +8651,9 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
/* virt-specifiers that apply to the declarator, for a declaration of
|
/* virt-specifiers that apply to the declarator, for a declaration of
|
||||||
a member function. */
|
a member function. */
|
||||||
cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
|
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. */
|
/* cv-qualifiers that apply to the type specified by the DECLSPECS. */
|
||||||
int type_quals;
|
int type_quals;
|
||||||
tree raises = NULL_TREE;
|
tree raises = NULL_TREE;
|
||||||
|
@ -9444,6 +9463,8 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
memfn_quals = declarator->u.function.qualifiers;
|
memfn_quals = declarator->u.function.qualifiers;
|
||||||
/* Pick up virt-specifiers. */
|
/* Pick up virt-specifiers. */
|
||||||
virt_specifiers = declarator->u.function.virt_specifiers;
|
virt_specifiers = declarator->u.function.virt_specifiers;
|
||||||
|
/* And ref-qualifier, too */
|
||||||
|
rqual = declarator->u.function.ref_qualifier;
|
||||||
/* Pick up the exception specifications. */
|
/* Pick up the exception specifications. */
|
||||||
raises = declarator->u.function.exception_specification;
|
raises = declarator->u.function.exception_specification;
|
||||||
/* If the exception-specification is ill-formed, let's pretend
|
/* If the exception-specification is ill-formed, let's pretend
|
||||||
|
@ -9511,12 +9532,13 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
therefore returns a void type. */
|
therefore returns a void type. */
|
||||||
|
|
||||||
/* ISO C++ 12.4/2. A destructor may not be declared
|
/* ISO C++ 12.4/2. A destructor may not be declared
|
||||||
const or volatile. A destructor may not be
|
const or volatile. A destructor may not be static.
|
||||||
static.
|
A destructor may not be declared with ref-qualifier.
|
||||||
|
|
||||||
ISO C++ 12.1. A constructor may not be declared
|
ISO C++ 12.1. A constructor may not be declared
|
||||||
const or volatile. A constructor may not be
|
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)
|
if (staticp == 2)
|
||||||
error ((flags == DTOR_FLAG)
|
error ((flags == DTOR_FLAG)
|
||||||
? G_("destructor cannot be static member function")
|
? G_("destructor cannot be static member function")
|
||||||
|
@ -9529,6 +9551,14 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
memfn_quals = TYPE_UNQUALIFIED;
|
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
|
if (decl_context == FIELD
|
||||||
&& !member_function_or_else (ctype,
|
&& !member_function_or_else (ctype,
|
||||||
current_class_type,
|
current_class_type,
|
||||||
|
@ -9650,14 +9680,18 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
memfn_quals |= type_memfn_quals (type);
|
memfn_quals |= type_memfn_quals (type);
|
||||||
type = build_memfn_type (type,
|
type = build_memfn_type (type,
|
||||||
declarator->u.pointer.class_type,
|
declarator->u.pointer.class_type,
|
||||||
memfn_quals);
|
memfn_quals,
|
||||||
|
rqual);
|
||||||
if (type == error_mark_node)
|
if (type == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
|
rqual = REF_QUAL_NONE;
|
||||||
memfn_quals = TYPE_UNQUALIFIED;
|
memfn_quals = TYPE_UNQUALIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (type) == FUNCTION_TYPE
|
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
|
error (declarator->kind == cdk_reference
|
||||||
? G_("cannot declare reference to qualified function type %qT")
|
? G_("cannot declare reference to qualified function type %qT")
|
||||||
: G_("cannot declare pointer 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
|
example "f S::*" declares a pointer to a const-qualified
|
||||||
member function of S. We record the cv-qualification in the
|
member function of S. We record the cv-qualification in the
|
||||||
function type. */
|
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. */
|
/* We have now dealt with these qualifiers. */
|
||||||
memfn_quals = TYPE_UNQUALIFIED;
|
memfn_quals = TYPE_UNQUALIFIED;
|
||||||
|
rqual = REF_QUAL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_uses_auto (type))
|
if (type_uses_auto (type))
|
||||||
|
@ -10137,8 +10172,10 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
if (decl_context != TYPENAME)
|
if (decl_context != TYPENAME)
|
||||||
{
|
{
|
||||||
/* A cv-qualifier-seq shall only be part of the function type
|
/* A cv-qualifier-seq shall only be part of the function type
|
||||||
for a non-static member function. [8.3.5/4 dcl.fct] */
|
for a non-static member function. A ref-qualifier shall only
|
||||||
if (type_memfn_quals (type) != TYPE_UNQUALIFIED
|
.... /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) )
|
&& (current_class_type == NULL_TREE || staticp) )
|
||||||
{
|
{
|
||||||
error (staticp
|
error (staticp
|
||||||
|
@ -10152,6 +10189,7 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
/* The qualifiers on the function type become the qualifiers on
|
/* The qualifiers on the function type become the qualifiers on
|
||||||
the non-static member function. */
|
the non-static member function. */
|
||||||
memfn_quals |= type_memfn_quals (type);
|
memfn_quals |= type_memfn_quals (type);
|
||||||
|
rqual = type_memfn_rqual (type);
|
||||||
type_quals = TYPE_UNQUALIFIED;
|
type_quals = TYPE_UNQUALIFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10216,10 +10254,10 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
ctype = TYPE_METHOD_BASETYPE (type);
|
ctype = TYPE_METHOD_BASETYPE (type);
|
||||||
|
|
||||||
if (ctype)
|
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. */
|
/* Core issue #547: need to allow this in template type args. */
|
||||||
else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
|
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
|
else
|
||||||
error ("invalid qualifiers on non-member function type");
|
error ("invalid qualifiers on non-member function type");
|
||||||
}
|
}
|
||||||
|
@ -10288,7 +10326,7 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
cp_cv_quals real_quals = memfn_quals;
|
cp_cv_quals real_quals = memfn_quals;
|
||||||
if (constexpr_p && sfk != sfk_constructor && sfk != sfk_destructor)
|
if (constexpr_p && sfk != sfk_constructor && sfk != sfk_destructor)
|
||||||
real_quals |= TYPE_QUAL_CONST;
|
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,
|
? unqualified_id : dname,
|
||||||
parms,
|
parms,
|
||||||
unqualified_id,
|
unqualified_id,
|
||||||
virtualp, flags, memfn_quals, raises,
|
virtualp, flags, memfn_quals, rqual, raises,
|
||||||
friendp ? -1 : 0, friendp, publicp,
|
friendp ? -1 : 0, friendp, publicp,
|
||||||
inlinep | (2 * constexpr_p),
|
inlinep | (2 * constexpr_p),
|
||||||
sfk,
|
sfk,
|
||||||
|
@ -10641,7 +10679,7 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
|| storage_class != sc_static);
|
|| storage_class != sc_static);
|
||||||
|
|
||||||
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
|
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
|
||||||
virtualp, flags, memfn_quals, raises,
|
virtualp, flags, memfn_quals, rqual, raises,
|
||||||
1, friendp,
|
1, friendp,
|
||||||
publicp, inlinep | (2 * constexpr_p), sfk,
|
publicp, inlinep | (2 * constexpr_p), sfk,
|
||||||
funcdef_flag,
|
funcdef_flag,
|
||||||
|
@ -14216,8 +14254,9 @@ static_fn_type (tree memfntype)
|
||||||
return memfntype;
|
return memfntype;
|
||||||
gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
|
gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
|
||||||
args = TYPE_ARG_TYPES (memfntype);
|
args = TYPE_ARG_TYPES (memfntype);
|
||||||
|
cp_ref_qualifier rqual = type_memfn_rqual (memfntype);
|
||||||
fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
|
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 = (cp_build_type_attribute_variant
|
||||||
(fntype, TYPE_ATTRIBUTES (memfntype)));
|
(fntype, TYPE_ATTRIBUTES (memfntype)));
|
||||||
fntype = (build_exception_variant
|
fntype = (build_exception_variant
|
||||||
|
@ -14233,9 +14272,10 @@ revert_static_member_fn (tree decl)
|
||||||
{
|
{
|
||||||
tree stype = static_fn_type (decl);
|
tree stype = static_fn_type (decl);
|
||||||
cp_cv_quals quals = type_memfn_quals (stype);
|
cp_cv_quals quals = type_memfn_quals (stype);
|
||||||
|
cp_ref_qualifier rqual = type_memfn_rqual (stype);
|
||||||
|
|
||||||
if (quals != TYPE_UNQUALIFIED)
|
if (quals != TYPE_UNQUALIFIED || rqual != REF_QUAL_NONE)
|
||||||
stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED);
|
stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED, REF_QUAL_NONE);
|
||||||
|
|
||||||
TREE_TYPE (decl) = stype;
|
TREE_TYPE (decl) = stype;
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,8 @@ int at_eof;
|
||||||
that apply to the function). */
|
that apply to the function). */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
|
build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals,
|
||||||
|
cp_ref_qualifier rqual)
|
||||||
{
|
{
|
||||||
tree raises;
|
tree raises;
|
||||||
tree attrs;
|
tree attrs;
|
||||||
|
@ -129,10 +130,12 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
|
||||||
(TREE_CODE (fntype) == METHOD_TYPE
|
(TREE_CODE (fntype) == METHOD_TYPE
|
||||||
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
|
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
|
||||||
: TYPE_ARG_TYPES (fntype)));
|
: TYPE_ARG_TYPES (fntype)));
|
||||||
if (raises)
|
|
||||||
fntype = build_exception_variant (fntype, raises);
|
|
||||||
if (attrs)
|
if (attrs)
|
||||||
fntype = cp_build_type_attribute_variant (fntype, 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);
|
||||||
|
|
||||||
return fntype;
|
return fntype;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +160,9 @@ change_return_type (tree new_ret, tree fntype)
|
||||||
if (TREE_CODE (fntype) == FUNCTION_TYPE)
|
if (TREE_CODE (fntype) == FUNCTION_TYPE)
|
||||||
{
|
{
|
||||||
newtype = build_function_type (new_ret, args);
|
newtype = build_function_type (new_ret, args);
|
||||||
newtype = apply_memfn_quals (newtype, type_memfn_quals (fntype));
|
newtype = apply_memfn_quals (newtype,
|
||||||
|
type_memfn_quals (fntype),
|
||||||
|
type_memfn_rqual (fntype));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
newtype = build_method_type_directly
|
newtype = build_method_type_directly
|
||||||
|
@ -672,6 +677,11 @@ check_classfn (tree ctype, tree function, tree template_parms)
|
||||||
if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
|
if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* ref-qualifier or absence of same must match. */
|
||||||
|
if (type_memfn_rqual (TREE_TYPE (function))
|
||||||
|
!= type_memfn_rqual (TREE_TYPE (fndecl)))
|
||||||
|
continue;
|
||||||
|
|
||||||
/* While finding a match, same types and params are not enough
|
/* While finding a match, same types and params are not enough
|
||||||
if the function is versioned. Also check version ("target")
|
if the function is versioned. Also check version ("target")
|
||||||
attributes. */
|
attributes. */
|
||||||
|
@ -1260,7 +1270,9 @@ cp_reconstruct_complex_type (tree type, tree bottom)
|
||||||
{
|
{
|
||||||
inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
|
inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
|
||||||
outer = build_function_type (inner, TYPE_ARG_TYPES (type));
|
outer = build_function_type (inner, TYPE_ARG_TYPES (type));
|
||||||
outer = apply_memfn_quals (outer, type_memfn_quals (type));
|
outer = apply_memfn_quals (outer,
|
||||||
|
type_memfn_quals (type),
|
||||||
|
type_memfn_rqual (type));
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (type) == METHOD_TYPE)
|
else if (TREE_CODE (type) == METHOD_TYPE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,6 +78,7 @@ static void dump_aggr_init_expr_args (tree, int, bool);
|
||||||
static void dump_expr_list (tree, int);
|
static void dump_expr_list (tree, int);
|
||||||
static void dump_global_iord (tree);
|
static void dump_global_iord (tree);
|
||||||
static void dump_parameters (tree, int);
|
static void dump_parameters (tree, int);
|
||||||
|
static void dump_ref_qualifier (tree, int);
|
||||||
static void dump_exception_spec (tree, int);
|
static void dump_exception_spec (tree, int);
|
||||||
static void dump_template_argument (tree, int);
|
static void dump_template_argument (tree, int);
|
||||||
static void dump_template_argument_list (tree, int);
|
static void dump_template_argument_list (tree, int);
|
||||||
|
@ -832,6 +833,7 @@ dump_type_suffix (tree t, int flags)
|
||||||
pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (t));
|
pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (t));
|
||||||
else
|
else
|
||||||
pp_cxx_cv_qualifier_seq (cxx_pp, t);
|
pp_cxx_cv_qualifier_seq (cxx_pp, t);
|
||||||
|
dump_ref_qualifier (t, flags);
|
||||||
dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
|
dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
|
||||||
dump_type_suffix (TREE_TYPE (t), flags);
|
dump_type_suffix (TREE_TYPE (t), flags);
|
||||||
break;
|
break;
|
||||||
|
@ -1426,6 +1428,7 @@ dump_function_decl (tree t, int flags)
|
||||||
{
|
{
|
||||||
pp_base (cxx_pp)->padding = pp_before;
|
pp_base (cxx_pp)->padding = pp_before;
|
||||||
pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (fntype));
|
pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (fntype));
|
||||||
|
dump_ref_qualifier (fntype, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & TFF_EXCEPTION_SPECIFICATION)
|
if (flags & TFF_EXCEPTION_SPECIFICATION)
|
||||||
|
@ -1507,6 +1510,21 @@ dump_parameters (tree parmtypes, int flags)
|
||||||
pp_cxx_right_paren (cxx_pp);
|
pp_cxx_right_paren (cxx_pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print ref-qualifier of a FUNCTION_TYPE or METHOD_TYPE. FLAGS are ignored. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
dump_ref_qualifier (tree t, int flags ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
if (FUNCTION_REF_QUALIFIED (t))
|
||||||
|
{
|
||||||
|
pp_base (cxx_pp)->padding = pp_before;
|
||||||
|
if (FUNCTION_RVALUE_QUALIFIED (t))
|
||||||
|
pp_cxx_ws_string (cxx_pp, "&&");
|
||||||
|
else
|
||||||
|
pp_cxx_ws_string (cxx_pp, "&");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Print an exception specification. T is the exception specification. */
|
/* Print an exception specification. T is the exception specification. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3408,6 +3426,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
|
||||||
"c++11 attributes "
|
"c++11 attributes "
|
||||||
"only available with -std=c++11 or -std=gnu++11");
|
"only available with -std=c++11 or -std=gnu++11");
|
||||||
break;
|
break;
|
||||||
|
case CPP0X_REF_QUALIFIER:
|
||||||
|
pedwarn (input_location, 0,
|
||||||
|
"ref-qualifiers "
|
||||||
|
"only available with -std=c++0x or -std=gnu++0x");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1234,7 +1234,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
|
||||||
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
|
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
|
||||||
|
|
||||||
static cp_declarator *make_call_declarator
|
static cp_declarator *make_call_declarator
|
||||||
(cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree);
|
(cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree);
|
||||||
static cp_declarator *make_array_declarator
|
static cp_declarator *make_array_declarator
|
||||||
(cp_declarator *, tree);
|
(cp_declarator *, tree);
|
||||||
static cp_declarator *make_pointer_declarator
|
static cp_declarator *make_pointer_declarator
|
||||||
|
@ -1413,6 +1413,7 @@ make_call_declarator (cp_declarator *target,
|
||||||
tree parms,
|
tree parms,
|
||||||
cp_cv_quals cv_qualifiers,
|
cp_cv_quals cv_qualifiers,
|
||||||
cp_virt_specifiers virt_specifiers,
|
cp_virt_specifiers virt_specifiers,
|
||||||
|
cp_ref_qualifier ref_qualifier,
|
||||||
tree exception_specification,
|
tree exception_specification,
|
||||||
tree late_return_type)
|
tree late_return_type)
|
||||||
{
|
{
|
||||||
|
@ -1423,6 +1424,7 @@ make_call_declarator (cp_declarator *target,
|
||||||
declarator->u.function.parameters = parms;
|
declarator->u.function.parameters = parms;
|
||||||
declarator->u.function.qualifiers = cv_qualifiers;
|
declarator->u.function.qualifiers = cv_qualifiers;
|
||||||
declarator->u.function.virt_specifiers = virt_specifiers;
|
declarator->u.function.virt_specifiers = virt_specifiers;
|
||||||
|
declarator->u.function.ref_qualifier = ref_qualifier;
|
||||||
declarator->u.function.exception_specification = exception_specification;
|
declarator->u.function.exception_specification = exception_specification;
|
||||||
declarator->u.function.late_return_type = late_return_type;
|
declarator->u.function.late_return_type = late_return_type;
|
||||||
if (target)
|
if (target)
|
||||||
|
@ -2018,6 +2020,8 @@ static cp_cv_quals cp_parser_cv_qualifier_seq_opt
|
||||||
(cp_parser *);
|
(cp_parser *);
|
||||||
static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
|
static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
|
||||||
(cp_parser *);
|
(cp_parser *);
|
||||||
|
static cp_ref_qualifier cp_parser_ref_qualifier_seq_opt
|
||||||
|
(cp_parser *);
|
||||||
static tree cp_parser_late_return_type_opt
|
static tree cp_parser_late_return_type_opt
|
||||||
(cp_parser *, cp_cv_quals);
|
(cp_parser *, cp_cv_quals);
|
||||||
static tree cp_parser_declarator_id
|
static tree cp_parser_declarator_id
|
||||||
|
@ -8640,6 +8644,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
|
||||||
? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
|
? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
|
||||||
declarator = make_call_declarator (declarator, param_list, quals,
|
declarator = make_call_declarator (declarator, param_list, quals,
|
||||||
VIRT_SPEC_UNSPECIFIED,
|
VIRT_SPEC_UNSPECIFIED,
|
||||||
|
REF_QUAL_NONE,
|
||||||
exception_spec,
|
exception_spec,
|
||||||
/*late_return_type=*/NULL_TREE);
|
/*late_return_type=*/NULL_TREE);
|
||||||
declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
|
declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
|
||||||
|
@ -16309,6 +16314,7 @@ cp_parser_declarator (cp_parser* parser,
|
||||||
declarator-id
|
declarator-id
|
||||||
direct-declarator ( parameter-declaration-clause )
|
direct-declarator ( parameter-declaration-clause )
|
||||||
cv-qualifier-seq [opt]
|
cv-qualifier-seq [opt]
|
||||||
|
ref-qualifier [opt]
|
||||||
exception-specification [opt]
|
exception-specification [opt]
|
||||||
direct-declarator [ constant-expression [opt] ]
|
direct-declarator [ constant-expression [opt] ]
|
||||||
( declarator )
|
( declarator )
|
||||||
|
@ -16317,6 +16323,7 @@ cp_parser_declarator (cp_parser* parser,
|
||||||
direct-abstract-declarator [opt]
|
direct-abstract-declarator [opt]
|
||||||
( parameter-declaration-clause )
|
( parameter-declaration-clause )
|
||||||
cv-qualifier-seq [opt]
|
cv-qualifier-seq [opt]
|
||||||
|
ref-qualifier [opt]
|
||||||
exception-specification [opt]
|
exception-specification [opt]
|
||||||
direct-abstract-declarator [opt] [ constant-expression [opt] ]
|
direct-abstract-declarator [opt] [ constant-expression [opt] ]
|
||||||
( abstract-declarator )
|
( abstract-declarator )
|
||||||
|
@ -16431,12 +16438,13 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||||
/* Consume the `)'. */
|
/* Consume the `)'. */
|
||||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||||
|
|
||||||
/* If all went well, parse the cv-qualifier-seq and the
|
/* If all went well, parse the cv-qualifier-seq,
|
||||||
exception-specification. */
|
ref-qualifier and the exception-specification. */
|
||||||
if (member_p || cp_parser_parse_definitely (parser))
|
if (member_p || cp_parser_parse_definitely (parser))
|
||||||
{
|
{
|
||||||
cp_cv_quals cv_quals;
|
cp_cv_quals cv_quals;
|
||||||
cp_virt_specifiers virt_specifiers;
|
cp_virt_specifiers virt_specifiers;
|
||||||
|
cp_ref_qualifier ref_qual;
|
||||||
tree exception_specification;
|
tree exception_specification;
|
||||||
tree late_return;
|
tree late_return;
|
||||||
tree attrs;
|
tree attrs;
|
||||||
|
@ -16451,6 +16459,8 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||||
|
|
||||||
/* Parse the cv-qualifier-seq. */
|
/* Parse the cv-qualifier-seq. */
|
||||||
cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
|
cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
|
||||||
|
/* Parse the ref-qualifier. */
|
||||||
|
ref_qual = cp_parser_ref_qualifier_seq_opt (parser);
|
||||||
/* And the exception-specification. */
|
/* And the exception-specification. */
|
||||||
exception_specification
|
exception_specification
|
||||||
= cp_parser_exception_specification_opt (parser);
|
= cp_parser_exception_specification_opt (parser);
|
||||||
|
@ -16468,6 +16478,7 @@ cp_parser_direct_declarator (cp_parser* parser,
|
||||||
params,
|
params,
|
||||||
cv_quals,
|
cv_quals,
|
||||||
virt_specifiers,
|
virt_specifiers,
|
||||||
|
ref_qual,
|
||||||
exception_specification,
|
exception_specification,
|
||||||
late_return);
|
late_return);
|
||||||
declarator->std_attributes = attrs;
|
declarator->std_attributes = attrs;
|
||||||
|
@ -17008,6 +17019,38 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
|
||||||
return cv_quals;
|
return cv_quals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse an (optional) ref-qualifier
|
||||||
|
|
||||||
|
ref-qualifier:
|
||||||
|
&
|
||||||
|
&&
|
||||||
|
|
||||||
|
Returns cp_ref_qualifier representing ref-qualifier. */
|
||||||
|
|
||||||
|
static cp_ref_qualifier
|
||||||
|
cp_parser_ref_qualifier_seq_opt (cp_parser* parser)
|
||||||
|
{
|
||||||
|
cp_ref_qualifier ref_qual = REF_QUAL_NONE;
|
||||||
|
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||||
|
switch (token->type)
|
||||||
|
{
|
||||||
|
case CPP_AND:
|
||||||
|
ref_qual = REF_QUAL_LVALUE;
|
||||||
|
break;
|
||||||
|
case CPP_AND_AND:
|
||||||
|
ref_qual = REF_QUAL_RVALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref_qual)
|
||||||
|
{
|
||||||
|
maybe_warn_cpp0x (CPP0X_REF_QUALIFIER);
|
||||||
|
cp_lexer_consume_token (parser->lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref_qual;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse an (optional) virt-specifier-seq.
|
/* Parse an (optional) virt-specifier-seq.
|
||||||
|
|
||||||
virt-specifier-seq:
|
virt-specifier-seq:
|
||||||
|
|
19
gcc/cp/pt.c
19
gcc/cp/pt.c
|
@ -10955,7 +10955,9 @@ tsubst_function_type (tree t,
|
||||||
if (TREE_CODE (t) == FUNCTION_TYPE)
|
if (TREE_CODE (t) == FUNCTION_TYPE)
|
||||||
{
|
{
|
||||||
fntype = build_function_type (return_type, arg_types);
|
fntype = build_function_type (return_type, arg_types);
|
||||||
fntype = apply_memfn_quals (fntype, type_memfn_quals (t));
|
fntype = apply_memfn_quals (fntype,
|
||||||
|
type_memfn_quals (t),
|
||||||
|
type_memfn_rqual (t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -10977,6 +10979,7 @@ tsubst_function_type (tree t,
|
||||||
|
|
||||||
fntype = build_method_type_directly (r, return_type,
|
fntype = build_method_type_directly (r, return_type,
|
||||||
TREE_CHAIN (arg_types));
|
TREE_CHAIN (arg_types));
|
||||||
|
fntype = build_ref_qualified_type (fntype, type_memfn_rqual (t));
|
||||||
}
|
}
|
||||||
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
|
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
|
||||||
|
|
||||||
|
@ -11609,7 +11612,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||||
/* The type of the implicit object parameter gets its
|
/* The type of the implicit object parameter gets its
|
||||||
cv-qualifiers from the FUNCTION_TYPE. */
|
cv-qualifiers from the FUNCTION_TYPE. */
|
||||||
tree memptr;
|
tree memptr;
|
||||||
tree method_type = build_memfn_type (type, r, type_memfn_quals (type));
|
tree method_type
|
||||||
|
= build_memfn_type (type, r, type_memfn_quals (type),
|
||||||
|
type_memfn_rqual (type));
|
||||||
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
|
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
|
||||||
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
|
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
|
||||||
complain);
|
complain);
|
||||||
|
@ -17097,10 +17102,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
|
||||||
build_function_type (TREE_TYPE (method_type),
|
build_function_type (TREE_TYPE (method_type),
|
||||||
TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
|
TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
|
||||||
|
|
||||||
/* Extract the cv-qualifiers of the member function from the
|
/* Extract the cv-qualifiers and ref-qualifier of the member
|
||||||
implicit object parameter and place them on the function
|
function from the implicit object parameter and place them
|
||||||
type to be restored later. */
|
on the function type to be restored later. */
|
||||||
fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
|
fntype = apply_memfn_quals (fntype,
|
||||||
|
type_memfn_quals (method_type),
|
||||||
|
type_memfn_rqual (method_type));
|
||||||
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, explain_p);
|
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, explain_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1081,6 +1081,15 @@ cp_build_qualified_type_real (tree type,
|
||||||
/* Retrieve (or create) the appropriately qualified variant. */
|
/* Retrieve (or create) the appropriately qualified variant. */
|
||||||
result = build_qualified_type (type, type_quals);
|
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,
|
/* 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
|
then we need to unshare the record that holds the cached
|
||||||
pointer-to-member-function type, because these will be distinct
|
pointer-to-member-function type, because these will be distinct
|
||||||
|
@ -1214,7 +1223,9 @@ strip_typedefs (tree t)
|
||||||
{
|
{
|
||||||
result = build_function_type (type,
|
result = build_function_type (type,
|
||||||
arg_types);
|
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))
|
if (TYPE_RAISES_EXCEPTIONS (t))
|
||||||
|
@ -1702,6 +1713,64 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p)
|
||||||
return t;
|
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)
|
/* Returns nonzero if X is an expression for a (possibly overloaded)
|
||||||
function. If "f" is a function or function template, "f", "c->f",
|
function. If "f" is a function or function template, "f", "c->f",
|
||||||
"c.f", "C::f", and "f<int>" will all be considered possibly
|
"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;
|
return type;
|
||||||
|
|
||||||
type_quals = TYPE_QUALS (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))
|
for (v = TYPE_MAIN_VARIANT (type); v; v = TYPE_NEXT_VARIANT (v))
|
||||||
if (check_qualified_type (v, type, type_quals)
|
if (cp_check_qualified_type (v, type, type_quals, rqual, raises))
|
||||||
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), ce_exact))
|
|
||||||
return v;
|
return v;
|
||||||
|
|
||||||
/* Need to build a new variant. */
|
/* 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);
|
new_type = build_type_attribute_variant (type, attributes);
|
||||||
if (TREE_CODE (new_type) == FUNCTION_TYPE
|
if (TREE_CODE (new_type) == FUNCTION_TYPE
|
||||||
|| TREE_CODE (new_type) == METHOD_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. */
|
/* Making a new main variant of a class type is broken. */
|
||||||
gcc_assert (!CLASS_TYPE_P (type) || new_type == type);
|
gcc_assert (!CLASS_TYPE_P (type) || new_type == type);
|
||||||
|
|
|
@ -832,7 +832,10 @@ merge_types (tree t1, tree t2)
|
||||||
|
|
||||||
rval = build_function_type (valtype, parms);
|
rval = build_function_type (valtype, parms);
|
||||||
gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
|
gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
|
||||||
rval = apply_memfn_quals (rval, type_memfn_quals (t1));
|
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),
|
raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
|
||||||
TYPE_RAISES_EXCEPTIONS (t2),
|
TYPE_RAISES_EXCEPTIONS (t2),
|
||||||
NULL_TREE);
|
NULL_TREE);
|
||||||
|
@ -1184,6 +1187,12 @@ structural_comptypes (tree t1, tree t2, int strict)
|
||||||
if (TREE_CODE (t1) == FUNCTION_TYPE
|
if (TREE_CODE (t1) == FUNCTION_TYPE
|
||||||
&& type_memfn_quals (t1) != type_memfn_quals (t2))
|
&& type_memfn_quals (t1) != type_memfn_quals (t2))
|
||||||
return false;
|
return false;
|
||||||
|
/* Need to check this before TYPE_MAIN_VARIANT.
|
||||||
|
FIXME function qualifiers should really change the main variant. */
|
||||||
|
if ((TREE_CODE (t1) == FUNCTION_TYPE
|
||||||
|
|| TREE_CODE (t1) == METHOD_TYPE)
|
||||||
|
&& type_memfn_rqual (t1) != type_memfn_rqual (t2))
|
||||||
|
return false;
|
||||||
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
|
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -8563,6 +8572,22 @@ cp_type_quals (const_tree type)
|
||||||
return quals;
|
return quals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns the function-ref-qualifier for TYPE */
|
||||||
|
|
||||||
|
cp_ref_qualifier
|
||||||
|
type_memfn_rqual (const_tree type)
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE
|
||||||
|
|| TREE_CODE (type) == METHOD_TYPE);
|
||||||
|
|
||||||
|
if (!FUNCTION_REF_QUALIFIED (type))
|
||||||
|
return REF_QUAL_NONE;
|
||||||
|
else if (FUNCTION_RVALUE_QUALIFIED (type))
|
||||||
|
return REF_QUAL_RVALUE;
|
||||||
|
else
|
||||||
|
return REF_QUAL_LVALUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or
|
/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or
|
||||||
METHOD_TYPE. */
|
METHOD_TYPE. */
|
||||||
|
|
||||||
|
@ -8578,18 +8603,22 @@ type_memfn_quals (const_tree type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to
|
/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to
|
||||||
MEMFN_QUALS. */
|
MEMFN_QUALS and its ref-qualifier to RQUAL. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
apply_memfn_quals (tree type, cp_cv_quals memfn_quals)
|
apply_memfn_quals (tree type, cp_cv_quals memfn_quals, cp_ref_qualifier rqual)
|
||||||
{
|
{
|
||||||
/* Could handle METHOD_TYPE here if necessary. */
|
/* Could handle METHOD_TYPE here if necessary. */
|
||||||
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
|
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
|
||||||
if (TYPE_QUALS (type) == memfn_quals)
|
if (TYPE_QUALS (type) == memfn_quals
|
||||||
|
&& type_memfn_rqual (type) == rqual)
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
/* This should really have a different TYPE_MAIN_VARIANT, but that gets
|
/* This should really have a different TYPE_MAIN_VARIANT, but that gets
|
||||||
complex. */
|
complex. */
|
||||||
return build_qualified_type (type, memfn_quals);
|
tree result = build_qualified_type (type, memfn_quals);
|
||||||
|
result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type));
|
||||||
|
return build_ref_qualified_type (result, rqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns nonzero if TYPE is const or volatile. */
|
/* Returns nonzero if TYPE is const or volatile. */
|
||||||
|
|
|
@ -1708,7 +1708,24 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain)
|
||||||
return datum;
|
return datum;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return build2 (OFFSET_REF, type, datum, component);
|
{
|
||||||
|
/* 5.5/6: In a .* expression whose object expression is an rvalue, the
|
||||||
|
program is ill-formed if the second operand is a pointer to member
|
||||||
|
function with ref-qualifier &. In a .* expression whose object
|
||||||
|
expression is an lvalue, the program is ill-formed if the second
|
||||||
|
operand is a pointer to member function with ref-qualifier &&. */
|
||||||
|
if (FUNCTION_REF_QUALIFIED (type))
|
||||||
|
{
|
||||||
|
bool lval = real_lvalue_p (datum);
|
||||||
|
if (lval && FUNCTION_RVALUE_QUALIFIED (type))
|
||||||
|
error ("pointer-to-member-function type %qT requires an rvalue",
|
||||||
|
ptrmem_type);
|
||||||
|
else if (!lval && !FUNCTION_RVALUE_QUALIFIED (type))
|
||||||
|
error ("pointer-to-member-function type %qT requires an lvalue",
|
||||||
|
ptrmem_type);
|
||||||
|
}
|
||||||
|
return build2 (OFFSET_REF, type, datum, component);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
|
/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
template <class,class> struct ST;
|
||||||
|
template <class T> struct ST<T,T> {};
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int f() &;
|
||||||
|
char f() &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> struct B
|
||||||
|
{
|
||||||
|
int f() &;
|
||||||
|
char f() &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
a.f();
|
||||||
|
A().f();
|
||||||
|
ST<decltype(a.f()), int>();
|
||||||
|
ST<decltype(A().f()), char>();
|
||||||
|
B<int> b;
|
||||||
|
b.f();
|
||||||
|
B<int>().f();
|
||||||
|
ST<decltype(b.f()), int>();
|
||||||
|
ST<decltype(B<int>().f()), char>();
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
// In a .* expression whose object expression is an rvalue, the program is
|
||||||
|
// ill-formed if the second operand is a pointer to member function with
|
||||||
|
// ref-qualifier &. In a .* expression whose object expression is an
|
||||||
|
// lvalue, the program is ill-formed if the second operand is a pointer to
|
||||||
|
// member function with ref-qualifier &&.
|
||||||
|
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
void f() &;
|
||||||
|
void g() &&;
|
||||||
|
void h();
|
||||||
|
};
|
||||||
|
|
||||||
|
void one()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
|
||||||
|
void (A::*p)() & = &A::f;
|
||||||
|
(a.*p)();
|
||||||
|
(A().*p)(); // { dg-error "" }
|
||||||
|
|
||||||
|
p = &A::g; // { dg-error "" }
|
||||||
|
p = &A::h; // { dg-error "" }
|
||||||
|
|
||||||
|
void (A::*p2)() && = &A::g;
|
||||||
|
(A().*p2)();
|
||||||
|
(a.*p2)(); // { dg-error "" }
|
||||||
|
p2 = &A::f; // { dg-error "" }
|
||||||
|
p2 = &A::h; // { dg-error "" }
|
||||||
|
|
||||||
|
void (A::*p3)() = &A::h;
|
||||||
|
(a.*p3)();
|
||||||
|
(A().*p3)();
|
||||||
|
p3 = &A::f; // { dg-error "" }
|
||||||
|
p3 = &A::g; // { dg-error "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct B {
|
||||||
|
void f() &;
|
||||||
|
void g() &&;
|
||||||
|
void h();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void two()
|
||||||
|
{
|
||||||
|
B<T> a;
|
||||||
|
|
||||||
|
void (B<T>::*p)() & = &B<T>::f;
|
||||||
|
(a.*p)();
|
||||||
|
(B<T>().*p)(); // { dg-error "" }
|
||||||
|
|
||||||
|
p = &B<T>::g; // { dg-error "" }
|
||||||
|
p = &B<T>::h; // { dg-error "" }
|
||||||
|
|
||||||
|
void (B<T>::*p2)() && = &B<T>::g;
|
||||||
|
(B<T>().*p2)();
|
||||||
|
(a.*p2)(); // { dg-error "" }
|
||||||
|
p2 = &B<T>::f; // { dg-error "" }
|
||||||
|
p2 = &B<T>::h; // { dg-error "" }
|
||||||
|
|
||||||
|
void (B<T>::*p3)() = &B<T>::h;
|
||||||
|
(a.*p3)();
|
||||||
|
(B<T>().*p3)();
|
||||||
|
p3 = &B<T>::f; // { dg-error "" }
|
||||||
|
p3 = &B<T>::g; // { dg-error "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
one();
|
||||||
|
two<int>();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// An explicitly defaulted function can have a ref-qualifier.
|
||||||
|
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
A& operator=(const A&) & = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct B {
|
||||||
|
B& operator=(const B&) & = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
B<T> b;
|
||||||
|
b = B<T>();
|
||||||
|
B<T>() = b; // { dg-error "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
a = A();
|
||||||
|
A() = a; // { dg-error "" }
|
||||||
|
|
||||||
|
f<int>();
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 12.1: A constructor shall not be declared with a ref-qualifier.
|
||||||
|
// 12.4: A destructor shall not be declared with a ref-qualifier.
|
||||||
|
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
A() & = default; // { dg-error "constructor" }
|
||||||
|
~A() & = default; // { dg-error "destructor" }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
// 13.1: ...cannot be overloaded if any of them, but not all, have a
|
||||||
|
// ref-qualifier.
|
||||||
|
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
class Y {
|
||||||
|
void h() &;
|
||||||
|
void h() const &; // OK
|
||||||
|
void h() &&; // OK, all declarations have a ref-qualifier
|
||||||
|
void i() &; // { dg-message "" }
|
||||||
|
void i() const; // { dg-error "" } prior declaration of i
|
||||||
|
// has a ref-qualifier
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Binding an rvalue to && beats binding it to const& (13.3.3.2).
|
||||||
|
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int operator+(int) &&;
|
||||||
|
};
|
||||||
|
|
||||||
|
void operator+ (const A&, int);
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return A() + 42;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// typedef test
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
typedef void F() &;
|
||||||
|
|
||||||
|
F f; // { dg-error "" }
|
||||||
|
F* p; // { dg-error "" }
|
||||||
|
extern F& r; // { dg-error "" }
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
F f;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
a.f();
|
||||||
|
A().f(); // { dg-error "" }
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
// { dg-require-effective-target c++11 }
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
virtual void f() & = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B: A
|
||||||
|
{
|
||||||
|
void f(); // doesn't override
|
||||||
|
};
|
||||||
|
|
||||||
|
B b; // { dg-error "abstract" }
|
Loading…
Reference in New Issue