OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Jan 2002 13:55:23 +0000 (13:55 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Jan 2002 13:55:23 +0000 (13:55 +0000)
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.
testsuite:
* g++.dg/template/ptrmem1.C: New test.
* g++.dg/template/ptrmem2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@48471 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/ptrmem1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/ptrmem2.C [new file with mode: 0644]

index 4751ae9..c259242 100644 (file)
@@ -1,5 +1,13 @@
 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.
index 4f20635..a60cacf 100644 (file)
@@ -5452,12 +5452,7 @@ tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
     {
     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:
@@ -6150,7 +6145,7 @@ tsubst_function_type (t, args, complain, in_decl)
   /* 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;
@@ -6565,7 +6560,7 @@ tsubst (t, args, complain, in_decl)
       {
        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);
@@ -6604,7 +6599,11 @@ tsubst (t, args, complain, in_decl)
            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);
@@ -6632,7 +6631,30 @@ tsubst (t, args, complain, in_decl)
                        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:
index d08a707..cdd244e 100644 (file)
@@ -1,5 +1,8 @@
 2002-01-02  Nathan Sidwell  <nathan@codesourcery.com>
 
+       * g++.dg/template/ptrmem1.C: New test.
+       * g++.dg/template/ptrmem2.C: New test.
+
        * g++.dg/template/ntp.C: New test.
 
        * g++.dg/other/component1.C: New test.
diff --git a/gcc/testsuite/g++.dg/template/ptrmem1.C b/gcc/testsuite/g++.dg/template/ptrmem1.C
new file mode 100644 (file)
index 0000000..ebd6a20
--- /dev/null
@@ -0,0 +1,33 @@
+// { 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);
+}
diff --git a/gcc/testsuite/g++.dg/template/ptrmem2.C b/gcc/testsuite/g++.dg/template/ptrmem2.C
new file mode 100644 (file)
index 0000000..23a4ad9
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile }
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 31 Dec 2001 <nathan@codesourcery.com>
+
+// We'd tsubst a pointer to member reference
+
+struct A {};
+
+template <typename T> T A::* Foo ();
+
+void Baz ()
+{
+  Foo <int &> (); // { dg-error "no matching function" "" }
+}