re PR c++/19076 (Pointer to member function not matched to pointer to member template)

2005-02-21  Douglas Gregor  <dgregor@cs.indiana.edu>

	PR c++/19076
	PR c++/6628
	* cp-tree.h (cp_apply_type_quals_to_decl): Declared.
	* decl.c (grokdeclarator): Pedwarn about qualifying a function
	type.
	Add qualifiers when declaring a typedef of a function type.
	Member function pointers pick up the qualifiers of the typedef
	used to declare them.
        Don't complain about creating cv-qualified function types.
	Complain about qualified function typedefs that are used to
	declare non-static member functions or free functions.
	Use cp_apply_type_quals_to_decl.
	(start_preparsed_function): Use cp_apply_type_quals_to_decl.
	(grokclassfn): Use cp_apply_type_quals_to_decl.
	* error.c (dump_type_suffix): Print qualifiers for function
	types.
	* pt.c (tsubst_decl): Use cp_apply_type_quals_to_decl.
	(tsubst): When substituting a function type into a member
	pointer type, pass along the qualifiers.
	(unify): Unify member pointers to member function pointers.
	* tree.c (cp_build_qualified_type_real): Function types may be
	qualified. This includes restrict qualifiers.
	* typeck.c (cp_apply_type_quals_to_decl): New function to replace
	use of c_apply_type_quals_to_decl. Drops qualifiers that are being
	added to function types.

From-SVN: r95356
This commit is contained in:
Douglas Gregor 2005-02-21 23:12:27 +00:00 committed by Paolo Carlini
parent 89e4aa8109
commit 9804209d32
8 changed files with 155 additions and 27 deletions

View File

@ -1,3 +1,31 @@
2005-02-21 Douglas Gregor <dgregor@cs.indiana.edu>
PR c++/19076
PR c++/6628
* cp-tree.h (cp_apply_type_quals_to_decl): Declared.
* decl.c (grokdeclarator): Pedwarn about qualifying a function
type.
Add qualifiers when declaring a typedef of a function type.
Member function pointers pick up the qualifiers of the typedef
used to declare them.
Don't complain about creating cv-qualified function types.
Complain about qualified function typedefs that are used to
declare non-static member functions or free functions.
Use cp_apply_type_quals_to_decl.
(start_preparsed_function): Use cp_apply_type_quals_to_decl.
(grokclassfn): Use cp_apply_type_quals_to_decl.
* error.c (dump_type_suffix): Print qualifiers for function
types.
* pt.c (tsubst_decl): Use cp_apply_type_quals_to_decl.
(tsubst): When substituting a function type into a member
pointer type, pass along the qualifiers.
(unify): Unify member pointers to member function pointers.
* tree.c (cp_build_qualified_type_real): Function types may be
qualified. This includes restrict qualifiers.
* typeck.c (cp_apply_type_quals_to_decl): New function to replace
use of c_apply_type_quals_to_decl. Drops qualifiers that are being
added to function types.
2005-02-20 Zack Weinberg <zack@codesourcery.com>
PR 18785

View File

@ -4310,6 +4310,7 @@ extern tree build_ptrmemfunc (tree, tree, int, bool);
extern int cp_type_quals (tree);
extern bool cp_has_mutable_p (tree);
extern bool at_least_as_qualified_p (tree, tree);
extern void cp_apply_type_quals_to_decl (int, tree);
extern tree build_ptrmemfunc1 (tree, tree, tree);
extern void expand_ptrmemfunc_cst (tree, tree *, tree *);
extern tree pfn_from_ptrmemfunc (tree);

View File

