2002-01-02 Nathan Sidwell <nathan@codesourcery.com>
+ PR c++/3716
+ * pt.c (tsubst_aggr_type): Move pmf handling into tsubst.
+ (tsubst, case POINTER_TYPE): Handle pmfs here.
+ (tsubst, case OFFSET_TYPE): Check it is not an offset to
+ reference. If it is offset to FUNCTION_TYPE, create a METHOD_TYPE.
+
+2002-01-02 Nathan Sidwell <nathan@codesourcery.com>
+
PR c++/35
* cp-tree.h (DECL_LANG_FLAG_0): Used for PARM_DECL too.
(DECL_TEMPLATE_PARM_P): A PARM_DECL might be one too.
{
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
- {
- tree r = build_ptrmemfunc_type
- (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl));
- return cp_build_qualified_type_real (r, TYPE_QUALS (t),
- complain);
- }
+ return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl);
/* else fall through */
case ENUMERAL_TYPE:
/* The TYPE_CONTEXT is not used for function/method types. */
my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
- /* Substitue the return type. */
+ /* Substitute the return type. */
return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (return_type == error_mark_node)
return error_mark_node;
{
enum tree_code code;
- if (type == TREE_TYPE (t))
+ if (type == TREE_TYPE (t) && TREE_CODE (type) != METHOD_TYPE)
return t;
code = TREE_CODE (t);
return error_mark_node;
}
else if (code == POINTER_TYPE)
- r = build_pointer_type (type);
+ {
+ r = build_pointer_type (type);
+ if (TREE_CODE (type) == METHOD_TYPE)
+ r = build_ptrmemfunc_type (r);
+ }
else
r = build_reference_type (type);
r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
r);
return error_mark_node;
}
- return build_offset_type (r, type);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ if (complain)
+ error ("creating pointer to member reference type `%T'", type);
+
+ return error_mark_node;
+ }
+ my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
+ 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::*);
+
+ */
+ return build_cplus_method_type (TYPE_MAIN_VARIANT (r),
+ TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
+ else
+ return build_offset_type (r, type);
}
case FUNCTION_TYPE:
case METHOD_TYPE:
--- /dev/null
+// { dg-do compile }
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 31 Dec 2001 <nathan@codesourcery.com>
+
+// PR 3716 tsubsting a pointer to member function did not create a
+// pointer to member function.
+
+template <class C, class T, T C::*M>
+struct Closure
+{
+ T operator() (C & c) const { return (c.*M); }
+};
+
+template <class C, class T, T (C::* M)()>
+struct Closure<C, T (), M>
+{
+ T operator()(C & c) const { return (c.*M)(); }
+};
+
+struct A
+{
+ int get();
+};
+
+static Closure<A, int (), & A::get> get_closure;
+
+
+void Foo ()
+{
+ A a;
+ get_closure (a);
+}