aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@cs.indiana.edu>2005-02-21 23:12:27 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2005-02-21 23:12:27 +0000
commit9804209d324be049840389053e370d5a1ce51550 (patch)
tree04879cd2510172e1979dedf06e8a47fcc01ae72a
parent89e4aa8109752fdf412a763afcb721acca852e96 (diff)
downloadgcc-9804209d324be049840389053e370d5a1ce51550.zip
gcc-9804209d324be049840389053e370d5a1ce51550.tar.gz
gcc-9804209d324be049840389053e370d5a1ce51550.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog28
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c55
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/pt.c59
-rw-r--r--gcc/cp/tree.c6
-rw-r--r--gcc/cp/typeck.c29
8 files changed, 155 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e190787..ae75f8f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bd5d0ec..d99ae7f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2f6b98f..1613488 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 113386a..8243cb1 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ec332f2..86ea7aa 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7025def..0d83bc1 100644
--- a/gcc/cp/pt.c
+++ b/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),
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8a264d7..321ba4b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e0dc1eb..4a6ded4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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. */