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:
parent
89e4aa8109
commit
9804209d32
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
59
gcc/cp/pt.c
59
gcc/cp/pt.c
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user