@ -6939,6 +6939,20 @@ grokdeclarator (const cp_declarator *declarator,
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
if (TREE_CODE (type) == FUNCTION_TYPE
&& type_quals != TYPE_UNQUALIFIED)
{
/* This was an error in C++98 (cv-qualifiers cannot be added to
a function type), but DR 295 makes the code well-formed by
dropping the extra qualifiers. */
if (pedantic)
{
tree bad_type = build_qualified_type (type, type_quals);
pedwarn ("ignoring %qV qualifiers added to function type %qT",
bad_type, type);
}
type_quals = TYPE_UNQUALIFIED;
}
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
@ -7300,6 +7314,7 @@ grokdeclarator (const cp_declarator *declarator,
}
type = build_function_type (type, arg_types);
type = cp_build_qualified_type (type, quals);
}
break;
@ -7332,7 +7347,15 @@ grokdeclarator (const cp_declarator *declarator,
&& (TREE_CODE (type) == FUNCTION_TYPE
|| (quals && TREE_CODE (type) == METHOD_TYPE)))
{
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
tree dummy;
/* If the type is a FUNCTION_TYPE, pick up the
qualifiers from that function type. No other
qualifiers may be supplied. */
if (TREE_CODE (type) == FUNCTION_TYPE)
quals = cp_type_quals (type);
dummy = build_decl (TYPE_DECL, NULL_TREE, type);
grok_method_quals (declarator->u.pointer.class_type,
dummy, quals);
type = TREE_TYPE (dummy);
@ -7629,11 +7652,12 @@ grokdeclarator (const cp_declarator *declarator,
{
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) != METHOD_TYPE)
error ("%Jinvalid type qualifier for non-member function type",
decl);
else
if (TREE_CODE (type) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (type);
/* Any qualifiers on a function type typedef have
already been dealt with. */
else if (TREE_CODE (type) == FUNCTION_TYPE)
quals = TYPE_UNQUALIFIED;
}
if (ctype != NULL_TREE)
grok_method_quals (ctype, decl, quals);
@ -7676,6 +7700,23 @@ grokdeclarator (const cp_declarator *declarator,
}
parms = nreverse (decls);
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 (cp_type_quals (type) != TYPE_UNQUALIFIED
&& (current_class_type == NULL_TREE || staticp) )
{
error ("qualified function types cannot be used to declare %s functions",
(staticp? "static member" : "free"));
type = TYPE_MAIN_VARIANT (type);
}
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
quals |= cp_type_quals (type);
}
}
/* If this is a type name (such as, in a cast or sizeof),
@ -8211,7 +8252,7 @@ grokdeclarator (const cp_declarator *declarator,
when processing a template; we'll do this for the instantiated
declaration based on the type of DECL. */
if (!processing_template_decl)
c_apply_type_quals_to_decl (type_quals, decl);
cp_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
@ -9995,7 +10036,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
DECL_IGNORED_P (resdecl) = 1;
DECL_RESULT (decl1) = resdecl;
c_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
}
/* Initialize RTL machinery. We cannot do this until

View File

@ -299,7 +299,7 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags,
this_quals |= TYPE_QUAL_CONST;
qual_type = cp_build_qualified_type (type, this_quals);
parm = build_artificial_parm (this_identifier, qual_type);
c_apply_type_quals_to_decl (this_quals, parm);
cp_apply_type_quals_to_decl (this_quals, parm);
TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
DECL_ARGUMENTS (function) = parm;
}

View File

@ -613,6 +613,8 @@ dump_type_suffix (tree t, int flags)
if (TREE_CODE (t) == METHOD_TYPE)
pp_cxx_cv_qualifier_seq
(cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
else
pp_cxx_cv_qualifier_seq(cxx_pp, t);
dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
dump_type_suffix (TREE_TYPE (t), flags);
break;

View File

@ -6469,7 +6469,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
if (DECL_INITIAL (r))
{
@ -6499,7 +6499,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (type == error_mark_node)
return error_mark_node;
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
@ -6599,7 +6599,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
DECL_CONTEXT (r) = ctx;
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
@ -7218,22 +7218,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (TREE_CODE (type) != METHOD_TYPE);
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* This is really a method type. The cv qualifiers of the
this pointer should _not_ be determined by the cv
qualifiers of the class type. They should be held
somewhere in the FUNCTION_TYPE, but we don't do that at
the moment. Consider
typedef void (Func) () const;
template <typename T1> void Foo (Func T1::*);
*/
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
tree method_type;
method_type = build_method_type_directly (TYPE_MAIN_VARIANT (r),
tree this_type = cp_build_qualified_type (TYPE_MAIN_VARIANT (r),
cp_type_quals (type));
tree memptr;
method_type = build_method_type_directly (this_type,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
return 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),
complain);
}
else
return cp_build_qualified_type_real (build_ptrmem_type (r, type),
@ -10251,6 +10247,37 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
DEDUCE_EXACT, 0, -1);
case OFFSET_TYPE:
/* Unify a pointer to member with a pointer to member function, which
deduces the type of the member as a function type. */
if (TYPE_PTRMEMFUNC_P (arg))
{
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))
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
return 1;
/* Determine the type of the function we are unifying against. */
method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
fntype =
build_function_type (TREE_TYPE (method_type),
TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
/* 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);
return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
}
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),

View File

@ -499,11 +499,10 @@ cp_build_qualified_type_real (tree type,
return build_ptrmemfunc_type (t);
}
/* A reference, function or method type shall not be cv qualified.
/* A reference or method type shall not be cv qualified.
[dcl.ref], [dct.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);
@ -511,10 +510,11 @@ cp_build_qualified_type_real (tree type,
}
/* A restrict-qualified type must be a pointer (or reference)
to object or incomplete type. */
to object or incomplete type, or a function type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE
&& TREE_CODE (type) != FUNCTION_TYPE
&& !POINTER_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;

View File

@ -6383,6 +6383,35 @@ cp_has_mutable_p (tree type)
return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
}
/* Apply the TYPE_QUALS to the new DECL. */
void
cp_apply_type_quals_to_decl (int type_quals, tree decl)
{
tree type = TREE_TYPE (decl);
if (type == error_mark_node)
return;
if (TREE_CODE (type) == FUNCTION_TYPE
&& type_quals != TYPE_UNQUALIFIED)
{
/* This was an error in C++98 (cv-qualifiers cannot be added to
a function type), but DR 295 makes the code well-formed by
dropping the extra qualifiers. */
if (pedantic)
{
tree bad_type = build_qualified_type (type, type_quals);
pedwarn ("ignoring %qV qualifiers added to function type %qT",
bad_type, type);
}
TREE_TYPE (decl) = TYPE_MAIN_VARIANT (type);
return;
}
c_apply_type_quals_to_decl (type_quals, decl);
}
/* Subroutine of casts_away_constness. Make T1 and T2 point at
exemplar types such that casting T1 to T2 is casting away constness
if and only if there is no implicit conversion from T1 to T2. */