Commit 2872152c by Jason Merrill Committed by Jason Merrill

re PR c++/44193 (function types, cv-quals and typename)

	PR c++/44193
	* typeck.c (type_memfn_quals): New fn.
	(apply_memfn_quals): New fn.
	(cp_type_quals): Return TYPE_UNQUALIFIED for FUNCTION_TYPE.
	(cp_type_readonly): Use cp_type_quals.
	* cp-tree.h: Add declarations.
	* tree.c (cp_build_qualified_type_real): Don't set, but do
	preserve, quals on FUNCTION_TYPE.
	(strip_typedefs): Use apply_memfn_quals and type_memfn_quals.
	* decl.c (build_ptrmem_type): Likewise.
	(grokdeclarator): Likewise.
	(static_fn_type): Likewise.
	* decl2.c (change_return_type): Likewise.
	(cp_reconstruct_complex_type): Likewise.
	* pt.c (tsubst_function_type): Likewise.
	(unify): Likewise.
	(tsubst): Likewise.  Drop special FUNCTION_TYPE substitution code.

From-SVN: r159596
parent 1961ffb8
2010-05-19 Jason Merrill <jason@redhat.com>
PR c++/44193
* typeck.c (type_memfn_quals): New fn.
(apply_memfn_quals): New fn.
(cp_type_quals): Return TYPE_UNQUALIFIED for FUNCTION_TYPE.
(cp_type_readonly): Use cp_type_quals.
* cp-tree.h: Add declarations.
* tree.c (cp_build_qualified_type_real): Don't set, but do
preserve, quals on FUNCTION_TYPE.
(strip_typedefs): Use apply_memfn_quals and type_memfn_quals.
* decl.c (build_ptrmem_type): Likewise.
(grokdeclarator): Likewise.
(static_fn_type): Likewise.
* decl2.c (change_return_type): Likewise.
(cp_reconstruct_complex_type): Likewise.
* pt.c (tsubst_function_type): Likewise.
(unify): Likewise.
(tsubst): Likewise. Drop special FUNCTION_TYPE substitution code.
2010-05-18 Nathan Froyd <froydnj@codesourcery.com>
* tree.c (build_min_non_dep_call_vec): Update comment.
......
......@@ -5413,6 +5413,8 @@ extern bool error_type_p (const_tree);
extern int ptr_reasonably_similar (const_tree, const_tree);
extern tree build_ptrmemfunc (tree, tree, int, bool);
extern int cp_type_quals (const_tree);
extern int type_memfn_quals (const_tree);
extern tree apply_memfn_quals (tree, cp_cv_quals);
extern bool cp_type_readonly (const_tree);
extern bool cp_has_mutable_p (const_tree);
extern bool at_least_as_qualified_p (const_tree, const_tree);
......
......@@ -7265,8 +7265,7 @@ build_ptrmem_type (tree class_type, tree member_type)
{
if (TREE_CODE (member_type) == METHOD_TYPE)
{
tree arg_types = TYPE_ARG_TYPES (member_type);
cp_cv_quals quals = cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)));
cp_cv_quals quals = type_memfn_quals (member_type);
member_type = build_memfn_type (member_type, class_type, quals);
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
......@@ -8683,7 +8682,7 @@ grokdeclarator (const cp_declarator *declarator,
&& (TREE_CODE (type) == FUNCTION_TYPE
|| (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
{
memfn_quals |= cp_type_quals (type);
memfn_quals |= type_memfn_quals (type);
type = build_memfn_type (type,
declarator->u.pointer.class_type,
memfn_quals);
......@@ -8691,7 +8690,7 @@ grokdeclarator (const cp_declarator *declarator,
}
if (TREE_CODE (type) == FUNCTION_TYPE
&& cp_type_quals (type) != TYPE_UNQUALIFIED)
&& type_memfn_quals (type) != TYPE_UNQUALIFIED)
error (declarator->kind == cdk_reference
? G_("cannot declare reference to qualified function type %qT")
: G_("cannot declare pointer to qualified function type %qT"),
......@@ -8994,7 +8993,7 @@ grokdeclarator (const cp_declarator *declarator,
function type. */
if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
{
type = cp_build_qualified_type (type, memfn_quals);
type = apply_memfn_quals (type, memfn_quals);
/* We have now dealt with these qualifiers. */
memfn_quals = TYPE_UNQUALIFIED;
......@@ -9114,7 +9113,7 @@ grokdeclarator (const cp_declarator *declarator,
{
/* 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 (cp_type_quals (type) != TYPE_UNQUALIFIED
if (type_memfn_quals (type) != TYPE_UNQUALIFIED
&& (current_class_type == NULL_TREE || staticp) )
{
error (staticp
......@@ -9127,7 +9126,7 @@ grokdeclarator (const cp_declarator *declarator,
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
memfn_quals |= cp_type_quals (type);
memfn_quals |= type_memfn_quals (type);
type_quals = TYPE_UNQUALIFIED;
}
}
......@@ -9195,7 +9194,7 @@ grokdeclarator (const cp_declarator *declarator,
type = build_memfn_type (type, ctype, memfn_quals);
/* Core issue #547: need to allow this in template type args. */
else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
type = cp_build_qualified_type (type, memfn_quals);
type = apply_memfn_quals (type, memfn_quals);
else
error ("invalid qualifiers on non-member function type");
}
......@@ -12944,7 +12943,6 @@ static_fn_type (tree memfntype)
{
tree fntype;
tree args;
int quals;
if (TYPE_PTRMEMFUNC_P (memfntype))
memfntype = TYPE_PTRMEMFUNC_FN_TYPE (memfntype);
......@@ -12956,8 +12954,7 @@ static_fn_type (tree memfntype)
gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
args = TYPE_ARG_TYPES (memfntype);
fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
quals = cp_type_quals (TREE_TYPE (TREE_VALUE (args)));
fntype = build_qualified_type (fntype, quals);
fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype));
fntype = (cp_build_type_attribute_variant
(fntype, TYPE_ATTRIBUTES (memfntype)));
fntype = (build_exception_variant
......
......@@ -154,7 +154,10 @@ change_return_type (tree new_ret, tree fntype)
return fntype;
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));
}
else
newtype = build_method_type_directly
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
......@@ -1246,6 +1249,7 @@ cp_reconstruct_complex_type (tree type, tree bottom)
{
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));
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
......
......@@ -9791,7 +9791,10 @@ tsubst_function_type (tree t,
/* Construct a new type node and return it. */
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));
}
else
{
tree r = TREE_TYPE (TREE_VALUE (arg_types));
......@@ -9813,7 +9816,6 @@ tsubst_function_type (tree t,
fntype = build_method_type_directly (r, return_type,
TREE_CHAIN (arg_types));
}
fntype = cp_build_qualified_type_real (fntype, TYPE_QUALS (t), complain);
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
return fntype;
......@@ -10111,14 +10113,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
int quals;
gcc_assert (TYPE_P (arg));
/* cv-quals from the template are discarded when
substituting in a function or reference type. */
if (TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE
|| TREE_CODE (arg) == REFERENCE_TYPE)
quals = cp_type_quals (arg);
else
quals = cp_type_quals (arg) | cp_type_quals (t);
quals = cp_type_quals (arg) | cp_type_quals (t);
return cp_build_qualified_type_real
(arg, quals, complain | tf_ignore_bad_quals);
......@@ -10378,7 +10373,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
tree memptr;
tree method_type = build_memfn_type (type, r, cp_type_quals (type));
tree method_type = build_memfn_type (type, r, type_memfn_quals (type));
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
complain);
......@@ -15042,7 +15037,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree method_type;
tree fntype;
cp_cv_quals cv_quals;
/* Check top-level cv qualifiers */
if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
......@@ -15061,9 +15055,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* Extract the cv-qualifiers of the member function from the
implicit object parameter and place them on the function
type to be restored later. */
cv_quals =
cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
fntype = build_qualified_type (fntype, cv_quals);
fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
}
......
......@@ -868,12 +868,17 @@ cp_build_qualified_type_real (tree type,
[dcl.ref], [dcl.fct] */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
{
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
/* But preserve any function-cv-quals on a FUNCTION_TYPE. */
if (TREE_CODE (type) == FUNCTION_TYPE)
type_quals |= type_memfn_quals (type);
/* A restrict-qualified type must be a pointer (or reference)
to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
......@@ -1038,8 +1043,11 @@ strip_typedefs (tree t)
TREE_CHAIN (arg_types));
}
else
{
result = build_function_type (type,
arg_types);
result = apply_memfn_quals (result, type_memfn_quals (t));
}
if (TYPE_RAISES_EXCEPTIONS (t))
result = build_exception_variant (result,
......
......@@ -7851,12 +7851,50 @@ comp_ptr_ttypes_const (tree to, tree from)
int
cp_type_quals (const_tree type)
{
int quals;
/* This CONST_CAST is okay because strip_array_types returns its
argument unmodified and we assign it to a const_tree. */
type = strip_array_types (CONST_CAST_TREE(type));
if (type == error_mark_node)
type = strip_array_types (CONST_CAST_TREE (type));
if (type == error_mark_node
/* Quals on a FUNCTION_TYPE are memfn quals. */
|| TREE_CODE (type) == FUNCTION_TYPE)
return TYPE_UNQUALIFIED;
return TYPE_QUALS (type);
quals = TYPE_QUALS (type);
/* METHOD and REFERENCE_TYPEs should never have quals. */
gcc_assert ((TREE_CODE (type) != METHOD_TYPE
&& TREE_CODE (type) != REFERENCE_TYPE)
|| ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
== TYPE_UNQUALIFIED));
return quals;
}
/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or
METHOD_TYPE. */
int
type_memfn_quals (const_tree type)
{
if (TREE_CODE (type) == FUNCTION_TYPE)
return TYPE_QUALS (type);
else if (TREE_CODE (type) == METHOD_TYPE)
return cp_type_quals (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))));
else
gcc_unreachable ();
}
/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to
MEMFN_QUALS. */
tree
apply_memfn_quals (tree type, cp_cv_quals memfn_quals)
{
/* Could handle METHOD_TYPE here if necessary. */
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
if (TYPE_QUALS (type) == memfn_quals)
return type;
/* This should really have a different TYPE_MAIN_VARIANT, but that gets
complex. */
return build_qualified_type (type, memfn_quals);
}
/* Returns nonzero if the TYPE is const from a C++ perspective: look inside
......@@ -7867,8 +7905,7 @@ cp_type_readonly (const_tree type)
{
/* This CONST_CAST is okay because strip_array_types returns its
argument unmodified and we assign it to a const_tree. */
type = strip_array_types (CONST_CAST_TREE(type));
return TYPE_READONLY (type);
return (cp_type_quals (type) & TYPE_QUAL_CONST) != 0;
}
/* Returns nonzero if TYPE is const or volatile. */
......
2010-05-19 Jason Merrill <jason@redhat.com>
PR c++/44193
* g++.dg/template/fntype1.C: New.
2010-05-19 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/discr23.ad[sb]: New test.
......
bool f(int i) { return i != 5; }
template <class X, class P = bool(X)>
struct Traits
{
typedef P type;
};
template <class X, class P = typename Traits<X>::type>
struct S
{
const P& p_;
S( const P& p ) : p_(p) {} // const reference
};
template <class X>
S<X> make_s(const typename Traits<X>::type & p) // const reference
{
return S<X>(p); // << HERE
}
int main()
{
make_s<int>(f);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment